diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..fd991dc --- /dev/null +++ b/.gitattributes @@ -0,0 +1,13 @@ +SECURITY.md linguist-generated=true +dependencies.md linguist-generated=true +doc/changes/changelog.md linguist-generated=true +pk_generated_parent.pom linguist-generated=true +.github/workflows/broken_links_checker.yml linguist-generated=true +.github/workflows/ci-build.yml linguist-generated=true +.github/workflows/ci-build-next-java.yml linguist-generated=true +.github/workflows/dependencies_check.yml linguist-generated=true +.github/workflows/dependencies_update.yml linguist-generated=true +.github/workflows/release.yml linguist-generated=true + +.settings/org.eclipse.jdt.core.prefs linguist-generated=true +.settings/org.eclipse.jdt.ui.prefs linguist-generated=true diff --git a/.github/workflows/broken_links_checker.yml b/.github/workflows/broken_links_checker.yml new file mode 100644 index 0000000..09e4bac --- /dev/null +++ b/.github/workflows/broken_links_checker.yml @@ -0,0 +1,44 @@ +# This file was generated by Project Keeper. +name: Broken Links Checker +on: + schedule: + - { + cron: 0 5 * * 0 + } + workflow_dispatch: null +jobs: + linkChecker: + runs-on: ubuntu-latest + permissions: { + contents: read + } + defaults: + run: { + shell: bash + } + concurrency: { + group: '${{ github.workflow }}-${{ github.ref }}', + cancel-in-progress: true + } + steps: + - { + id: checkout, + uses: actions/checkout@v4 + } + - id: configure-broken-links-checker + name: Configure broken links checker + run: | + mkdir -p ./target + echo '{"aliveStatusCodes": [429, 200], "ignorePatterns": [' \ + '{"pattern": "^https?://(www|dev).mysql.com/"},' \ + '{"pattern": "^https?://(www.)?opensource.org"}' \ + '{"pattern": "^https?://(www.)?eclipse.org"}' \ + '{"pattern": "^https?://projects.eclipse.org"}' \ + ']}' > ./target/broken_links_checker.json + - id: run-broken-links-checker + uses: gaurav-nelson/github-action-markdown-link-check@v1 + with: { + use-quiet-mode: yes, + use-verbose-mode: yes, + config-file: ./target/broken_links_checker.json + } diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml new file mode 100644 index 0000000..63f3e50 --- /dev/null +++ b/.github/workflows/ci-build.yml @@ -0,0 +1,231 @@ +# This file was generated by Project Keeper. +name: CI Build +on: + push: + branches: [ + main + ] + + pull_request: + types: [ + opened, + synchronize, + reopened, + ready_for_review + ] + +jobs: + matrix-build: + runs-on: ubuntu-24.04 + defaults: + run: { + shell: bash + } + permissions: { + contents: read + } + concurrency: { + group: '${{ github.workflow }}-${{ github.ref }}-${{ matrix.exasol_db_version }}', + cancel-in-progress: true + } + strategy: + fail-fast: false + matrix: + exasol_db_version: [ + 8.34.0 + ] + + env: { + DEFAULT_EXASOL_DB_VERSION: 8.34.0 + } + steps: + - name: Free Disk Space + id: free-disk-space + if: ${{ false }} + run: | + sudo rm -rf /usr/local/lib/android + sudo rm -rf /usr/share/dotnet + - name: Checkout the repository + id: checkout + uses: actions/checkout@v4 + with: { + fetch-depth: 0 + } + - name: Set up JDKs + id: setup-java + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: |- + 11 + 17 + cache: maven + - name: Cache SonarCloud packages + id: cache-sonar + uses: actions/cache@v4 + with: { + path: ~/.sonar/cache, + key: '${{ runner.os }}-sonar', + restore-keys: '${{ runner.os }}-sonar' + } + - { + name: Enable testcontainer reuse, + id: enable-testcontainer-reuse, + run: echo 'testcontainers.reuse.enable=true' > "$HOME/.testcontainers.properties" + } + - { + name: Fix VM Crash in UDFs, + id: fix-vm-crash, + run: sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 + } + - name: Run tests and build with Maven + id: build-pk-verify + run: | + mvn --batch-mode clean verify \ + -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn \ + -DtrimStackTrace=false \ + -Dcom.exasol.dockerdb.image=${{ matrix.exasol_db_version }} + env: { + EXASOL_DB_VERSION: '${{ matrix.exasol_db_version }}' + } + - name: Sonar analysis + id: sonar-analysis + if: ${{ env.SONAR_TOKEN != null && matrix.exasol_db_version == env.DEFAULT_EXASOL_DB_VERSION }} + run: | + mvn --batch-mode org.sonarsource.scanner.maven:sonar-maven-plugin:sonar \ + -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn \ + -DtrimStackTrace=false \ + -Dsonar.token=$SONAR_TOKEN + env: { + GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}', + SONAR_TOKEN: '${{ secrets.SONAR_TOKEN }}' + } + - name: Verify Release Artifacts + id: verify-release-artifacts + run: "print_message() {\n local -r message=$1\n echo \"$message\"\n echo \"$message\" >> \"$GITHUB_STEP_SUMMARY\"\n}\n\nprint_message \"### Release Artifacts\"\n\nIFS=$'\\n' artifacts_array=($ARTIFACTS)\nmissing_files=()\nfor file in \"${artifacts_array[@]}\";\ndo \n echo \"Checking if file $file exists...\"\n if ! [[ -f \"$file\" ]]; then\n print_message \"* ⚠️ \\`$file\\` does not exist ⚠️\"\n echo \"Content of directory $(dirname \"$file\"):\"\n ls \"$(dirname \"$file\")\"\n missing_files+=(\"$file\")\n else\n print_message \"* \\`$file\\` ✅\" \n fi\ndone\nprint_message \"\"\nnumber_of_missing_files=${#missing_files[@]}\nif [[ $number_of_missing_files -gt 0 ]]; then\n print_message \"⚠️ $number_of_missing_files release artifact(s) missing ⚠️\"\n exit 1\nfi\n" + env: { + ARTIFACTS: '${{ steps.build-pk-verify.outputs.release-artifacts }}' + } + - name: Upload artifacts + id: upload-artifacts + uses: actions/upload-artifact@v4 + with: { + name: 'artifacts-exasol-${{ matrix.exasol_db_version }}', + path: '${{ steps.build-pk-verify.outputs.release-artifacts }}', + retention-days: 5 + } + - name: Configure broken links checker + id: configure-link-check + run: | + mkdir -p ./target + echo '{"aliveStatusCodes": [429, 200], "ignorePatterns": [' \ + '{"pattern": "^https?://(www|dev).mysql.com/"},' \ + '{"pattern": "^https?://(www.)?opensource.org"}' \ + '{"pattern": "^https?://(www.)?eclipse.org"}' \ + '{"pattern": "^https?://projects.eclipse.org"}' \ + ']}' > ./target/broken_links_checker.json + - uses: gaurav-nelson/github-action-markdown-link-check@v1 + id: run-link-check + with: { + use-quiet-mode: yes, + use-verbose-mode: yes, + config-file: ./target/broken_links_checker.json + } + next-java-compatibility: + runs-on: ubuntu-latest + defaults: + run: { + shell: bash + } + permissions: { + contents: read + } + concurrency: { + group: '${{ github.workflow }}-next-java-${{ github.ref }}', + cancel-in-progress: true + } + steps: + - name: Checkout the repository + id: checkout + uses: actions/checkout@v4 + with: { + fetch-depth: 0 + } + - name: Set up JDK 17 + id: setup-java + uses: actions/setup-java@v4 + with: { + distribution: temurin, + java-version: '17', + cache: maven + } + - { + name: Run tests and build with Maven 17, + id: build-next-java, + run: mvn --batch-mode clean package -DtrimStackTrace=false -Djava.version=17 + } + build: + needs: [ + matrix-build, + next-java-compatibility + ] + runs-on: ubuntu-latest + defaults: + run: { + shell: bash + } + permissions: { + contents: read, + issues: read + } + outputs: { + release-required: '${{ steps.check-release.outputs.release-required }}' + } + steps: + - name: Checkout the repository + id: checkout + uses: actions/checkout@v4 + with: { + fetch-depth: 0 + } + - name: Set up JDKs + id: setup-java + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: |- + 11 + 17 + cache: maven + - name: Check if release is needed + id: check-release + if: ${{ github.ref == 'refs/heads/main' }} + run: | + if mvn --batch-mode com.exasol:project-keeper-maven-plugin:verify-release --projects .; then + echo "### ✅ Release preconditions met, start release" >> "$GITHUB_STEP_SUMMARY" + echo "release-required=true" >> "$GITHUB_OUTPUT" + else + echo "### 🛑 Not all release preconditions met, skipping release" >> "$GITHUB_STEP_SUMMARY" + echo "See log output for details." >> "$GITHUB_STEP_SUMMARY" + echo "release-required=false" >> "$GITHUB_OUTPUT" + fi + env: { + GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}' + } + start_release: + needs: build + if: ${{ github.ref == 'refs/heads/main' && needs.build.outputs.release-required == 'true' }} + concurrency: { + cancel-in-progress: false, + group: release + } + secrets: inherit + permissions: { + contents: write, + actions: read, + issues: read + } + uses: ./.github/workflows/release.yml + with: { + started-from-ci: true + } diff --git a/.github/workflows/dependencies_check.yml b/.github/workflows/dependencies_check.yml new file mode 100644 index 0000000..0832e80 --- /dev/null +++ b/.github/workflows/dependencies_check.yml @@ -0,0 +1,80 @@ +# This file was generated by Project Keeper. +name: Report Security Issues +on: + workflow_dispatch: null + schedule: + - { + cron: 0 2 * * * + } +jobs: + report_security_issues: + runs-on: ubuntu-latest + defaults: + run: { + shell: bash + } + permissions: { + contents: read, + issues: write + } + outputs: { + created-issues: '${{ steps.security-issues.outputs.created-issues }}' + } + concurrency: { + group: '${{ github.workflow }}-report_security_issues', + cancel-in-progress: true + } + steps: + - { + name: Checkout, + id: checkout, + uses: actions/checkout@v4 + } + - name: Set up JDKs + id: setup-jdks + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: |- + 11 + 17 + cache: maven + - name: Generate ossindex report + id: ossindex-report + run: | + mvn --batch-mode org.sonatype.ossindex.maven:ossindex-maven-plugin:audit \ + org.sonatype.ossindex.maven:ossindex-maven-plugin:audit-aggregate \ + -Dossindex.reportFile=$(pwd)/ossindex-report.json \ + -Dossindex.fail=false + - name: Create GitHub Issues + id: create-security-issues + uses: exasol/python-toolbox/.github/actions/security-issues@1.1.0 + with: { + format: maven, + command: cat ossindex-report.json, + github-token: '${{ secrets.GITHUB_TOKEN }}' + } + - name: Output security issues (Debugging) + id: debug-print-security-issues + run: | + echo "$CREATED_ISSUES" > test.jsonl + cat test.jsonl + env: { + CREATED_ISSUES: '${{ steps.security-issues.outputs.created-issues }}' + } + start_dependency_udpate: + needs: report_security_issues + if: ${{ needs.report_security_issues.outputs.created-issues }} + concurrency: { + group: '${{ github.workflow }}-start_dependency_update', + cancel-in-progress: false + } + secrets: inherit + permissions: { + contents: write, + pull-requests: write + } + uses: ./.github/workflows/dependencies_update.yml + with: { + vulnerability_issues: '${{ needs.report_security_issues.outputs.created-issues }}' + } diff --git a/.github/workflows/dependencies_update.yml b/.github/workflows/dependencies_update.yml new file mode 100644 index 0000000..c901506 --- /dev/null +++ b/.github/workflows/dependencies_update.yml @@ -0,0 +1,176 @@ +# This file was generated by Project Keeper. +name: Update dependencies +on: + workflow_call: + inputs: + vulnerability_issues: { + description: GitHub issues for vulnerable dependencies as JSONL, + required: true, + type: string + } + workflow_dispatch: null +jobs: + update_dependencies: + runs-on: ubuntu-latest + defaults: + run: { + shell: bash + } + permissions: { + contents: write, + pull-requests: write + } + concurrency: { + group: '${{ github.workflow }}', + cancel-in-progress: false + } + steps: + - uses: actions/checkout@v4 + id: checkout + with: { + fetch-depth: 0 + } + - name: Set up JDKs + id: setup-jdks + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: |- + 11 + 17 + cache: maven + - name: Print issues + id: debug-print-issues + run: | + echo "Issues from Action input: $ISSUES" + env: { + ISSUES: '${{ inputs.vulnerability_issues }}' + } + - name: Fail if not running on a branch + id: check-branch + if: ${{ !startsWith(github.ref, 'refs/heads/') }} + uses: actions/github-script@v7 + with: + script: | + core.setFailed('Not running on a branch, github.ref is ${{ github.ref }}. Please start this workflow only on main or a branch') + - name: Update dependencies + id: update-dependencies + run: | + mvn --batch-mode com.exasol:project-keeper-maven-plugin:update-dependencies --projects . \ + -Dproject-keeper:vulnerabilities="$CREATED_ISSUES" + env: { + CREATED_ISSUES: '${{ inputs.vulnerability_issues }}' + } + - name: Generate Pull Request comment + id: pr-comment + run: | + echo 'comment<> "$GITHUB_OUTPUT" + echo 'This Pull Request was created by [`dependencies_update.yml`](https://github.com/exasol/project-keeper/blob/main/project-keeper/src/main/resources/templates/.github/workflows/dependencies_update.yml) workflow.' >> "$GITHUB_OUTPUT" + if [ -n "$CREATED_ISSUES" ]; then + echo 'It updates dependencies to fix the following vulnerabilities:' >> "$GITHUB_OUTPUT" + echo $CREATED_ISSUES | jq --raw-output '. | "* Closes " + .issue_url + " (" + .cve + ")"' >> "$GITHUB_OUTPUT" + else + echo 'It updates dependencies.' >> "$GITHUB_OUTPUT" + fi + echo >> "$GITHUB_OUTPUT" + echo '# ⚠️ Notes ⚠️' >> "$GITHUB_OUTPUT" + echo '## Run PK fix manually' >> "$GITHUB_OUTPUT" + echo 'Due to restrictions workflow `dependencies_update.yml` cannot update other workflows, see https://github.com/exasol/project-keeper/issues/578 for details.' >> "$GITHUB_OUTPUT" + echo 'Please checkout this PR locally and run `mvn com.exasol:project-keeper-maven-plugin:fix --projects .`' >> "$GITHUB_OUTPUT" + echo '## This PR does not trigger CI workflows' >> "$GITHUB_OUTPUT" + echo 'Please click the **Close pull request** button and then **Reopen pull request** to trigger running checks.' >> "$GITHUB_OUTPUT" + echo 'See https://github.com/exasol/project-keeper/issues/534 for details.' >> "$GITHUB_OUTPUT" + echo 'EOF' >> "$GITHUB_OUTPUT" + + cat "$GITHUB_OUTPUT" + env: { + CREATED_ISSUES: '${{ inputs.vulnerability_issues }}' + } + - name: Generate Pull Request Title + id: pr-title + run: | + if [ -n "$CREATED_ISSUES" ]; then + echo "Security issues are available" + echo "title=🔐 Update dependencies to fix vulnerabilities" >> "$GITHUB_OUTPUT" + else + echo "Security issues are not available" + echo "title=Update dependencies" >> "$GITHUB_OUTPUT" + fi + + cat "$GITHUB_OUTPUT" + env: { + CREATED_ISSUES: '${{ inputs.vulnerability_issues }}' + } + - name: Configure git + id: configure-git + run: | + git config --global user.email "opensource@exasol.com" + git config --global user.name "Automatic Dependency Updater" + - name: Create branch + id: create-branch + if: ${{ github.ref == 'refs/heads/main' }} + run: | + branch_name="dependency-update/$(date "+%Y%m%d%H%M%S")" + echo "Creating branch $branch_name" + git checkout -b "$branch_name" + - name: Commit changes & push + id: publish-branch + if: ${{ startsWith(github.ref, 'refs/heads/' ) }} + run: | + branch_name=$(git rev-parse --abbrev-ref HEAD) + echo "Current branch: $branch_name" + echo "git diff --stat" + git diff --stat + echo "git diff --numstat" + git diff --numstat + echo "git diff --name-status" + git diff --name-status + echo "Adding untracked files:" + git add . --verbose --all + echo "Committing changes..." + git commit --message "$TITLE" + echo "Pushing branch $branch_name..." + git push --set-upstream origin "$branch_name" + echo "Done." + env: { + TITLE: '${{ steps.pr-title.outputs.title }}' + } + - name: Create pull request + id: create-pr + if: ${{ github.ref == 'refs/heads/main' }} + run: | + pr_url=$(gh pr create --base main --title "$TITLE" --body "$COMMENT") + echo "Created Pull Request: $pr_url" + echo "pr_url=$pr_url" >> "$GITHUB_OUTPUT" + env: { + COMMENT: '${{ steps.pr-comment.outputs.comment }}', + TITLE: '${{ steps.pr-title.outputs.title }}', + GH_TOKEN: '${{ github.token }}' + } + - name: Report failure Status to Slack channel + id: report-failure-slack + if: ${{ always() }} + uses: ravsamhq/notify-slack-action@v2 + with: { + status: '${{ job.status }}', + token: '${{ secrets.GITHUB_TOKEN }}', + notification_title: 'Dependency check in {repo} has {status_message}', + message_format: '{emoji} *{workflow}* {status_message} in <{repo_url}|{repo}>', + notify_when: 'failure,cancelled,warnings' + } + env: { + SLACK_WEBHOOK_URL: '${{ secrets.INTEGRATION_TEAM_SLACK_NOTIFICATION_WEBHOOK }}' + } + - name: Report new Pull Request to Slack channel + id: report-pr-slack + if: ${{ steps.create-pr.outputs.pr_url }} + uses: ravsamhq/notify-slack-action@v2 + with: { + status: '${{ job.status }}', + token: '${{ secrets.GITHUB_TOKEN }}', + notification_title: 'Dependency update for {repo} created a Pull Request', + message_format: '{workflow} created Pull Request ${{ steps.create-pr.outputs.pr_url }}' + } + env: { + SLACK_WEBHOOK_URL: '${{ secrets.INTEGRATION_TEAM_SLACK_NOTIFICATION_WEBHOOK }}' + } diff --git a/.github/workflows/github_release.yml b/.github/workflows/github_release.yml deleted file mode 100644 index 3afc904..0000000 --- a/.github/workflows/github_release.yml +++ /dev/null @@ -1,36 +0,0 @@ -name: GitHub Release - -on: - workflow_dispatch: - inputs: - upload_url: - description: 'Upload URL' - required: true - asset_name: - description: 'Asset file name' - required: true - asset_path: - description: 'Asset file path' - required: true - -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Set up JDK 11 - uses: actions/setup-java@v1 - with: - java-version: 11 - - name: Build with Maven - run: mvn -B clean package --file pom.xml - - - name: Upload Release Asset - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ github.event.inputs.upload_url }} - asset_path: ${{ github.event.inputs.asset_path }} - asset_name: ${{ github.event.inputs.asset_name }} - asset_content_type: application/java-archive \ No newline at end of file diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml deleted file mode 100644 index 2a4f4d9..0000000 --- a/.github/workflows/maven.yml +++ /dev/null @@ -1,21 +0,0 @@ -# This workflow will build a Java project with Maven -# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven - -name: Dependencies Check - -on: - schedule: - - cron: "0 2 * * *" - -jobs: - build: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - name: Set up JDK 11 - uses: actions/setup-java@v1 - with: - java-version: 11 - - name: Checking dependencies for vulnerabilities - run: mvn org.sonatype.ossindex.maven:ossindex-maven-plugin:audit -f pom.xml \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..e4682a3 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,219 @@ +# This file was generated by Project Keeper. +name: Release +on: + workflow_call: + inputs: + started-from-ci: { + description: 'Marks this release as started from CI, skipping precondition check', + type: boolean, + required: true, + default: false + } + workflow_dispatch: + inputs: + skip-maven-central: { + description: Skip deployment to Maven Central, + required: true, + type: boolean, + default: false + } + skip-github-release: { + description: Skip creating the GitHub release, + required: true, + type: boolean, + default: false + } +jobs: + release: + runs-on: ubuntu-latest + defaults: + run: { + shell: bash + } + concurrency: { + group: '${{ github.workflow }}', + cancel-in-progress: false + } + permissions: { + contents: write, + actions: read, + issues: read + } + steps: + - name: Checkout the repository + id: checkout + uses: actions/checkout@v4 + with: { + fetch-depth: 0 + } + - name: Set up Maven Central Repository + id: configure-maven-central-credentials + if: ${{ true }} + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: |- + 11 + 17 + cache: maven + server-id: ossrh + server-username: MAVEN_USERNAME + server-password: MAVEN_PASSWORD + gpg-private-key: ${{ secrets.OSSRH_GPG_SECRET_KEY }} + gpg-passphrase: MAVEN_GPG_PASSPHRASE + - name: Set up JDKs + id: setup-jdks + if: ${{ ! true }} + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: |- + 11 + 17 + cache: maven + - name: Fail if not running on main branch + id: check-main-branch + if: ${{ github.ref != 'refs/heads/main' }} + uses: actions/github-script@v7 + with: + script: | + core.setFailed('Not running on main branch, github.ref is ${{ github.ref }}. Please start this workflow only on main') + - name: Check CI build of this commit succeeded + id: check-ci-build-status + if: ${{ ! inputs.started-from-ci }} + run: | + echo "Commit SHA: $COMMIT_SHA" + gh run list --workflow ci-build.yml --branch main --event push --commit $COMMIT_SHA + ci_build_status=$(gh run list --workflow ci-build.yml --branch main --event push --commit $COMMIT_SHA --json conclusion --template '{{range .}}{{.conclusion}}{{"\n"}}{{end}}') + echo "CI build status at commit $COMMIT_SHA was '$ci_build_status'" + if [[ "$ci_build_status" != "success" ]]; then + gh run list --workflow ci-build.yml --commit $COMMIT_SHA >> $GITHUB_STEP_SUMMARY + echo "Status of CI build for commit $COMMIT_SHA was '$ci_build_status', expected 'success'" >> $GITHUB_STEP_SUMMARY + cat $GITHUB_STEP_SUMMARY + exit 1 + fi + env: { + COMMIT_SHA: '${{ github.sha }}', + GH_TOKEN: '${{ github.token }}' + } + - name: Verify release preconditions + id: verify-release + run: | + mvn --batch-mode com.exasol:project-keeper-maven-plugin:verify-release --projects . + echo "$GITHUB_OUTPUT" + env: { + GITHUB_TOKEN: '${{ github.token }}' + } + - { + name: Build project, + id: build, + run: mvn --batch-mode -DskipTests clean verify + } + - { + name: List secret GPG keys, + id: list-secret-gpg-keys, + if: '${{ true && (! inputs.skip-maven-central) }}', + run: gpg --list-secret-keys + } + - name: Publish to Central Repository + id: deploy-maven-central + if: ${{ true && (! inputs.skip-maven-central) }} + run: | + echo "#### Maven Central Release" >> "$GITHUB_STEP_SUMMARY" + mvn --batch-mode -Dgpg.skip=false -DskipTests deploy + echo "Published to Maven Central ✅" >> "$GITHUB_STEP_SUMMARY" + env: { + MAVEN_USERNAME: '${{ secrets.OSSRH_USERNAME }}', + MAVEN_PASSWORD: '${{ secrets.OSSRH_PASSWORD }}', + MAVEN_GPG_PASSPHRASE: '${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }}' + } + - name: Calculate Artifact Checksums + id: artifact-checksum + if: ${{ ! inputs.skip-github-release }} + run: | + echo "Calculating sha256 checksum for artifact files" + echo "artifacts<> "$GITHUB_OUTPUT" + IFS=$'\n' artifacts_array=($ARTIFACTS) + for file in "${artifacts_array[@]}"; + do + full_path=$(realpath "$file") + echo "Calculate sha256sum for file '$full_path'" + file_dir="$(dirname "$full_path")" + file_name=$(basename "$full_path") + pushd "$file_dir" + checksum_file_name="${file_name}.sha256" + sha256sum "$file_name" > "$checksum_file_name" + echo "$full_path" >> "$GITHUB_OUTPUT" + echo "${file_dir}/$checksum_file_name" >> "$GITHUB_OUTPUT" + popd + done + echo "EOF" >> "$GITHUB_OUTPUT" + echo "Full artifact file list" + cat "$GITHUB_OUTPUT" + env: { + ARTIFACTS: '${{ steps.verify-release.outputs.release-artifacts }}' + } + - name: Create GitHub Release + id: create-github-release + if: ${{ ! inputs.skip-github-release }} + run: | + echo "### GitHub Release" >> "$GITHUB_STEP_SUMMARY" + IFS=$'\n' artifacts_array=($ARTIFACTS) + echo "#### Attaching Release Artifacts" >> "$GITHUB_STEP_SUMMARY" + for file in "${artifacts_array[@]}"; + do + echo "Attaching artifact '$file'" + echo "* \`$file\`" >> "$GITHUB_STEP_SUMMARY" + done + echo "" >> "$GITHUB_STEP_SUMMARY" + release_url=$(gh release create --latest --title "$TITLE" --notes "$NOTES" --target main $TAG "${artifacts_array[@]}") + echo "Created release $TAG with title '$TITLE' at $release_url ✅" >> "$GITHUB_STEP_SUMMARY" + echo "release-url=$release_url" >> "$GITHUB_OUTPUT" + + # [impl->dsn~release-workflow.create-golang-tags~1] + echo "#### Creating Additional Tags" >> "$GITHUB_STEP_SUMMARY" + IFS=$'\n' tags_array=($ADDITIONAL_TAGS) + for tag in "${tags_array[@]}"; + do + echo "Creating tag '$tag'" + git tag "$tag" + git push origin "$tag" + echo "* \`$tag\`" >> "$GITHUB_STEP_SUMMARY" + done + + git fetch --tags origin + env: { + GH_TOKEN: '${{ github.token }}', + TAG: '${{ steps.verify-release.outputs.release-tag }}', + ADDITIONAL_TAGS: '${{ steps.verify-release.outputs.additional-release-tags }}', + NOTES: '${{ steps.verify-release.outputs.release-notes }}', + TITLE: '${{ steps.verify-release.outputs.release-title }}', + ARTIFACTS: '${{ steps.artifact-checksum.outputs.artifacts }}' + } + - name: Report failure Status to Slack channel + id: report-failure-status-slack + if: ${{ always() }} + uses: ravsamhq/notify-slack-action@v2 + with: { + status: '${{ job.status }}', + token: '${{ github.token }}', + notification_title: 'Release build in {repo} has {status_message}', + message_format: '{emoji} *{workflow}* {status_message} in <{repo_url}|{repo}>', + notify_when: 'failure,cancelled,warnings,skipped' + } + env: { + SLACK_WEBHOOK_URL: '${{ secrets.INTEGRATION_TEAM_SLACK_NOTIFICATION_WEBHOOK }}' + } + - name: Report new release to Slack channel + id: report-new-release-slack + if: ${{ steps.create-github-release.outputs.release-url }} + uses: ravsamhq/notify-slack-action@v2 + with: { + status: '${{ job.status }}', + token: '${{ github.token }}', + notification_title: 'Release build for {repo} created a new release', + message_format: '{workflow} created release ${{ steps.create-github-release.outputs.release-url }}' + } + env: { + SLACK_WEBHOOK_URL: '${{ secrets.INTEGRATION_TEAM_SLACK_NOTIFICATION_WEBHOOK }}' + } diff --git a/.gitignore b/.gitignore index c250eb4..ea71e1a 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,9 @@ pom.xml.versionsBackup # Eclipse and Maven .classpath .project +/.settings/org.eclipse.jdt.apt.core.prefs +/.settings/org.eclipse.core.resources.prefs +/.settings/org.eclipse.m2e.core.prefs # .settings : we need Eclipse settings for code formatter and clean-up rules target .cache @@ -24,3 +27,13 @@ Scripts **/*.log .directory venv/ + +~* +*.lock +*.bak +*.orig +*.old +*.md.html +*.flattened-pom.xml +/.apt_generated/ +/.apt_generated_tests/ diff --git a/.project-keeper.yml b/.project-keeper.yml new file mode 100644 index 0000000..bab3287 --- /dev/null +++ b/.project-keeper.yml @@ -0,0 +1,22 @@ +sources: + - type: maven + path: pom.xml + modules: + - maven_central + - integration_tests +build: + runnerOs: ubuntu-24.04 + exasolDbVersions: + - "8.34.0" + # UDFs in Exasol 7.1 with Ubuntu 20.04 will be fixed in the next Docker-DB release + # - "7.1.30" + workflows: + - name: ci-build.yml + stepCustomizations: + - action: INSERT_AFTER + job: matrix-build + stepId: enable-testcontainer-reuse + content: + name: Fix VM Crash in UDFs + id: fix-vm-crash + run: sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs index e3a8580..7644ed3 100644 --- a/.settings/org.eclipse.jdt.core.prefs +++ b/.settings/org.eclipse.jdt.core.prefs @@ -1,15 +1,19 @@ eclipse.preferences.version=1 +org.eclipse.jdt.core.builder.annotationPath.allLocations=disabled org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull org.eclipse.jdt.core.compiler.annotation.nonnull.secondary= org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary= +org.eclipse.jdt.core.compiler.annotation.notowning=org.eclipse.jdt.annotation.NotOwning org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable org.eclipse.jdt.core.compiler.annotation.nullable.secondary= org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled +org.eclipse.jdt.core.compiler.annotation.owning=org.eclipse.jdt.annotation.Owning +org.eclipse.jdt.core.compiler.annotation.resourceanalysis=disabled org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate +org.eclipse.jdt.core.compiler.codegen.methodParameters=generate org.eclipse.jdt.core.compiler.codegen.targetPlatform=11 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve org.eclipse.jdt.core.compiler.compliance=11 @@ -17,6 +21,7 @@ org.eclipse.jdt.core.compiler.debug.lineNumber=generate org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate org.eclipse.jdt.core.compiler.problem.APILeak=warning +org.eclipse.jdt.core.compiler.problem.annotatedTypeArgumentToUnannotated=info org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.autoboxing=ignore @@ -39,8 +44,10 @@ org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompatibleOwningContract=warning org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore +org.eclipse.jdt.core.compiler.problem.insufficientResourceAnalysis=warning org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore @@ -56,15 +63,15 @@ org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error +org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=warning org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning +org.eclipse.jdt.core.compiler.problem.nullSpecViolation=warning +org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=ignore org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore -org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore +org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning @@ -78,7 +85,8 @@ org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled +org.eclipse.jdt.core.compiler.problem.suppressWarningsNotFullyAnalysed=info +org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=enabled org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning @@ -111,6 +119,7 @@ org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.processAnnotations=disabled org.eclipse.jdt.core.compiler.release=disabled org.eclipse.jdt.core.compiler.source=11 org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false @@ -119,12 +128,20 @@ org.eclipse.jdt.core.formatter.align_type_members_on_columns=false org.eclipse.jdt.core.formatter.align_variable_declarations_on_columns=false org.eclipse.jdt.core.formatter.align_with_spaces=false org.eclipse.jdt.core.formatter.alignment_for_additive_operator=16 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_enum_constant=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_field=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_local_variable=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_method=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_package=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_parameter=0 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_type=49 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_assertion_message=0 org.eclipse.jdt.core.formatter.alignment_for_assignment=0 org.eclipse.jdt.core.formatter.alignment_for_bitwise_operator=16 org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 @@ -142,6 +159,7 @@ org.eclipse.jdt.core.formatter.alignment_for_multiplicative_operator=16 org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references=0 org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_record_components=16 org.eclipse.jdt.core.formatter.alignment_for_relational_operator=0 org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80 org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16 @@ -149,14 +167,18 @@ org.eclipse.jdt.core.formatter.alignment_for_shift_operator=0 org.eclipse.jdt.core.formatter.alignment_for_string_concatenation=16 org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_record_declaration=16 org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_type_annotations=0 org.eclipse.jdt.core.formatter.alignment_for_type_arguments=0 org.eclipse.jdt.core.formatter.alignment_for_type_parameters=0 org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16 org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_last_class_body_declaration=0 org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_abstract_method=1 org.eclipse.jdt.core.formatter.blank_lines_before_field=0 org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 @@ -165,6 +187,7 @@ org.eclipse.jdt.core.formatter.blank_lines_before_method=1 org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 org.eclipse.jdt.core.formatter.blank_lines_before_package=0 org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +org.eclipse.jdt.core.formatter.blank_lines_between_statement_group_in_switch=0 org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line @@ -176,6 +199,8 @@ org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_record_constructor=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_record_declaration=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line org.eclipse.jdt.core.formatter.comment.align_tags_descriptions_grouped=true @@ -193,6 +218,7 @@ org.eclipse.jdt.core.formatter.comment.indent_parameter_description=false org.eclipse.jdt.core.formatter.comment.indent_root_tags=false org.eclipse.jdt.core.formatter.comment.indent_tag_description=false org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_between_different_tags=do not insert org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert org.eclipse.jdt.core.formatter.comment.line_length=120 org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true @@ -208,13 +234,14 @@ org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=fals org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_record_header=true org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true org.eclipse.jdt.core.formatter.indent_empty_lines=false org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true -org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true org.eclipse.jdt.core.formatter.indentation.size=4 org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant=insert org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert @@ -234,6 +261,8 @@ org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=d org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert org.eclipse.jdt.core.formatter.insert_space_after_additive_operator=insert org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_default=insert org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert @@ -263,13 +292,16 @@ org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arg org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_record_components=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_switch_case_expressions=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert org.eclipse.jdt.core.formatter.insert_space_after_logical_operator=insert org.eclipse.jdt.core.formatter.insert_space_after_multiplicative_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_not_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert @@ -286,6 +318,7 @@ org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not ins org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_record_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert @@ -302,6 +335,8 @@ org.eclipse.jdt.core.formatter.insert_space_after_string_concatenation=insert org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_before_additive_operator=insert org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_case=insert +org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_default=insert org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert org.eclipse.jdt.core.formatter.insert_space_before_bitwise_operator=insert @@ -321,6 +356,7 @@ org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not in org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_record_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert @@ -347,7 +383,9 @@ org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_ar org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_record_components=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_switch_case_expressions=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert @@ -365,6 +403,8 @@ org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_ org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_constructor=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_declaration=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert @@ -380,6 +420,7 @@ org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_record_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert @@ -406,7 +447,7 @@ org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constan org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert org.eclipse.jdt.core.formatter.join_lines_in_comments=true -org.eclipse.jdt.core.formatter.join_wrapped_lines=true +org.eclipse.jdt.core.formatter.join_wrapped_lines=false org.eclipse.jdt.core.formatter.keep_annotation_declaration_on_one_line=one_line_never org.eclipse.jdt.core.formatter.keep_anonymous_type_declaration_on_one_line=one_line_never org.eclipse.jdt.core.formatter.keep_code_block_on_one_line=one_line_never @@ -419,6 +460,8 @@ org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false org.eclipse.jdt.core.formatter.keep_lambda_body_block_on_one_line=one_line_never org.eclipse.jdt.core.formatter.keep_loop_body_block_on_one_line=one_line_never org.eclipse.jdt.core.formatter.keep_method_body_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_record_constructor_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_record_declaration_on_one_line=one_line_never org.eclipse.jdt.core.formatter.keep_simple_do_while_body_on_same_line=false org.eclipse.jdt.core.formatter.keep_simple_for_body_on_same_line=false org.eclipse.jdt.core.formatter.keep_simple_getter_setter_on_one_line=false @@ -428,7 +471,12 @@ org.eclipse.jdt.core.formatter.keep_type_declaration_on_one_line=one_line_never org.eclipse.jdt.core.formatter.lineSplit=120 org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false +org.eclipse.jdt.core.formatter.number_of_blank_lines_after_code_block=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_code_block=0 org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_code_block=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_before_code_block=0 org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation=common_lines org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause=common_lines @@ -438,14 +486,17 @@ org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement=commo org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration=common_lines org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration=common_lines org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_record_declaration=common_lines org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement=common_lines org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause=common_lines org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true org.eclipse.jdt.core.formatter.tabulation.char=space org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.text_block_indentation=0 org.eclipse.jdt.core.formatter.use_on_off_tags=false org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=true org.eclipse.jdt.core.formatter.wrap_before_additive_operator=true +org.eclipse.jdt.core.formatter.wrap_before_assertion_message_operator=true org.eclipse.jdt.core.formatter.wrap_before_assignment_operator=false org.eclipse.jdt.core.formatter.wrap_before_bitwise_operator=true org.eclipse.jdt.core.formatter.wrap_before_conditional_operator=true diff --git a/.settings/org.eclipse.jdt.ui.prefs b/.settings/org.eclipse.jdt.ui.prefs index e7e7880..54d02ac 100644 --- a/.settings/org.eclipse.jdt.ui.prefs +++ b/.settings/org.eclipse.jdt.ui.prefs @@ -61,11 +61,12 @@ cleanup_settings_version=2 eclipse.preferences.version=1 editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true formatter_profile=_Exasol -formatter_settings_version=16 +formatter_settings_version=21 org.eclipse.jdt.ui.ignorelowercasenames=true org.eclipse.jdt.ui.importorder=java;javax;org;com; org.eclipse.jdt.ui.ondemandthreshold=3 org.eclipse.jdt.ui.staticondemandthreshold=3 +sp_cleanup.add_all=false sp_cleanup.add_default_serial_version_id=true sp_cleanup.add_generated_serial_version_id=false sp_cleanup.add_missing_annotations=true @@ -75,30 +76,79 @@ sp_cleanup.add_missing_nls_tags=false sp_cleanup.add_missing_override_annotations=true sp_cleanup.add_missing_override_annotations_interface_methods=true sp_cleanup.add_serial_version_id=false +sp_cleanup.also_simplify_lambda=false sp_cleanup.always_use_blocks=true sp_cleanup.always_use_parentheses_in_expressions=true sp_cleanup.always_use_this_for_non_static_field_access=true sp_cleanup.always_use_this_for_non_static_method_access=false +sp_cleanup.array_with_curly=false +sp_cleanup.arrays_fill=false +sp_cleanup.bitwise_conditional_expression=false +sp_cleanup.boolean_literal=false +sp_cleanup.boolean_value_rather_than_comparison=false +sp_cleanup.break_loop=false +sp_cleanup.collection_cloning=false +sp_cleanup.comparing_on_criteria=false +sp_cleanup.comparison_statement=false +sp_cleanup.controlflow_merge=false sp_cleanup.convert_functional_interfaces=true sp_cleanup.convert_to_enhanced_for_loop=true +sp_cleanup.convert_to_enhanced_for_loop_if_loop_var_used=false +sp_cleanup.convert_to_switch_expressions=false sp_cleanup.correct_indentation=true +sp_cleanup.do_while_rather_than_while=false +sp_cleanup.double_negation=false +sp_cleanup.else_if=false +sp_cleanup.embedded_if=false +sp_cleanup.evaluate_nullable=false +sp_cleanup.extract_increment=false sp_cleanup.format_source_code=true sp_cleanup.format_source_code_changes_only=false +sp_cleanup.hash=false +sp_cleanup.if_condition=false sp_cleanup.insert_inferred_type_arguments=false +sp_cleanup.instanceof=false +sp_cleanup.instanceof_keyword=false +sp_cleanup.invert_equals=false +sp_cleanup.join=false +sp_cleanup.lazy_logical_operator=false sp_cleanup.make_local_variable_final=true sp_cleanup.make_parameters_final=true sp_cleanup.make_private_fields_final=true sp_cleanup.make_type_abstract_if_missing_method=false sp_cleanup.make_variable_declarations_final=true +sp_cleanup.map_cloning=false +sp_cleanup.merge_conditional_blocks=false +sp_cleanup.multi_catch=false sp_cleanup.never_use_blocks=false sp_cleanup.never_use_parentheses_in_expressions=false +sp_cleanup.no_string_creation=false +sp_cleanup.no_super=false +sp_cleanup.number_suffix=false +sp_cleanup.objects_equals=false sp_cleanup.on_save_use_additional_actions=true +sp_cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=false +sp_cleanup.operand_factorization=false sp_cleanup.organize_imports=true +sp_cleanup.overridden_assignment=false +sp_cleanup.overridden_assignment_move_decl=false +sp_cleanup.plain_replacement=false +sp_cleanup.precompile_regex=false +sp_cleanup.primitive_comparison=false +sp_cleanup.primitive_parsing=false +sp_cleanup.primitive_rather_than_wrapper=false +sp_cleanup.primitive_serialization=false +sp_cleanup.pull_out_if_from_if_else=false +sp_cleanup.pull_up_assignment=false +sp_cleanup.push_down_negation=false sp_cleanup.qualify_static_field_accesses_with_declaring_class=false sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true sp_cleanup.qualify_static_member_accesses_with_declaring_class=true sp_cleanup.qualify_static_method_accesses_with_declaring_class=false +sp_cleanup.reduce_indentation=false +sp_cleanup.redundant_comparator=false +sp_cleanup.redundant_falling_through_block_end=false sp_cleanup.remove_private_constructors=true sp_cleanup.remove_redundant_modifiers=false sp_cleanup.remove_redundant_semicolons=true @@ -106,22 +156,56 @@ sp_cleanup.remove_redundant_type_arguments=true sp_cleanup.remove_trailing_whitespaces=true sp_cleanup.remove_trailing_whitespaces_all=true sp_cleanup.remove_trailing_whitespaces_ignore_empty=false +sp_cleanup.remove_unnecessary_array_creation=false sp_cleanup.remove_unnecessary_casts=true sp_cleanup.remove_unnecessary_nls_tags=true sp_cleanup.remove_unused_imports=true sp_cleanup.remove_unused_local_variables=false +sp_cleanup.remove_unused_method_parameters=false sp_cleanup.remove_unused_private_fields=true sp_cleanup.remove_unused_private_members=false sp_cleanup.remove_unused_private_methods=true sp_cleanup.remove_unused_private_types=true +sp_cleanup.replace_deprecated_calls=false +sp_cleanup.return_expression=false +sp_cleanup.simplify_lambda_expression_and_method_ref=false +sp_cleanup.single_used_field=false sp_cleanup.sort_members=false sp_cleanup.sort_members_all=false +sp_cleanup.standard_comparison=false +sp_cleanup.static_inner_class=false +sp_cleanup.strictly_equal_or_different=false +sp_cleanup.stringbuffer_to_stringbuilder=false +sp_cleanup.stringbuilder=false +sp_cleanup.stringbuilder_for_local_vars=false +sp_cleanup.stringconcat_stringbuffer_stringbuilder=false +sp_cleanup.stringconcat_to_textblock=false +sp_cleanup.substring=false +sp_cleanup.switch=false +sp_cleanup.system_property=false +sp_cleanup.system_property_boolean=false +sp_cleanup.system_property_file_encoding=false +sp_cleanup.system_property_file_separator=false +sp_cleanup.system_property_line_separator=false +sp_cleanup.system_property_path_separator=false +sp_cleanup.ternary_operator=false +sp_cleanup.try_with_resource=false +sp_cleanup.unlooped_while=false +sp_cleanup.unreachable_block=false sp_cleanup.use_anonymous_class_creation=false +sp_cleanup.use_autoboxing=false sp_cleanup.use_blocks=true sp_cleanup.use_blocks_only_for_return_and_throw=false +sp_cleanup.use_directly_map_method=false sp_cleanup.use_lambda=true sp_cleanup.use_parentheses_in_expressions=true +sp_cleanup.use_string_is_blank=false sp_cleanup.use_this_for_non_static_field_access=true sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=false sp_cleanup.use_this_for_non_static_method_access=false sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true +sp_cleanup.use_unboxing=false +sp_cleanup.use_var=false +sp_cleanup.useless_continue=false +sp_cleanup.useless_return=false +sp_cleanup.valueof_rather_than_instantiation=false diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index f6845a5..0000000 --- a/.travis.yml +++ /dev/null @@ -1,16 +0,0 @@ -language: java -sudo: required -matrix: - include: - - jdk: openjdk11 -addons: - sonarcloud: - organization: exasol - token: - secure: AgZwCb56VbdlHlyTAsRi99yVB/+/inLhki2+mzMWf5BJ8IZhjJNN5zRP+gmjf0sjHwKtL3NdoPeqjMy3Q4+UxhydEd3mbZ8NaIYeQ3ZBE9zBZqBCEG15TfVCL9gSNkXuFfmpdyQt+MdnzkL9/vUKlMajfUuywDj/4FOzCW6PfPrDCvxHEUwkmWYLCTqxnDAGJu6ogb8RrpOqoWSOyUH2hMm+Qm5YKY9+xn+UjfD0kApv868BF1g7Jgz6PYv1hiQMwPjTNlI1ISuom3RXY5QtNSchB7/ZLK3KXpbpwjDNh+AfDFCrrCNiHM24kIp4gwJoyjg4wh/ao3umTalIR3iVErMmz7F/Mbd7ZJHNFC9rqXbgzrj1rySYJ0QemeI7FvTqdRQTaXENlz45sw3YRf4PU/Palpga/RCqwFYxuF5wErSngMOFVvaxjxYUDrNz3aO4v1ZYCOksKM7LhnOPE+sqrZAWBRDU+iKfevoLXUpfWMfedKYVQAqO+tqgolxPSUVmyfzgQC1vqhVrcDbXHFXfE5hJdCUd9YN4PJo98EtUXou4SGp6dpwRn/D9M3nZjOsfpahPFMYYzfaBpIIG6AEN6eGVbE9AA94x/tMKdhlUcEiHBA57YbyvHly8wA8wHoMWFWe7QxE7cP3afi/ognfHRb77/Ay0ggcG1CT9VeCov6A= -script: - - mvn clean org.jacoco:jacoco-maven-plugin:prepare-agent org.jacoco:jacoco-maven-plugin:prepare-agent-integration - verify sonar:sonar -Dsonar.login=${SONAR_TOKEN} -Dsonar.coverage.jacoco.xmlReportPaths=target/site/jacoco/jacoco.xml,target/site/jacoco-it/jacoco.xml,target/site/jacoco-udf/jacoco.xml -cache: - directories: - - "$HOME/.m2" diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..30f0f3f --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,22 @@ +{ + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.organizeImports": "explicit", + "source.generate.finalModifiers": "explicit", + "source.fixAll": "explicit" + }, + "java.codeGeneration.useBlocks": true, + "java.saveActions.organizeImports": true, + "java.sources.organizeImports.starThreshold": 3, + "java.sources.organizeImports.staticStarThreshold": 3, + "java.test.config": { + "vmArgs": [ + "-Djava.util.logging.config.file=src/test/resources/logging.properties", + "-Dcom.exasol.dockerdb.image=7.1.30" + ] + }, + "sonarlint.connectedMode.project": { + "connectionId": "exasol", + "projectKey": "com.exasol:udf-debugging-java" + } +} diff --git a/NOTICE b/NOTICE deleted file mode 100644 index ea37de8..0000000 --- a/NOTICE +++ /dev/null @@ -1,40 +0,0 @@ -This project has the following dependencies: - Apache Commons Compress under Apache License, Version 2.0 - asm under BSD-3-Clause - asm-analysis under BSD-3-Clause - asm-commons under BSD-3-Clause - asm-tree under BSD-3-Clause - Duct Tape under MIT - EXASolution JDBC Driver under EXAClient License - Hamcrest Core under New BSD License - JaCoCo :: Agent under Eclipse Public License 2.0 - JaCoCo :: Core under Eclipse Public License 2.0 - Java Native Access under LGPL, version 2.1 or Apache License v2.0 - Java Native Access Platform under LGPL, version 2.1 or Apache License v2.0 - JetBrains Java Annotations under The Apache Software License, Version 2.0 - JSR 374 (JSON Processing) API under Dual license consisting of the CDDL v1.1 and GPL v2 - JUnit under Eclipse Public License 1.0 - JUnit Jupiter API under Eclipse Public License v2.0 - JUnit Jupiter Engine under Eclipse Public License v2.0 - JUnit Jupiter Params under Eclipse Public License v2.0 - JUnit Platform Commons under Eclipse Public License v2.0 - JUnit Platform Engine API under Eclipse Public License v2.0 - JUnit Platform Launcher under Eclipse Public License v2.0 - JUnit Platform Runner under Eclipse Public License v2.0 - JUnit Platform Suite API under Eclipse Public License v2.0 - junixsocket-common under Apache License, Version 2.0 - junixsocket-native-common under Apache License, Version 2.0 - Native Library Loader under CC0 1.0 Universal License - org.apiguardian:apiguardian-api under The Apache License, Version 2.0 - org.opentest4j:opentest4j under The Apache License, Version 2.0 - SLF4J API Module under MIT License - SLF4J JDK14 Binding under MIT License - TCP to Unix Socket Proxy under MIT - Test containers for Exasol on Docker under MIT - Testcontainers :: Database-Commons under MIT - Testcontainers :: JDBC under MIT - Testcontainers :: JUnit Jupiter Extension under MIT - Testcontainers Core under MIT - udf-debugging-java under MIT - Visible Assertions under MIT - diff --git a/NOTICE.template b/NOTICE.template deleted file mode 100644 index b8b28b0..0000000 --- a/NOTICE.template +++ /dev/null @@ -1,2 +0,0 @@ -This project has the following dependencies: -#GENERATED_NOTICES# \ No newline at end of file diff --git a/README.md b/README.md index 3d35e52..1c88953 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,109 @@ # UDF Debugging Tools for Java -[![Build Status](https://travis-ci.com/exasol/udf-debugging-java.svg?branch=master)](https://travis-ci.com/exasol/udf-debugging-java) -[![Maven Central](https://img.shields.io/maven-central/v/com.exasol/udf-debugging-java)](https://search.maven.org/artifact/com.exasol/udf-debugging-java) +[![Build Status](https://github.com/exasol/udf-debugging-java/actions/workflows/ci-build.yml/badge.svg)](https://github.com/exasol/udf-debugging-java/actions/workflows/ci-build.yml) +[![Maven Central – udf-debugging-java](https://img.shields.io/maven-central/v/com.exasol/udf-debugging-java)](https://search.maven.org/artifact/com.exasol/udf-debugging-java) + +[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=com.exasol%3Audf-debugging-java&metric=alert_status)](https://sonarcloud.io/dashboard?id=com.exasol%3Audf-debugging-java) + +[![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=com.exasol%3Audf-debugging-java&metric=security_rating)](https://sonarcloud.io/dashboard?id=com.exasol%3Audf-debugging-java) +[![Reliability Rating](https://sonarcloud.io/api/project_badges/measure?project=com.exasol%3Audf-debugging-java&metric=reliability_rating)](https://sonarcloud.io/dashboard?id=com.exasol%3Audf-debugging-java) +[![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=com.exasol%3Audf-debugging-java&metric=sqale_rating)](https://sonarcloud.io/dashboard?id=com.exasol%3Audf-debugging-java) +[![Technical Debt](https://sonarcloud.io/api/project_badges/measure?project=com.exasol%3Audf-debugging-java&metric=sqale_index)](https://sonarcloud.io/dashboard?id=com.exasol%3Audf-debugging-java) + +[![Code Smells](https://sonarcloud.io/api/project_badges/measure?project=com.exasol%3Audf-debugging-java&metric=code_smells)](https://sonarcloud.io/dashboard?id=com.exasol%3Audf-debugging-java) +[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=com.exasol%3Audf-debugging-java&metric=coverage)](https://sonarcloud.io/dashboard?id=com.exasol%3Audf-debugging-java) +[![Duplicated Lines (%)](https://sonarcloud.io/api/project_badges/measure?project=com.exasol%3Audf-debugging-java&metric=duplicated_lines_density)](https://sonarcloud.io/dashboard?id=com.exasol%3Audf-debugging-java) +[![Lines of Code](https://sonarcloud.io/api/project_badges/measure?project=com.exasol%3Audf-debugging-java&metric=ncloc)](https://sonarcloud.io/dashboard?id=com.exasol%3Audf-debugging-java) This repository contains tools for debugging UDFs. ## Installation -Install as maven dependency. -You can get the dependency declaration by clicking the maven badge above. +Install as maven dependency. You can get the dependency declaration by clicking the maven badge above. + +## Typical Usage + +Typically, you use this package together with [test-db-builder-java](https://github.com/exasol/test-db-builder-java) and [exasol-testcontainers](https://github.com/exasol/exasol-testcontainers) as follows: + +```java + +private static final ExasolContainer> EXASOL=new ExasolContainer<>(); +final UdfTestSetup udfTestSetup=new UdfTestSetup(getTestHostIp(),EXASOL.getDefaultBucket()); +final ExasolObjectFactory testDbBuilder=new ExasolObjectFactory(EXASOL.createConnection(), + ExasolObjectConfiguration.builder().withJvmOptions(udfTestSetup.getJvmOptions()).build()); +``` + +## Modules + +This package contains multiple modules that you can enable on runtime by setting the corresponding system property to `true`. Typically, you do so by appending `-D="true"` to your JVM call. + +### Debugging + +System property: `test.debug` + +This module instructs the UDF JVMs to connect to a Java debugger listening on the default port 8000 on you machine, running the tests. + +### Code Coverage + +System property: `test.coverage` + +This module installs a jacoco agent to the UDF JVM and receives the execution data using a TCP socket. + +This module requires additional maven configuration. Use [project-keeper](https://github.com/exasol/project-keeper-maven-plugin) module `udf_coverage` to verify it. + +Please note that using a [JaCoCo agent](https://www.jacoco.org/jacoco/trunk/doc/agent.html) fails when running on Windows using a [Docker image](https://docs.docker.com/glossary/#container-image) in a Linux virtual machine, see known issue [Failing Integration Tests on Windows](#known-issue:-failing-integration-tests-on-windows). + +### JProfiler + +System property: `test.jprofiler` + +This module allows you to profile UDF runs using [JProfiler](https://www.ej-technologies.com/products/jprofiler/overview.html). For that it uploads the JProfiler archive to BucketFs and adds the agent to the UDF command. + +Since JProfiler uses a forward TCP connection you can only profile one UDF instance at once. Make sure that you don't start multiple parallel instances. + +#### Usage + +* Install JProfiler on your system +* Download JProfiler for Linux without JRE as `.tar.gz` (Also choose the Linux version if you're on a different operating system!) +* Now you've two options: + * Store it as `jprofiler.tar.gz` in your home directory + * Store it somewhere and pass `-DjProfilerAgent=` to each test run +* Run your tests with `-Dtest.jprofiler=true` +* Find out the IPv4 address of your Exasol DB (for docker use `docker inspect`) +* Start JProfiler GUI +* Connect to `:11002` + * The UDF execution will wait until you connect the profiler + * Ensure that the port is reachable from your system (for AWS instances you can use an SSH tunnel from inside JProfiler) + +### UDF Logs + +System property: `test.udf-logs` + +This module redirects the STDOUT from UDFs to files on the test host. + +You can find the logs in `target/udf-logs/`. For each incoming stream (UDF instance) this module creates one file and logs its name: + +``` +Created log file for UDF output: target/udf-logs/udf-log-2023-07-05T10:49:09.316547Z-576983159368731727.log +``` + +## Known Issue: Failing Integration Tests on Windows + +Please note that integration tests fail when running on Windows using a Docker image in a Linux virtual machine due to JaCoCo agent obtaining the [Code Coverage](#code-coverage) in the UDF. + +Steps to reproduce + +* Use a virtual schema, e.g. https://github.com/exasol/mysql-virtual-schema +* with Maven command `mvn clean verify -Dtest=MySQLSqlDialectIT` + +Known workarounds + +* Either run integration tests from the Eclipse IDE +* or remove `.withJvmOptions(udfTestSetup.getJvmOptions())` from `ExasolObjectConfiguration.builder()` +* or run tests with JVM option `-Dtest.coverage="false"` +* or run integration tests inside the VM. ## Additional Information * [Changelog](doc/changes/changelog.md) -* [Dependencies](NOTICE) \ No newline at end of file +* [Dependencies](dependencies.md) diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..f0edc21 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,25 @@ +# Security + +If you believe you have found a new security vulnerability in this repository, please report it to us as follows. + +## Reporting Security Issues + +* Please do **not** report security vulnerabilities through public GitHub issues. + +* Please create a draft security advisory on the Github page: the reporting form is under `> Security > Advisories`. The URL is https://github.com/exasol/udf-debugging-java/security/advisories/new. + +* If you prefer to email, please send your report to `infosec@exasol.com`. + +## Guidelines + +* When reporting a vulnerability, please include as much information as possible, including the complete steps to reproduce the issue. + +* Avoid sending us executables. + +* Feel free to include any script you wrote and used but avoid sending us scripts that download and run binaries. + +* We will prioritise reports that show how the exploits work in realistic environments. + +* We prefer all communications to be in English. + +* We do not offer financial rewards. We are happy to acknowledge your research publicly when possible. diff --git a/assembly/all-dependencies.xml b/assembly/all-dependencies.xml deleted file mode 100644 index efe5abc..0000000 --- a/assembly/all-dependencies.xml +++ /dev/null @@ -1,22 +0,0 @@ - - all-dependencies - - jar - - false - - - - metaInf-services - - - - - true - runtime - / - - - diff --git a/dependencies.md b/dependencies.md new file mode 100644 index 0000000..3778478 --- /dev/null +++ b/dependencies.md @@ -0,0 +1,130 @@ + +# Dependencies + +## Compile Dependencies + +| Dependency | License | +| --------------------------------------- | ------------------------------------------------------------------------------------------------------------ | +| [Jakarta JSON Processing API][0] | [Eclipse Public License 2.0][1]; [GNU General Public License, version 2 with the GNU Classpath Exception][2] | +| [error-reporting-java][3] | [MIT License][4] | +| [JaCoCo :: Core][5] | [EPL-2.0][6] | +| [BucketFS Java][7] | [MIT License][8] | +| [exasol-test-setup-abstraction-java][9] | [MIT License][10] | +| [Apache Commons Compress][11] | [Apache-2.0][12] | +| [SLF4J JDK14 Provider][13] | [MIT][14] | + +## Test Dependencies + +| Dependency | License | +| ----------------------------------------------- | --------------------------------- | +| [JaCoCo :: Agent][5] | [EPL-2.0][6] | +| [JUnit Jupiter Engine][15] | [Eclipse Public License v2.0][16] | +| [JUnit Jupiter Params][15] | [Eclipse Public License v2.0][16] | +| [mockito-junit-jupiter][17] | [MIT][18] | +| [Hamcrest][19] | [BSD-3-Clause][20] | +| [Test containers for Exasol on Docker][21] | [MIT License][22] | +| [Testcontainers :: JUnit Jupiter Extension][23] | [MIT][24] | +| [Test Database Builder for Java][25] | [MIT License][26] | +| [JUnit5 System Extensions][27] | [Eclipse Public License v2.0][28] | + +## Runtime Dependencies + +| Dependency | License | +| --------------------- | ------------------------------------------------------------------------------------------------------------ | +| [Eclipse Parsson][29] | [Eclipse Public License 2.0][1]; [GNU General Public License, version 2 with the GNU Classpath Exception][2] | + +## Plugin Dependencies + +| Dependency | License | +| ------------------------------------------------------- | ------------------------------------------- | +| [Apache Maven Clean Plugin][30] | [Apache-2.0][12] | +| [Apache Maven Install Plugin][31] | [Apache-2.0][12] | +| [Apache Maven Resources Plugin][32] | [Apache-2.0][12] | +| [Apache Maven Site Plugin][33] | [Apache-2.0][12] | +| [SonarQube Scanner for Maven][34] | [GNU LGPL 3][35] | +| [Apache Maven Toolchains Plugin][36] | [Apache-2.0][12] | +| [Apache Maven Dependency Plugin][37] | [Apache-2.0][12] | +| [Project Keeper Maven plugin][38] | [The MIT License][39] | +| [Apache Maven Compiler Plugin][40] | [Apache-2.0][12] | +| [Apache Maven Enforcer Plugin][41] | [Apache-2.0][12] | +| [Maven Flatten Plugin][42] | [Apache Software Licenese][12] | +| [org.sonatype.ossindex.maven:ossindex-maven-plugin][43] | [ASL2][44] | +| [Maven Surefire Plugin][45] | [Apache-2.0][12] | +| [Versions Maven Plugin][46] | [Apache License, Version 2.0][12] | +| [duplicate-finder-maven-plugin Maven Mojo][47] | [Apache License 2.0][48] | +| [Apache Maven Artifact Plugin][49] | [Apache-2.0][12] | +| [Apache Maven Deploy Plugin][50] | [Apache-2.0][12] | +| [Apache Maven GPG Plugin][51] | [Apache-2.0][12] | +| [Apache Maven Source Plugin][52] | [Apache License, Version 2.0][12] | +| [Apache Maven Javadoc Plugin][53] | [Apache-2.0][12] | +| [Nexus Staging Maven Plugin][54] | [Eclipse Public License][55] | +| [Maven Failsafe Plugin][56] | [Apache-2.0][12] | +| [JaCoCo :: Maven Plugin][57] | [EPL-2.0][6] | +| [Quality Summarizer Maven Plugin][58] | [MIT License][59] | +| [error-code-crawler-maven-plugin][60] | [MIT License][61] | +| [Git Commit Id Maven Plugin][62] | [GNU Lesser General Public License 3.0][63] | + +[0]: https://github.com/eclipse-ee4j/jsonp +[1]: https://projects.eclipse.org/license/epl-2.0 +[2]: https://projects.eclipse.org/license/secondary-gpl-2.0-cp +[3]: https://github.com/exasol/error-reporting-java/ +[4]: https://github.com/exasol/error-reporting-java/blob/main/LICENSE +[5]: https://www.eclemma.org/jacoco/index.html +[6]: https://www.eclipse.org/legal/epl-2.0/ +[7]: https://github.com/exasol/bucketfs-java/ +[8]: https://github.com/exasol/bucketfs-java/blob/main/LICENSE +[9]: https://github.com/exasol/exasol-test-setup-abstraction-java/ +[10]: https://github.com/exasol/exasol-test-setup-abstraction-java/blob/main/LICENSE +[11]: https://commons.apache.org/proper/commons-compress/ +[12]: https://www.apache.org/licenses/LICENSE-2.0.txt +[13]: http://www.slf4j.org +[14]: https://opensource.org/license/mit +[15]: https://junit.org/junit5/ +[16]: https://www.eclipse.org/legal/epl-v20.html +[17]: https://github.com/mockito/mockito +[18]: https://opensource.org/licenses/MIT +[19]: http://hamcrest.org/JavaHamcrest/ +[20]: https://raw.githubusercontent.com/hamcrest/JavaHamcrest/master/LICENSE +[21]: https://github.com/exasol/exasol-testcontainers/ +[22]: https://github.com/exasol/exasol-testcontainers/blob/main/LICENSE +[23]: https://java.testcontainers.org +[24]: http://opensource.org/licenses/MIT +[25]: https://github.com/exasol/test-db-builder-java/ +[26]: https://github.com/exasol/test-db-builder-java/blob/main/LICENSE +[27]: https://github.com/itsallcode/junit5-system-extensions +[28]: http://www.eclipse.org/legal/epl-v20.html +[29]: https://github.com/eclipse-ee4j/parsson +[30]: https://maven.apache.org/plugins/maven-clean-plugin/ +[31]: https://maven.apache.org/plugins/maven-install-plugin/ +[32]: https://maven.apache.org/plugins/maven-resources-plugin/ +[33]: https://maven.apache.org/plugins/maven-site-plugin/ +[34]: http://docs.sonarqube.org/display/PLUG/Plugin+Library/sonar-scanner-maven/sonar-maven-plugin +[35]: http://www.gnu.org/licenses/lgpl.txt +[36]: https://maven.apache.org/plugins/maven-toolchains-plugin/ +[37]: https://maven.apache.org/plugins/maven-dependency-plugin/ +[38]: https://github.com/exasol/project-keeper/ +[39]: https://github.com/exasol/project-keeper/blob/main/LICENSE +[40]: https://maven.apache.org/plugins/maven-compiler-plugin/ +[41]: https://maven.apache.org/enforcer/maven-enforcer-plugin/ +[42]: https://www.mojohaus.org/flatten-maven-plugin/ +[43]: https://sonatype.github.io/ossindex-maven/maven-plugin/ +[44]: http://www.apache.org/licenses/LICENSE-2.0.txt +[45]: https://maven.apache.org/surefire/maven-surefire-plugin/ +[46]: https://www.mojohaus.org/versions/versions-maven-plugin/ +[47]: https://basepom.github.io/duplicate-finder-maven-plugin +[48]: http://www.apache.org/licenses/LICENSE-2.0.html +[49]: https://maven.apache.org/plugins/maven-artifact-plugin/ +[50]: https://maven.apache.org/plugins/maven-deploy-plugin/ +[51]: https://maven.apache.org/plugins/maven-gpg-plugin/ +[52]: https://maven.apache.org/plugins/maven-source-plugin/ +[53]: https://maven.apache.org/plugins/maven-javadoc-plugin/ +[54]: http://www.sonatype.com/public-parent/nexus-maven-plugins/nexus-staging/nexus-staging-maven-plugin/ +[55]: http://www.eclipse.org/legal/epl-v10.html +[56]: https://maven.apache.org/surefire/maven-failsafe-plugin/ +[57]: https://www.jacoco.org/jacoco/trunk/doc/maven.html +[58]: https://github.com/exasol/quality-summarizer-maven-plugin/ +[59]: https://github.com/exasol/quality-summarizer-maven-plugin/blob/main/LICENSE +[60]: https://github.com/exasol/error-code-crawler-maven-plugin/ +[61]: https://github.com/exasol/error-code-crawler-maven-plugin/blob/main/LICENSE +[62]: https://github.com/git-commit-id/git-commit-id-maven-plugin +[63]: http://www.gnu.org/licenses/lgpl-3.0.txt diff --git a/doc/changes/changelog.md b/doc/changes/changelog.md index 39f13d8..39e84a8 100644 --- a/doc/changes/changelog.md +++ b/doc/changes/changelog.md @@ -1,4 +1,25 @@ # Changes +* [0.6.16](changes_0.6.16.md) +* [0.6.15](changes_0.6.15.md) +* [0.6.14](changes_0.6.14.md) +* [0.6.13](changes_0.6.13.md) +* [0.6.12](changes_0.6.12.md) +* [0.6.11](changes_0.6.11.md) +* [0.6.10](changes_0.6.10.md) +* [0.6.9](changes_0.6.9.md) +* [0.6.8](changes_0.6.8.md) +* [0.6.7](changes_0.6.7.md) +* [0.6.6](changes_0.6.6.md) +* [0.6.5](changes_0.6.5.md) +* [0.6.4](changes_0.6.4.md) +* [0.6.3](changes_0.6.3.md) +* [0.6.2](changes_0.6.2.md) +* [0.6.1](changes_0.6.1.md) +* [0.6.0](changes_0.6.0.md) +* [0.5.0](changes_0.5.0.md) +* [0.4.1](changes_0.4.1.md) +* [0.4.0](changes_0.4.0.md) +* [0.3.0](changes_0.3.0.md) * [0.2.0](changes_0.2.0.md) * [0.1.0](changes_0.1.0.md) diff --git a/doc/changes/changes_0.2.0.md b/doc/changes/changes_0.2.0.md index 050ed73..8c3aeeb 100644 --- a/doc/changes/changes_0.2.0.md +++ b/doc/changes/changes_0.2.0.md @@ -1,11 +1,12 @@ -# udf-debugging-java 0.2.0, released 2020-XX-XX +# udf-debugging-java 0.2.0, released 2020-10-28 -Code name: +Code name: Test setup for UDF debugging ## Features / Enhancements * #5: Sonar Cloud setup * #6: Changed default value of getSelectionThatIsSentToTheAdapter to empty string +* #8: Added test setup for debugging in UDFs ## Dependency Updates: diff --git a/doc/changes/changes_0.3.0.md b/doc/changes/changes_0.3.0.md new file mode 100644 index 0000000..f8809cc --- /dev/null +++ b/doc/changes/changes_0.3.0.md @@ -0,0 +1,20 @@ +# udf-debugging-java 0.3.0, released 2020-11-23 + +Code name: Test setup for UDF code coverage + +## Features / Enhancements + +* #10: Added a module for code coverage in UDFs + +## Dependency Updates: + +* Updated to `com:exasol:project-keeper-maven-plugin:0.3.0` (was 0.2.0) +* Added `com.exasol:error-reporting-java:0.2.0` +* Added `org.jacoco:org.jacoco.core:0.8.6` +* Added `com.exasol:exasol-testcontainers:3.3.1` +* Added `org.mockito:mockito-core:3.6.0` +* Added `org.hamcrest:hamcrest-all:1.3` +* Added `com.exasol:test-db-builder-java:2.0.0` +* Updated to `org.jacoco:jacoco-maven-plugin:0.8.6` (was 0.8.5) +* Added `org.sonatype.plugins:nexus-staging-maven-plugin:1.6.8` +* Updated `org.jacoco:org.jacoco.agent0.8.6` (was 0.8.5) \ No newline at end of file diff --git a/doc/changes/changes_0.4.0.md b/doc/changes/changes_0.4.0.md new file mode 100644 index 0000000..ef22173 --- /dev/null +++ b/doc/changes/changes_0.4.0.md @@ -0,0 +1,47 @@ +# udf-debugging-java 0.4.0, released 2021-07-16 + +Code name: Added JProfiler Module + +## Features / Enhancements + +* #15: Add API for host port proxy +* #26: Added support for exasol-test-setup-abstraction +* #20: Added module for JProfiler + +## Refactoring: + +* #11: Removed exasol-testconatiner compile dependency + +## Bug Fixes: + +* #18: Fixed Broken URL link in the pom.xml + +## Dependency Updates + +### Compile Dependency Updates + +* Added `com.exasol:bucketfs-java:2.0.1` +* Updated `com.exasol:error-reporting-java:0.2.0` to `0.4.0` +* Added `com.exasol:exasol-test-setup-abstraction-java:0.1.1` +* Removed `com.exasol:exasol-testcontainers:3.3.1` +* Updated `com.exasol:test-db-builder-java:2.0.0` to `3.2.0` +* Added `org.apache.commons:commons-compress:1.21` +* Updated `org.jacoco:org.jacoco.core:0.8.6` to `0.8.7` +* Updated `org.slf4j:slf4j-api:1.7.30` to `1.7.31` + +### Test Dependency Updates + +* Added `com.exasol:exasol-testcontainers:3.5.3` +* Updated `org.jacoco:org.jacoco.agent:0.8.6` to `0.8.7` +* Updated `org.junit.jupiter:junit-jupiter-engine:5.6.2` to `5.7.2` +* Updated `org.junit.jupiter:junit-jupiter-params:5.6.2` to `5.7.2` +* Removed `org.junit.platform:junit-platform-runner:1.6.2` +* Updated `org.mockito:mockito-core:3.6.0` to `3.11.2` +* Updated `org.testcontainers:junit-jupiter:1.14.3` to `1.15.3` + +### Plugin Dependency Updates + +* Added `com.exasol:error-code-crawler-maven-plugin:0.5.0` +* Updated `com.exasol:project-keeper-maven-plugin:0.3.0` to `0.10.0` +* Added `io.github.zlika:reproducible-build-maven-plugin:0.13` +* Updated `org.jacoco:jacoco-maven-plugin:0.8.6` to `0.8.7` diff --git a/doc/changes/changes_0.4.1.md b/doc/changes/changes_0.4.1.md new file mode 100644 index 0000000..bd4a3b3 --- /dev/null +++ b/doc/changes/changes_0.4.1.md @@ -0,0 +1,35 @@ +# udf-debugging-java 0.4.1, released 2021-10-01 + +Code name: Dependency Updates on Added JProfiler Module + +## Features + +* #29: Replaced javax.json by jakarta.json + +## Dependency Updates + +### Compile Dependency Updates + +* Updated `com.exasol:bucketfs-java:2.0.1` to `2.2.0` +* Updated `com.exasol:exasol-test-setup-abstraction-java:0.1.1` to `0.2.0` +* Updated `com.exasol:test-db-builder-java:3.2.0` to `3.2.1` +* Added `jakarta.json:jakarta.json-api:2.0.1` +* Removed `javax.json:javax.json-api:1.1.4` +* Updated `org.slf4j:slf4j-api:1.7.31` to `1.7.32` + +### Runtime Dependency Updates + +* Added `org.glassfish:jakarta.json:2.0.1` + +### Test Dependency Updates + +* Updated `com.exasol:exasol-testcontainers:3.5.3` to `5.1.0` +* Updated `org.junit.jupiter:junit-jupiter-engine:5.7.2` to `5.8.1` +* Updated `org.junit.jupiter:junit-jupiter-params:5.7.2` to `5.8.1` +* Updated `org.mockito:mockito-core:3.11.2` to `3.12.4` +* Updated `org.testcontainers:junit-jupiter:1.15.3` to `1.16.0` + +### Plugin Dependency Updates + +* Updated `com.exasol:error-code-crawler-maven-plugin:0.5.0` to `0.6.0` +* Updated `com.exasol:project-keeper-maven-plugin:0.10.0` to `1.2.0` diff --git a/doc/changes/changes_0.5.0.md b/doc/changes/changes_0.5.0.md new file mode 100644 index 0000000..cb0ae6d --- /dev/null +++ b/doc/changes/changes_0.5.0.md @@ -0,0 +1,29 @@ +# udf-debugging-java 0.5.0, released 2022-01-12 + +Code name: Logs from UDFs + +## Features + +* #31: Added module for capturing logs from UDFs + +## Dependency Updates + +### Compile Dependency Updates + +* Updated `com.exasol:error-reporting-java:0.4.0` to `0.4.1` +* Updated `com.exasol:exasol-test-setup-abstraction-java:0.2.0` to `0.2.1` + +### Test Dependency Updates + +* Updated `com.exasol:exasol-testcontainers:5.1.0` to `5.1.1` +* Updated `org.junit.jupiter:junit-jupiter-engine:5.8.1` to `5.8.2` +* Updated `org.junit.jupiter:junit-jupiter-params:5.8.1` to `5.8.2` +* Updated `org.mockito:mockito-core:3.12.4` to `4.2.0` +* Added `org.mockito:mockito-junit-jupiter:4.2.0` +* Updated `org.testcontainers:junit-jupiter:1.16.0` to `1.16.2` + +### Plugin Dependency Updates + +* Updated `com.exasol:error-code-crawler-maven-plugin:0.6.0` to `0.7.1` +* Updated `com.exasol:project-keeper-maven-plugin:1.2.0` to `1.3.4` +* Updated `org.apache.maven.plugins:maven-javadoc-plugin:3.2.0` to `3.3.1` diff --git a/doc/changes/changes_0.6.0.md b/doc/changes/changes_0.6.0.md new file mode 100644 index 0000000..22f5cb0 --- /dev/null +++ b/doc/changes/changes_0.6.0.md @@ -0,0 +1,24 @@ +# udf-debugging-java 0.6.0, released 2022-02-23 + +Code name: Single line info message + +## Features + +* #13: Made info message single line + +## Dependency Updates + +### Compile Dependency Updates + +* Updated `com.exasol:bucketfs-java:2.2.0` to `2.3.0` +* Updated `com.exasol:exasol-test-setup-abstraction-java:0.2.1` to `0.2.2` +* Updated `com.exasol:test-db-builder-java:3.2.1` to `3.2.2` +* Added `org.itsallcode:junit5-system-extensions:1.2.0` +* Updated `org.slf4j:slf4j-api:1.7.32` to `1.7.36` + +### Test Dependency Updates + +* Updated `com.exasol:exasol-testcontainers:5.1.1` to `6.0.0` +* Updated `org.mockito:mockito-core:4.2.0` to `4.3.1` +* Updated `org.mockito:mockito-junit-jupiter:4.2.0` to `4.3.1` +* Updated `org.testcontainers:junit-jupiter:1.16.2` to `1.16.3` diff --git a/doc/changes/changes_0.6.1.md b/doc/changes/changes_0.6.1.md new file mode 100644 index 0000000..71e9a4a --- /dev/null +++ b/doc/changes/changes_0.6.1.md @@ -0,0 +1,43 @@ +# udf-debugging-java 0.6.1, released 2022-05-10 + +Code name: 0.6.1: Upgrade dependencies + +This release upgrades dependencies and reduces the number of runtime dependencies, fixing [CVE-2022-21724](https://ossindex.sonatype.org/) in the PostgreSQL JDBC driver. + +## Features + +## Dependency Updates + +### Compile Dependency Updates + +* Removed `com.exasol:test-db-builder-java:3.2.2` +* Updated `jakarta.json:jakarta.json-api:2.0.1` to `2.1.0` +* Removed `org.itsallcode:junit5-system-extensions:1.2.0` +* Updated `org.jacoco:org.jacoco.core:0.8.7` to `0.8.8` + +### Test Dependency Updates + +* Updated `com.exasol:exasol-testcontainers:6.0.0` to `6.1.1` +* Added `com.exasol:test-db-builder-java:3.3.2` +* Added `org.itsallcode:junit5-system-extensions:1.2.0` +* Updated `org.jacoco:org.jacoco.agent:0.8.7` to `0.8.8` +* Removed `org.mockito:mockito-core:4.3.1` +* Updated `org.mockito:mockito-junit-jupiter:4.3.1` to `4.5.1` +* Updated `org.testcontainers:junit-jupiter:1.16.3` to `1.17.1` + +### Plugin Dependency Updates + +* Updated `com.exasol:error-code-crawler-maven-plugin:0.7.1` to `1.1.1` +* Updated `com.exasol:project-keeper-maven-plugin:1.3.4` to `2.3.2` +* Updated `io.github.zlika:reproducible-build-maven-plugin:0.13` to `0.15` +* Updated `org.apache.maven.plugins:maven-compiler-plugin:3.8.1` to `3.10.1` +* Updated `org.apache.maven.plugins:maven-deploy-plugin:2.7` to `3.0.0-M2` +* Updated `org.apache.maven.plugins:maven-enforcer-plugin:3.0.0-M3` to `3.0.0` +* Updated `org.apache.maven.plugins:maven-gpg-plugin:1.6` to `3.0.1` +* Updated `org.apache.maven.plugins:maven-javadoc-plugin:3.3.1` to `3.4.0` +* Added `org.codehaus.mojo:flatten-maven-plugin:1.2.7` +* Updated `org.codehaus.mojo:versions-maven-plugin:2.7` to `2.10.0` +* Updated `org.jacoco:jacoco-maven-plugin:0.8.7` to `0.8.8` +* Added `org.sonarsource.scanner.maven:sonar-maven-plugin:3.9.1.2184` +* Updated `org.sonatype.ossindex.maven:ossindex-maven-plugin:3.1.0` to `3.2.0` +* Updated `org.sonatype.plugins:nexus-staging-maven-plugin:1.6.8` to `1.6.13` diff --git a/doc/changes/changes_0.6.10.md b/doc/changes/changes_0.6.10.md new file mode 100644 index 0000000..69b6b16 --- /dev/null +++ b/doc/changes/changes_0.6.10.md @@ -0,0 +1,15 @@ +# Udf Debugging Java 0.6.10, released 2023-07-05 + +Code name: Reduce dependencies + +## Summary + +This release uses readable and sortable names for UDF debug log files written to `target/udf-logs/`. The release also replaces code that causes an unnecessary dependency on `slf4j-api`. + +## Features + +* #56: Used readable and sortable names for UDF debug log files. + +## Refactoring + +* #55: Replaced code using `slf4j-api` diff --git a/doc/changes/changes_0.6.11.md b/doc/changes/changes_0.6.11.md new file mode 100644 index 0000000..a4bf90d --- /dev/null +++ b/doc/changes/changes_0.6.11.md @@ -0,0 +1,46 @@ +# Udf Debugging Java 0.6.11, released 2023-09-26 + +Code name: Fix CVE-2023-42503 + +## Summary + +This release fixes CVE-2023-42503 in `org.apache.commons:commons-compress` by upgrading dependencies. + +**Known issue:** Transitive dependency `io.netty:netty-handler` used by `software.amazon.awssdk:cloudformation` in scope `provided` contains vulnerability CVE-2023-4586. We assume that the AWS SDK's usage of netty is not affected. + +## Security + +* #61: Fixed CVE-2023-42503 in `org.apache.commons:commons-compress` + +## Dependency Updates + +### Compile Dependency Updates + +* Updated `org.apache.commons:commons-compress:1.23.0` to `1.24.0` +* Updated `org.slf4j:slf4j-jdk14:2.0.7` to `2.0.9` + +### Runtime Dependency Updates + +* Updated `org.eclipse.parsson:parsson:1.1.2` to `1.1.4` + +### Test Dependency Updates + +* Updated `com.exasol:exasol-testcontainers:6.6.0` to `6.6.2` +* Updated `com.exasol:test-db-builder-java:3.4.2` to `3.5.0` +* Updated `org.junit.jupiter:junit-jupiter-engine:5.9.3` to `5.10.0` +* Updated `org.junit.jupiter:junit-jupiter-params:5.9.3` to `5.10.0` +* Updated `org.mockito:mockito-junit-jupiter:5.4.0` to `5.5.0` +* Updated `org.testcontainers:junit-jupiter:1.18.3` to `1.19.0` + +### Plugin Dependency Updates + +* Updated `com.exasol:error-code-crawler-maven-plugin:1.2.3` to `1.3.0` +* Updated `com.exasol:project-keeper-maven-plugin:2.9.7` to `2.9.12` +* Updated `org.apache.maven.plugins:maven-enforcer-plugin:3.3.0` to `3.4.0` +* Updated `org.apache.maven.plugins:maven-failsafe-plugin:3.0.0` to `3.1.2` +* Updated `org.apache.maven.plugins:maven-gpg-plugin:3.0.1` to `3.1.0` +* Updated `org.apache.maven.plugins:maven-surefire-plugin:3.0.0` to `3.1.2` +* Updated `org.basepom.maven:duplicate-finder-maven-plugin:1.5.1` to `2.0.1` +* Updated `org.codehaus.mojo:flatten-maven-plugin:1.4.1` to `1.5.0` +* Updated `org.codehaus.mojo:versions-maven-plugin:2.15.0` to `2.16.0` +* Updated `org.jacoco:jacoco-maven-plugin:0.8.9` to `0.8.10` diff --git a/doc/changes/changes_0.6.12.md b/doc/changes/changes_0.6.12.md new file mode 100644 index 0000000..2b7fbb4 --- /dev/null +++ b/doc/changes/changes_0.6.12.md @@ -0,0 +1,50 @@ +# Udf Debugging Java 0.6.12, released 2024-03-01 + +Code name: Fix CVE-2024-25710 and CVE-2024-26308 in compile dependency `org.apache.commons:commons-compress` + +## Summary + +This release fixes vulnerabilities CVE-2024-25710 and CVE-2024-26308 in compile dependency `org.apache.commons:commons-compress`. + +## Security + +* #63: Fixed CVE-2024-25710 and CVE-2024-26308 in compile dependency `org.apache.commons:commons-compress` + +## Dependency Updates + +### Compile Dependency Updates + +* Updated `com.exasol:bucketfs-java:3.1.0` to `3.1.2` +* Updated `jakarta.json:jakarta.json-api:2.1.2` to `2.1.3` +* Updated `org.apache.commons:commons-compress:1.24.0` to `1.26.0` +* Updated `org.jacoco:org.jacoco.core:0.8.10` to `0.8.11` +* Updated `org.slf4j:slf4j-jdk14:2.0.9` to `2.0.12` + +### Runtime Dependency Updates + +* Updated `org.eclipse.parsson:parsson:1.1.4` to `1.1.5` + +### Test Dependency Updates + +* Updated `com.exasol:exasol-testcontainers:6.6.2` to `7.0.1` +* Updated `com.exasol:test-db-builder-java:3.5.0` to `3.5.3` +* Updated `org.jacoco:org.jacoco.agent:0.8.10` to `0.8.11` +* Updated `org.junit.jupiter:junit-jupiter-engine:5.10.0` to `5.10.2` +* Updated `org.junit.jupiter:junit-jupiter-params:5.10.0` to `5.10.2` +* Updated `org.mockito:mockito-junit-jupiter:5.5.0` to `5.10.0` +* Updated `org.testcontainers:junit-jupiter:1.19.0` to `1.19.6` + +### Plugin Dependency Updates + +* Updated `com.exasol:error-code-crawler-maven-plugin:1.3.0` to `2.0.0` +* Updated `com.exasol:project-keeper-maven-plugin:2.9.12` to `4.1.0` +* Updated `org.apache.maven.plugins:maven-compiler-plugin:3.11.0` to `3.12.1` +* Updated `org.apache.maven.plugins:maven-enforcer-plugin:3.4.0` to `3.4.1` +* Updated `org.apache.maven.plugins:maven-failsafe-plugin:3.1.2` to `3.2.5` +* Updated `org.apache.maven.plugins:maven-javadoc-plugin:3.5.0` to `3.6.3` +* Updated `org.apache.maven.plugins:maven-surefire-plugin:3.1.2` to `3.2.5` +* Added `org.apache.maven.plugins:maven-toolchains-plugin:3.1.0` +* Updated `org.codehaus.mojo:flatten-maven-plugin:1.5.0` to `1.6.0` +* Updated `org.codehaus.mojo:versions-maven-plugin:2.16.0` to `2.16.2` +* Updated `org.jacoco:jacoco-maven-plugin:0.8.10` to `0.8.11` +* Updated `org.sonarsource.scanner.maven:sonar-maven-plugin:3.9.1.2184` to `3.10.0.2594` diff --git a/doc/changes/changes_0.6.13.md b/doc/changes/changes_0.6.13.md new file mode 100644 index 0000000..3bb0cfa --- /dev/null +++ b/doc/changes/changes_0.6.13.md @@ -0,0 +1,40 @@ +# Udf Debugging Java 0.6.13, released 2024-04-09 + +Code name: Fixes CVE-2024-29025 in io.netty:netty-codec-http:jar:4.1.100.Final:provided + +## Summary + +This release fixes vulnerability CVE-2024-29025 in `io.netty:netty-codec-http:jar:4.1.100.Final:provided`. + +**Excluded vulnerability** This release contains vulnerability CVE-2017-10355 in `fr.turri:aXMLRPC` for connecting to ExaOperation during tests. We accept this vulnerability (CWE-833: Deadlock) as we assume that we only connect to the known endpoint ExaOperations. + +## Security + +* #65: Fixed CVE-2024-29025 in `io.netty:netty-codec-http:jar:4.1.100.Final:provided` + +## Dependency Updates + +### Compile Dependency Updates + +* Updated `org.apache.commons:commons-compress:1.26.0` to `1.26.1` +* Updated `org.jacoco:org.jacoco.core:0.8.11` to `0.8.12` + +### Runtime Dependency Updates + +* Updated `org.eclipse.parsson:parsson:1.1.5` to `1.1.6` + +### Test Dependency Updates + +* Updated `com.exasol:test-db-builder-java:3.5.3` to `3.5.4` +* Updated `org.jacoco:org.jacoco.agent:0.8.11` to `0.8.12` +* Updated `org.mockito:mockito-junit-jupiter:5.10.0` to `5.11.0` +* Updated `org.testcontainers:junit-jupiter:1.19.6` to `1.19.7` + +### Plugin Dependency Updates + +* Updated `com.exasol:error-code-crawler-maven-plugin:2.0.0` to `2.0.2` +* Updated `com.exasol:project-keeper-maven-plugin:4.1.0` to `4.3.0` +* Updated `org.apache.maven.plugins:maven-compiler-plugin:3.12.1` to `3.13.0` +* Updated `org.apache.maven.plugins:maven-gpg-plugin:3.1.0` to `3.2.2` +* Updated `org.jacoco:jacoco-maven-plugin:0.8.11` to `0.8.12` +* Updated `org.sonarsource.scanner.maven:sonar-maven-plugin:3.10.0.2594` to `3.11.0.3922` diff --git a/doc/changes/changes_0.6.14.md b/doc/changes/changes_0.6.14.md new file mode 100644 index 0000000..124e9a2 --- /dev/null +++ b/doc/changes/changes_0.6.14.md @@ -0,0 +1,54 @@ +# Udf Debugging Java 0.6.14, released 2024-11-19 + +Code name: Fix CVE-2024-47535: io.netty:netty-common:jar:4.1.108.Final:provided + +## Summary + +This release fixes CVE-2024-47535 in transitive production dependency `io.netty:netty-common:jar:4.1.108.Final:provided` added by `com.exasol:exasol-test-setup-abstraction-java`. + +## Security + +* #67: Fixed CVE-2024-47535 in `io.netty:netty-common:jar:4.1.108.Final:provided` + +## Dependency Updates + +### Compile Dependency Updates + +* Updated `com.exasol:bucketfs-java:3.1.2` to `3.2.0` +* Updated `org.apache.commons:commons-compress:1.26.1` to `1.27.1` +* Updated `org.slf4j:slf4j-jdk14:2.0.12` to `2.0.16` + +### Runtime Dependency Updates + +* Updated `org.eclipse.parsson:parsson:1.1.6` to `1.1.7` + +### Test Dependency Updates + +* Updated `com.exasol:exasol-testcontainers:7.0.1` to `7.1.1` +* Updated `com.exasol:test-db-builder-java:3.5.4` to `3.6.0` +* Updated `org.itsallcode:junit5-system-extensions:1.2.0` to `1.2.2` +* Updated `org.junit.jupiter:junit-jupiter-engine:5.10.2` to `5.11.3` +* Updated `org.junit.jupiter:junit-jupiter-params:5.10.2` to `5.11.3` +* Updated `org.mockito:mockito-junit-jupiter:5.11.0` to `5.14.2` +* Updated `org.testcontainers:junit-jupiter:1.19.7` to `1.20.3` + +### Plugin Dependency Updates + +* Updated `com.exasol:error-code-crawler-maven-plugin:2.0.2` to `2.0.3` +* Updated `com.exasol:project-keeper-maven-plugin:4.3.0` to `4.4.0` +* Added `com.exasol:quality-summarizer-maven-plugin:0.2.0` +* Updated `io.github.zlika:reproducible-build-maven-plugin:0.16` to `0.17` +* Updated `org.apache.maven.plugins:maven-clean-plugin:2.5` to `3.4.0` +* Updated `org.apache.maven.plugins:maven-deploy-plugin:3.1.1` to `3.1.2` +* Updated `org.apache.maven.plugins:maven-enforcer-plugin:3.4.1` to `3.5.0` +* Updated `org.apache.maven.plugins:maven-failsafe-plugin:3.2.5` to `3.5.1` +* Updated `org.apache.maven.plugins:maven-gpg-plugin:3.2.2` to `3.2.7` +* Updated `org.apache.maven.plugins:maven-install-plugin:2.4` to `3.1.3` +* Updated `org.apache.maven.plugins:maven-javadoc-plugin:3.6.3` to `3.10.1` +* Updated `org.apache.maven.plugins:maven-resources-plugin:2.6` to `3.3.1` +* Updated `org.apache.maven.plugins:maven-site-plugin:3.3` to `3.9.1` +* Updated `org.apache.maven.plugins:maven-surefire-plugin:3.2.5` to `3.5.1` +* Updated `org.apache.maven.plugins:maven-toolchains-plugin:3.1.0` to `3.2.0` +* Updated `org.codehaus.mojo:versions-maven-plugin:2.16.2` to `2.17.1` +* Updated `org.sonarsource.scanner.maven:sonar-maven-plugin:3.11.0.3922` to `4.0.0.4121` +* Updated `org.sonatype.plugins:nexus-staging-maven-plugin:1.6.13` to `1.7.0` diff --git a/doc/changes/changes_0.6.15.md b/doc/changes/changes_0.6.15.md new file mode 100644 index 0000000..0e23146 --- /dev/null +++ b/doc/changes/changes_0.6.15.md @@ -0,0 +1,42 @@ +# Udf Debugging Java 0.6.15, released 2025-02-12 + +Code name: Fix vulnerabilities CVE-2025-25193 and CVE-2025-24970 in test dependencies + +## Summary + +This release fixes the following vulnerabilities in test dependencies: + +* `io.netty:netty-common:jar:4.1.115.Final:test`: CVE-2025-25193 +* `io.netty:netty-handler:jar:4.1.115.Final:test`: CVE-2025-24970 + +## Security + +* #69: Fixed CVE-2025-25193 in `io.netty:netty-common:jar:4.1.115.Final:test` +* #70: Fixed CVE-2025-24970 in `io.netty:netty-handler:jar:4.1.115.Final:test` + +## Dependency Updates + +### Compile Dependency Updates + +* Updated `com.exasol:bucketfs-java:3.2.0` to `3.2.1` + +### Test Dependency Updates + +* Updated `com.exasol:exasol-testcontainers:7.1.1` to `7.1.3` +* Removed `org.hamcrest:hamcrest-all:1.3` +* Added `org.hamcrest:hamcrest:3.0` +* Updated `org.junit.jupiter:junit-jupiter-engine:5.11.3` to `5.11.4` +* Updated `org.junit.jupiter:junit-jupiter-params:5.11.3` to `5.11.4` +* Updated `org.mockito:mockito-junit-jupiter:5.14.2` to `5.15.2` +* Updated `org.testcontainers:junit-jupiter:1.20.3` to `1.20.4` + +### Plugin Dependency Updates + +* Updated `com.exasol:project-keeper-maven-plugin:4.4.0` to `4.5.0` +* Updated `org.apache.maven.plugins:maven-deploy-plugin:3.1.2` to `3.1.3` +* Updated `org.apache.maven.plugins:maven-failsafe-plugin:3.5.1` to `3.5.2` +* Updated `org.apache.maven.plugins:maven-javadoc-plugin:3.10.1` to `3.11.1` +* Updated `org.apache.maven.plugins:maven-site-plugin:3.9.1` to `3.21.0` +* Updated `org.apache.maven.plugins:maven-surefire-plugin:3.5.1` to `3.5.2` +* Updated `org.codehaus.mojo:versions-maven-plugin:2.17.1` to `2.18.0` +* Updated `org.sonarsource.scanner.maven:sonar-maven-plugin:4.0.0.4121` to `5.0.0.4389` diff --git a/doc/changes/changes_0.6.16.md b/doc/changes/changes_0.6.16.md new file mode 100644 index 0000000..f085995 --- /dev/null +++ b/doc/changes/changes_0.6.16.md @@ -0,0 +1,48 @@ +# Udf Debugging Java 0.6.16, released 2025-06-02 + +Code name: Security updates on top of 0.6.15 + +## Summary + +This release is a security update. We updated the dependencies of the project to fix transitive security issues. + +We also added an exception for the OSSIndex for CVE-2024-55551, which is a false positive in Exasol's JDBC driver. +This issue has been fixed quite a while back now, but the OSSIndex unfortunately does not contain the fix version of 24.2.1 (2024-12-10) set. + +## Security + +* #74: Fix CVE-2024-55551 in com.exasol:exasol-jdbc:jar:24.2.1 + +## Dependency Updates + +### Compile Dependency Updates + +* Updated `org.jacoco:org.jacoco.core:0.8.12` to `0.8.13` +* Updated `org.slf4j:slf4j-jdk14:2.0.16` to `2.0.17` + +### Test Dependency Updates + +* Updated `com.exasol:exasol-testcontainers:7.1.3` to `7.1.5` +* Updated `com.exasol:test-db-builder-java:3.6.0` to `3.6.1` +* Updated `org.jacoco:org.jacoco.agent:0.8.12` to `0.8.13` +* Updated `org.junit.jupiter:junit-jupiter-engine:5.11.4` to `5.13.0` +* Updated `org.junit.jupiter:junit-jupiter-params:5.11.4` to `5.13.0` +* Updated `org.mockito:mockito-junit-jupiter:5.15.2` to `5.18.0` +* Updated `org.testcontainers:junit-jupiter:1.20.4` to `1.21.1` + +### Plugin Dependency Updates + +* Updated `com.exasol:project-keeper-maven-plugin:4.5.0` to `5.1.0` +* Added `io.github.git-commit-id:git-commit-id-maven-plugin:9.0.1` +* Removed `io.github.zlika:reproducible-build-maven-plugin:0.17` +* Added `org.apache.maven.plugins:maven-artifact-plugin:3.6.0` +* Updated `org.apache.maven.plugins:maven-clean-plugin:3.4.0` to `3.4.1` +* Updated `org.apache.maven.plugins:maven-compiler-plugin:3.13.0` to `3.14.0` +* Updated `org.apache.maven.plugins:maven-deploy-plugin:3.1.3` to `3.1.4` +* Updated `org.apache.maven.plugins:maven-failsafe-plugin:3.5.2` to `3.5.3` +* Updated `org.apache.maven.plugins:maven-install-plugin:3.1.3` to `3.1.4` +* Updated `org.apache.maven.plugins:maven-javadoc-plugin:3.11.1` to `3.11.2` +* Updated `org.apache.maven.plugins:maven-surefire-plugin:3.5.2` to `3.5.3` +* Updated `org.codehaus.mojo:flatten-maven-plugin:1.6.0` to `1.7.0` +* Updated `org.jacoco:jacoco-maven-plugin:0.8.12` to `0.8.13` +* Updated `org.sonarsource.scanner.maven:sonar-maven-plugin:5.0.0.4389` to `5.1.0.4751` diff --git a/doc/changes/changes_0.6.2.md b/doc/changes/changes_0.6.2.md new file mode 100644 index 0000000..ed980ed --- /dev/null +++ b/doc/changes/changes_0.6.2.md @@ -0,0 +1,17 @@ +# udf-debugging-java 0.6.2, released 2022-06-14 + +Code name: Dependency updates / CVE fixes + +## Summary + +Dependency updates for test-setup-abstraction and project-keeper + +## Dependency Updates + +### Compile Dependency Updates + +* Updated `com.exasol:exasol-test-setup-abstraction-java:0.2.2` to `0.3.2` + +### Plugin Dependency Updates + +* Updated `com.exasol:project-keeper-maven-plugin:2.3.2` to `2.4.6` diff --git a/doc/changes/changes_0.6.3.md b/doc/changes/changes_0.6.3.md new file mode 100644 index 0000000..a8205ed --- /dev/null +++ b/doc/changes/changes_0.6.3.md @@ -0,0 +1,24 @@ +# udf-debugging-java 0.6.3, released 2022-06-24 + +Code name: Removed ETSA dependency + +## Summary + +In this release we removed the exasol-test-setup-abstraction from the compile dependencies. Now it's declared as `provided`. By that, it's no longer pulled as transitive dependency into other projects. + +## Bug Fixes + +* #38: Removed exasol-test-setup-abstraction as compile dependency + +## Dependency Updates + +### Compile Dependency Updates + +* Removed `com.exasol:exasol-test-setup-abstraction-java:0.3.2` + +### Test Dependency Updates + +* Updated `com.exasol:exasol-testcontainers:6.1.1` to `6.1.2` +* Updated `com.exasol:test-db-builder-java:3.3.2` to `3.3.3` +* Updated `org.mockito:mockito-junit-jupiter:4.5.1` to `4.6.1` +* Updated `org.testcontainers:junit-jupiter:1.17.1` to `1.17.2` diff --git a/doc/changes/changes_0.6.4.md b/doc/changes/changes_0.6.4.md new file mode 100644 index 0000000..9df8762 --- /dev/null +++ b/doc/changes/changes_0.6.4.md @@ -0,0 +1,11 @@ +# udf-debugging-java 0.6.4, released 2022-06-27 + +Code name: Fixed NoClassDefFoundError + +## Summary + +## Bug Fixes + +* #40: Fixed NoClassDefFoundError when used without exasol-test-setup-abstraction-java + +## Dependency Updates diff --git a/doc/changes/changes_0.6.5.md b/doc/changes/changes_0.6.5.md new file mode 100644 index 0000000..7a03839 --- /dev/null +++ b/doc/changes/changes_0.6.5.md @@ -0,0 +1,47 @@ +# udf-debugging-java 0.6.5, released 2022-11-22 + +Code name: Updated dependencies on top of 0.6.4 + +## Summary + +In this release we fixed a version collision between the BucketFS library used in this project and `exasol-test-setup-abstraction-java` that led to a class-not-found error in certain combinations. + +## Known Issues + +This project depends on an Amazon AWS SDK which in turn depends on the Netty HTTP server version 4.1.77. This versions has a vulnerability in certificate validation that can allow to man-in-the-middle attacks. Unfortunately, no update of the AWS SDK is available at the time of this release. + +## Bugfixes + +* #43: Fixed BucketFS library version collisions. + +## Dependency Updates + +### Compile Dependency Updates + +* Updated `com.exasol:bucketfs-java:2.3.0` to `2.4.1` +* Updated `com.exasol:error-reporting-java:0.4.1` to `1.0.0` +* Updated `jakarta.json:jakarta.json-api:2.1.0` to `2.1.1` +* Updated `org.apache.commons:commons-compress:1.21` to `1.22` +* Updated `org.slf4j:slf4j-api:1.7.36` to `2.0.4` + +### Test Dependency Updates + +* Updated `com.exasol:exasol-testcontainers:6.1.2` to `6.3.1` +* Updated `com.exasol:test-db-builder-java:3.3.3` to `3.4.1` +* Updated `org.junit.jupiter:junit-jupiter-engine:5.8.2` to `5.9.1` +* Updated `org.junit.jupiter:junit-jupiter-params:5.8.2` to `5.9.1` +* Updated `org.mockito:mockito-junit-jupiter:4.6.1` to `4.9.0` +* Updated `org.testcontainers:junit-jupiter:1.17.2` to `1.17.6` + +### Plugin Dependency Updates + +* Updated `com.exasol:error-code-crawler-maven-plugin:1.1.1` to `1.2.1` +* Updated `com.exasol:project-keeper-maven-plugin:2.4.6` to `2.9.1` +* Updated `io.github.zlika:reproducible-build-maven-plugin:0.15` to `0.16` +* Updated `org.apache.maven.plugins:maven-deploy-plugin:3.0.0-M2` to `3.0.0` +* Updated `org.apache.maven.plugins:maven-enforcer-plugin:3.0.0` to `3.1.0` +* Updated `org.apache.maven.plugins:maven-failsafe-plugin:3.0.0-M4` to `3.0.0-M7` +* Updated `org.apache.maven.plugins:maven-javadoc-plugin:3.4.0` to `3.4.1` +* Updated `org.apache.maven.plugins:maven-surefire-plugin:3.0.0-M4` to `3.0.0-M7` +* Updated `org.codehaus.mojo:flatten-maven-plugin:1.2.7` to `1.3.0` +* Updated `org.codehaus.mojo:versions-maven-plugin:2.10.0` to `2.13.0` diff --git a/doc/changes/changes_0.6.6.md b/doc/changes/changes_0.6.6.md new file mode 100644 index 0000000..8c4274a --- /dev/null +++ b/doc/changes/changes_0.6.6.md @@ -0,0 +1,24 @@ +# Udf Debugging Java 0.6.6, released 2022-12-22 + +Code name: Dependency Upgrade + +## Summary + +Updated dependencies after breaking changes in interface of bucketfs-java to re-enable compatibility with newer versions of bucketfs-java used by other libraries, e.g. exasol-testcontainers. + +## Changes + +* #46: Updated dependencies +* #42: Documented known issue of JaCoCo failing on Windows. + +## Dependency Updates + +### Compile Dependency Updates + +* Updated `com.exasol:bucketfs-java:2.4.1` to `2.6.0` +* Updated `org.slf4j:slf4j-api:2.0.4` to `2.0.6` + +### Test Dependency Updates + +* Updated `com.exasol:exasol-testcontainers:6.3.1` to `6.4.1` +* Updated `org.mockito:mockito-junit-jupiter:4.9.0` to `4.10.0` diff --git a/doc/changes/changes_0.6.7.md b/doc/changes/changes_0.6.7.md new file mode 100644 index 0000000..68e5b2a --- /dev/null +++ b/doc/changes/changes_0.6.7.md @@ -0,0 +1,21 @@ +# Udf Debugging Java 0.6.7, released 2023-01-20 + +Code name: Upgrade dependencies on top of 0.6.6 + +## Summary + +This release upgrades dependencies incl. exasol-test-setup-abstraction-java 2.0.0 to adapt to the updated API. + +## Features + +* #51: Updated to exasol-test-setup-abstraction-java 2.0.0 + +## Dependency Updates + +### Test Dependency Updates + +* Updated `com.exasol:exasol-testcontainers:6.4.1` to `6.5.0` +* Updated `com.exasol:test-db-builder-java:3.4.1` to `3.4.2` +* Updated `org.junit.jupiter:junit-jupiter-engine:5.9.1` to `5.9.2` +* Updated `org.junit.jupiter:junit-jupiter-params:5.9.1` to `5.9.2` +* Updated `org.mockito:mockito-junit-jupiter:4.10.0` to `5.0.0` diff --git a/doc/changes/changes_0.6.8.md b/doc/changes/changes_0.6.8.md new file mode 100644 index 0000000..be89a6e --- /dev/null +++ b/doc/changes/changes_0.6.8.md @@ -0,0 +1,30 @@ +# Udf Debugging Java 0.6.8, released 2023-02-07 + +Code name: Improved LocalServiceExposer + +## Summary + +Enhanced interface `LocalServiceExposer` and simplified usage. + +## Features + +* #53: Enhanced interface `LocalServiceExposer` and simplified usage. + +## Dependency Updates + +### Compile Dependency Updates + +* Updated `com.exasol:bucketfs-java:2.6.0` to `3.0.0` + +### Test Dependency Updates + +* Updated `com.exasol:exasol-testcontainers:6.5.0` to `6.5.1` +* Updated `org.mockito:mockito-junit-jupiter:5.0.0` to `5.1.1` + +### Plugin Dependency Updates + +* Updated `com.exasol:error-code-crawler-maven-plugin:1.2.1` to `1.2.2` +* Updated `com.exasol:project-keeper-maven-plugin:2.9.1` to `2.9.3` +* Updated `org.apache.maven.plugins:maven-failsafe-plugin:3.0.0-M7` to `3.0.0-M8` +* Updated `org.apache.maven.plugins:maven-surefire-plugin:3.0.0-M7` to `3.0.0-M8` +* Updated `org.codehaus.mojo:versions-maven-plugin:2.13.0` to `2.14.2` diff --git a/doc/changes/changes_0.6.9.md b/doc/changes/changes_0.6.9.md new file mode 100644 index 0000000..850d3d9 --- /dev/null +++ b/doc/changes/changes_0.6.9.md @@ -0,0 +1,53 @@ +# Udf Debugging Java 0.6.9, released 2023-07-03 + +Code name: Upgrade dependencies on top of 0.6.8 + +## Summary + +This release fixes the following vulnerability in `provided` dependency `io.netty:netty-handler`: +* CVE-2023-34462, severity CWE-770: Allocation of Resources Without Limits or Throttling (6.5) + +## Security + +* #57: Upgraded dependencies + +## Dependency Updates + +### Compile Dependency Updates + +* Updated `com.exasol:bucketfs-java:3.0.0` to `3.1.0` +* Updated `com.exasol:error-reporting-java:1.0.0` to `1.0.1` +* Updated `jakarta.json:jakarta.json-api:2.1.1` to `2.1.2` +* Updated `org.apache.commons:commons-compress:1.22` to `1.23.0` +* Updated `org.jacoco:org.jacoco.core:0.8.8` to `0.8.10` +* Removed `org.slf4j:slf4j-api:2.0.6` +* Added `org.slf4j:slf4j-jdk14:2.0.7` + +### Runtime Dependency Updates + +* Added `org.eclipse.parsson:parsson:1.1.2` +* Removed `org.glassfish:jakarta.json:2.0.1` + +### Test Dependency Updates + +* Updated `com.exasol:exasol-testcontainers:6.5.1` to `6.6.0` +* Updated `org.jacoco:org.jacoco.agent:0.8.8` to `0.8.10` +* Updated `org.junit.jupiter:junit-jupiter-engine:5.9.2` to `5.9.3` +* Updated `org.junit.jupiter:junit-jupiter-params:5.9.2` to `5.9.3` +* Updated `org.mockito:mockito-junit-jupiter:5.1.1` to `5.4.0` +* Updated `org.testcontainers:junit-jupiter:1.17.6` to `1.18.3` + +### Plugin Dependency Updates + +* Updated `com.exasol:error-code-crawler-maven-plugin:1.2.2` to `1.2.3` +* Updated `com.exasol:project-keeper-maven-plugin:2.9.3` to `2.9.7` +* Updated `org.apache.maven.plugins:maven-compiler-plugin:3.10.1` to `3.11.0` +* Updated `org.apache.maven.plugins:maven-deploy-plugin:3.0.0` to `3.1.1` +* Updated `org.apache.maven.plugins:maven-enforcer-plugin:3.1.0` to `3.3.0` +* Updated `org.apache.maven.plugins:maven-failsafe-plugin:3.0.0-M8` to `3.0.0` +* Updated `org.apache.maven.plugins:maven-javadoc-plugin:3.4.1` to `3.5.0` +* Updated `org.apache.maven.plugins:maven-surefire-plugin:3.0.0-M8` to `3.0.0` +* Added `org.basepom.maven:duplicate-finder-maven-plugin:1.5.1` +* Updated `org.codehaus.mojo:flatten-maven-plugin:1.3.0` to `1.4.1` +* Updated `org.codehaus.mojo:versions-maven-plugin:2.14.2` to `2.15.0` +* Updated `org.jacoco:jacoco-maven-plugin:0.8.8` to `0.8.9` diff --git a/error_code_config.yml b/error_code_config.yml new file mode 100644 index 0000000..de4c0d6 --- /dev/null +++ b/error_code_config.yml @@ -0,0 +1,5 @@ +error-tags: + UDJ: + packages: + - com.exasol.udfdebugging + highest-index: 19 \ No newline at end of file diff --git a/pk_generated_parent.pom b/pk_generated_parent.pom new file mode 100644 index 0000000..26ca8c2 --- /dev/null +++ b/pk_generated_parent.pom @@ -0,0 +1,448 @@ + + + 4.0.0 + com.exasol + udf-debugging-java-generated-parent + 0.6.16 + pom + + UTF-8 + UTF-8 + ${git.commit.time} + 11 + exasol + https://sonarcloud.io + + true + + + + ossrh + https://oss.sonatype.org/content/repositories/snapshots + + + ossrh + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + + + MIT License + https://github.com/exasol/udf-debugging-java/blob/main/LICENSE + repo + + + + + Exasol + opensource@exasol.com + Exasol AG + https://www.exasol.com/ + + + + scm:git:https://github.com/exasol/udf-debugging-java.git + scm:git:https://github.com/exasol/udf-debugging-java.git + https://github.com/exasol/udf-debugging-java/ + + + + + + org.apache.maven.plugins + maven-clean-plugin + 3.4.1 + + + org.apache.maven.plugins + maven-install-plugin + 3.1.4 + + + org.apache.maven.plugins + maven-resources-plugin + 3.3.1 + + + org.apache.maven.plugins + maven-site-plugin + 3.21.0 + + + org.sonarsource.scanner.maven + sonar-maven-plugin + 5.1.0.4751 + + + org.apache.maven.plugins + maven-toolchains-plugin + 3.2.0 + + + + toolchain + + + + + + + ${java.version} + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.14.0 + + ${java.version} + ${java.version} + true + + -Xlint:all + -Werror + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.5.0 + + + enforce-maven + + enforce + + + + + 3.8.7 + + + 17 + + + + + + + + org.codehaus.mojo + flatten-maven-plugin + 1.7.0 + + true + oss + + + + flatten + process-resources + + flatten + + + + flatten.clean + clean + + clean + + + + + + org.sonatype.ossindex.maven + ossindex-maven-plugin + 3.2.0 + + + audit + package + + audit + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.5.3 + + + -Djava.util.logging.config.file=src/test/resources/logging.properties ${argLine} + ${test.excludeTags} + + + + org.codehaus.mojo + versions-maven-plugin + 2.18.0 + + + display-updates + verify + + display-plugin-updates + display-dependency-updates + + + + + file:///${project.basedir}/versionsMavenPluginRules.xml + false + true + true + true + false + true + true + true + false + false + true + true + + + + org.basepom.maven + duplicate-finder-maven-plugin + 2.0.1 + + + default + verify + + check + + + + + true + true + true + true + true + true + false + true + false + + + + org.apache.maven.plugins + maven-artifact-plugin + 3.6.0 + + + check-build-plan + verify + + check-buildplan + + + + + + org.apache.maven.plugins + maven-deploy-plugin + 3.1.4 + + true + + + + org.apache.maven.plugins + maven-gpg-plugin + 3.2.7 + + + sign-artifacts + verify + + sign + + + + --pinentry-mode + loopback + + + + + + + org.apache.maven.plugins + maven-source-plugin + + 3.2.1 + + + attach-sources + + jar + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.11.2 + + + attach-javadocs + + jar + + + + + UTF-8 + + true + true + true + true + ${java.version} + + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.7.0 + + true + ossrh + https://oss.sonatype.org/ + 15 + 30 + + + + default-deploy + deploy + + deploy + + + + + + org.apache.maven.plugins + maven-failsafe-plugin + 3.5.3 + + + -Djava.util.logging.config.file=src/test/resources/logging.properties ${argLine} + + ${test.excludeTags} + + + + verify + + integration-test + verify + + + + + + org.jacoco + jacoco-maven-plugin + 0.8.13 + + + prepare-agent + + prepare-agent + + + + merge-results + verify + + merge + + + + + ${project.build.directory}/ + + jacoco*.exec + + + + ${project.build.directory}/aggregate.exec + + + + report + verify + + report + + + ${project.build.directory}/aggregate.exec + + + + + + com.exasol + quality-summarizer-maven-plugin + 0.2.0 + + + summarize-metrics + + summarize + + + + + + com.exasol + error-code-crawler-maven-plugin + 2.0.3 + + + verify + + verify + + + + + + io.github.git-commit-id + git-commit-id-maven-plugin + 9.0.1 + + + get-the-git-infos + + revision + + initialize + + + + true + UTC + + git.commit.time + + + + + + diff --git a/pom.xml b/pom.xml index 689fcdc..b55779c 100644 --- a/pom.xml +++ b/pom.xml @@ -1,80 +1,63 @@ - + 4.0.0 - com.exasol udf-debugging-java - 0.2.0 + 0.6.16 udf-debugging-java Utilities for debugging, profiling and code coverage measure for UDFs. - https://github.com/exasol/udf-debugging-javat + https://github.com/exasol/udf-debugging-java/ - UTF-8 - UTF-8 - 11 - 5.6.2 - 1.6.2 - 0.8.5 - 11.0.0 - true - 1.14.3 - 3.0.0-M4 + 5.13.0 + 0.8.13 - - - MIT - https://opensource.org/licenses/MIT - repo - - - - - Exasol - opensource@exasol.com - Exasol AG - https://www.exasol.com/ - - - - - ossrh - https://oss.sonatype.org/content/repositories/snapshots - - - ossrh - https://oss.sonatype.org/service/local/staging/deploy/maven2/ - - - - scm:git:https://github.com/exasol/udf-debugging-java.git - scm:git:https://github.com/exasol/udf-debugging-java.git - https://github.com/exasol/udf-debugging-java/tree/master - - - - maven.exasol.com - https://maven.exasol.com/artifactory/exasol-releases - - false - - - - maven.exasol.com-snapshots - https://maven.exasol.com/artifactory/exasol-snapshots - - true - - - - jitpack.io - https://jitpack.io - - - javax.json - javax.json-api - 1.1.4 + jakarta.json + jakarta.json-api + 2.1.3 + + + org.eclipse.parsson + parsson + 1.1.7 + runtime + + + com.exasol + error-reporting-java + 1.0.1 + + + org.jacoco + org.jacoco.core + ${jacoco.version} + + + org.jacoco + org.jacoco.agent + ${jacoco.version} + runtime + test + + + com.exasol + bucketfs-java + 3.2.1 + + + com.exasol + exasol-test-setup-abstraction-java + 2.1.7 + + provided + + + org.apache.commons + commons-compress + 1.27.1 @@ -83,134 +66,58 @@ ${junit.version} test - - org.junit.platform - junit-platform-runner - ${junit.platform.version} - test - org.junit.jupiter junit-jupiter-params ${junit.version} test + + org.mockito + mockito-junit-jupiter + 5.18.0 + test + + + org.hamcrest + hamcrest + 3.0 + test + com.exasol exasol-testcontainers - 3.2.0 + 7.1.5 test org.testcontainers junit-jupiter - ${org.testcontainers.version} + 1.21.1 test - org.jacoco - org.jacoco.agent - ${jacoco.version} - runtime + com.exasol + test-db-builder-java + 3.6.1 test - org.jacoco - org.jacoco.core - ${jacoco.version} + org.itsallcode + junit5-system-extensions + 1.2.2 test + + + org.slf4j + slf4j-jdk14 + 2.0.17 + - - org.apache.maven.plugins - maven-surefire-plugin - ${surefire.and.failsafe.plugin.version} - - - -Djava.util.logging.config.file=src/test/resources/logging.properties ${argLine} - - **IT.java - - - - - org.apache.maven.plugins - maven-failsafe-plugin - ${surefire.and.failsafe.plugin.version} - - - -Djava.util.logging.config.file=src/test/resources/logging.properties ${argLine} - - **IT.java - - - - - - integration-test - verify - - - - - - org.jacoco - jacoco-maven-plugin - ${jacoco.version} - - - prepare-agent - - prepare-agent - - - - prepare-agent-integration - - prepare-agent-integration - - - - report - test - - report - - - - report-integration - verify - - report-integration - - - - report-udf-integration - verify - - report-integration - - - ${project.build.directory}/jacoco-udf.exec - ${project.reporting.outputDirectory}/jacoco-udf - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - ${java.version} - ${java.version} - - maven-dependency-plugin @@ -230,156 +137,48 @@ - org.codehaus.mojo - versions-maven-plugin - 2.7 - - - package - - display-plugin-updates - display-dependency-updates - - - - - file:///${project.basedir}/versionsMavenPluginRules.xml - - - - org.apache.maven.plugins - maven-source-plugin - 3.2.1 + com.exasol + project-keeper-maven-plugin + 5.1.0 - attach-sources - jar + verify org.apache.maven.plugins - maven-javadoc-plugin - 3.2.0 - - - attach-javadocs - - jar - - - + maven-compiler-plugin - UTF-8 - - true - true - true - - - implNote - Implementation Note: - a - - + + + -Xlint:all,-path + -Werror + - - org.apache.maven.plugins - maven-gpg-plugin - 1.6 - - - sign-artifacts - verify - - sign - - - - --pinentry-mode - loopback - - - - - org.sonatype.ossindex.maven ossindex-maven-plugin - 3.1.0 - - - package - - audit - - - - - - org.apache.maven.plugins - maven-enforcer-plugin - 3.0.0-M3 - - - enforce-maven - - enforce - - - - - 3.3.9 - - - - - - - - com.exasol - project-keeper-maven-plugin - 0.2.0 - - - - verify - - - - - + + + CVE-2017-10355 + + CVE-2024-55551 + - - - - ${project.basedir}/src/test/resources - - - \ No newline at end of file + + udf-debugging-java-generated-parent + com.exasol + 0.6.16 + pk_generated_parent.pom + + diff --git a/src/main/java/com/exasol/udfdebugging/LocalServiceExposer.java b/src/main/java/com/exasol/udfdebugging/LocalServiceExposer.java new file mode 100644 index 0000000..205d3b8 --- /dev/null +++ b/src/main/java/com/exasol/udfdebugging/LocalServiceExposer.java @@ -0,0 +1,28 @@ +package com.exasol.udfdebugging; + +import java.net.InetSocketAddress; + +/** + * Implementors of this interface exposes a local service (socket) into the Exasol database. + */ +@FunctionalInterface +public interface LocalServiceExposer { + + /** + * Create an instance of {@code LocalServiceExposer} for a host that does not require port mapping. + * + * @param host host name or IP address of host (but without port) providing the service to expose + * @return new instance of {@code LocalServiceExposer} + */ + public static LocalServiceExposer forHost(final String host) { + return port -> new InetSocketAddress(host, port); + } + + /** + * Get the address for the network scope inside of the Exasol database for a given local service. + * + * @param port port number + * @return proxy + */ + InetSocketAddress exposeLocalServiceToDatabase(int port); +} diff --git a/src/main/java/com/exasol/udfdebugging/Module.java b/src/main/java/com/exasol/udfdebugging/Module.java new file mode 100644 index 0000000..b0dc9c5 --- /dev/null +++ b/src/main/java/com/exasol/udfdebugging/Module.java @@ -0,0 +1,17 @@ +package com.exasol.udfdebugging; + +import java.io.Closeable; +import java.util.stream.Stream; + +/** + * Modules define a specific functionality that users can enable using system properties. + */ +public interface Module extends Closeable { + + /** + * Get JVM options required by this module. + * + * @return JVM options + */ + public Stream getJvmOptions(); +} diff --git a/src/main/java/com/exasol/udfdebugging/ModuleFactory.java b/src/main/java/com/exasol/udfdebugging/ModuleFactory.java new file mode 100644 index 0000000..a85c270 --- /dev/null +++ b/src/main/java/com/exasol/udfdebugging/ModuleFactory.java @@ -0,0 +1,36 @@ +package com.exasol.udfdebugging; + +import java.sql.Connection; + +import com.exasol.bucketfs.Bucket; + +/** + * Interface for factories for {@link Module}. + */ +public interface ModuleFactory { + + /** + * Get if this module is enabled by system property. + * + * @return {@code true} if this module is enabled + */ + public boolean isEnabled(); + + /** + * Get the name of the property to enable this module. + * + * @return name of the property to enable this module + */ + public String getModulePropertyName(); + + /** + * Build the {@link Module}. + * + * @param localServiceExposer Proxy factory that makes ports of the test host available in the container + * @param bucket BucketFS bucket to upload resource to + * @param exasolConnection connection to the Exasol database + * @return built {@link Module} + */ + public Module buildModule(final LocalServiceExposer localServiceExposer, Bucket bucket, + final Connection exasolConnection); +} diff --git a/src/main/java/com/exasol/udfdebugging/PushDownTesting.java b/src/main/java/com/exasol/udfdebugging/PushDownTesting.java index 466baeb..f09f147 100644 --- a/src/main/java/com/exasol/udfdebugging/PushDownTesting.java +++ b/src/main/java/com/exasol/udfdebugging/PushDownTesting.java @@ -1,14 +1,26 @@ package com.exasol.udfdebugging; -import javax.json.Json; -import javax.json.JsonObject; -import javax.json.JsonReader; import java.io.StringReader; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; +import java.sql.*; +import jakarta.json.*; + +/** + * This class contains helper functions for testing virtual schema push down queries. + */ public class PushDownTesting { + private PushDownTesting() { + // Not instanciable + } + + /** + * Get the push-down SQL query generated by a Virtual Schema adapter call. + * + * @param statement SQL statement + * @param query query to a Virtual Schema table + * @return generated push down query + * @throws SQLException if execution fails + */ public static String getPushDownSql(final Statement statement, final String query) throws SQLException { try (final ResultSet pushDownSqlResult = statement .executeQuery("SELECT PUSHDOWN_SQL FROM (EXPLAIN VIRTUAL " + query + ");")) { @@ -17,7 +29,16 @@ public static String getPushDownSql(final Statement statement, final String quer } } - public static String getSelectionThatIsSentToTheAdapter(final Statement statement, final String query) throws SQLException { + /** + * Get the selection (where clause) that the Exasol database passed to the Virtual Schema adapter. + * + * @param statement SQL statement + * @param query query to a Virtual Schema table + * @return selection (where clause) + * @throws SQLException if SQL statement fails + */ + public static String getSelectionThatIsSentToTheAdapter(final Statement statement, final String query) + throws SQLException { try (final ResultSet pushDownSqlResult = statement .executeQuery("SELECT PUSHDOWN_JSON FROM (EXPLAIN VIRTUAL " + query + ");")) { pushDownSqlResult.next(); diff --git a/src/main/java/com/exasol/udfdebugging/UdfTestSetup.java b/src/main/java/com/exasol/udfdebugging/UdfTestSetup.java new file mode 100644 index 0000000..9332b07 --- /dev/null +++ b/src/main/java/com/exasol/udfdebugging/UdfTestSetup.java @@ -0,0 +1,89 @@ +package com.exasol.udfdebugging; + +import java.sql.Connection; +import java.util.List; +import java.util.logging.Logger; +import java.util.stream.Collectors; + +import com.exasol.bucketfs.Bucket; +import com.exasol.exasoltestsetup.ExasolTestSetup; +import com.exasol.udfdebugging.modules.coverage.CoverageModuleFactory; +import com.exasol.udfdebugging.modules.debugging.DebuggingModuleFactory; +import com.exasol.udfdebugging.modules.jprofiler.JProfilerModuleFactory; +import com.exasol.udfdebugging.modules.udflogs.UdfLogsModuleFactory; + +/** + * Test setup for testing UDFs in the database. + */ +public class UdfTestSetup implements AutoCloseable { + private static final List AVAILABLE_MODULES = List.of(new DebuggingModuleFactory(), + new CoverageModuleFactory(), new JProfilerModuleFactory(), new UdfLogsModuleFactory()); + private static final Logger LOGGER = Logger.getLogger(UdfTestSetup.class.getName()); + private final List enabledModules; + + /** + * Create a new instance of {@link UdfTestSetup}. + * + * @param testHostIpAddress IP address of the host running this UDF Test Setup under which UDFs can reach it + * @param bucket BucketFS bucket to upload resource to + * @param exasolConnection connection to the Exasol database. Make sure that your tests use the same connection + */ + public UdfTestSetup(final String testHostIpAddress, final Bucket bucket, final Connection exasolConnection) { + this(LocalServiceExposer.forHost(testHostIpAddress), bucket, exasolConnection); + } + + /** + * Create a new instance of {@link UdfTestSetup}. + * + * @param localServiceExposer Proxy factory that makes ports of the test host available in the container + * @param bucket BucketFS bucket to upload resource to + * @param exasolConnection connection to the Exasol database. Make sure that your tests use the same connection + */ + private UdfTestSetup(final LocalServiceExposer localServiceExposer, final Bucket bucket, + final Connection exasolConnection) { + this.enabledModules = AVAILABLE_MODULES.stream().filter(ModuleFactory::isEnabled) + .map(moduleFactory -> moduleFactory.buildModule(localServiceExposer, bucket, exasolConnection)) + .collect(Collectors.toList()); + printInfoMessage(); + } + + /** + * Create a new instance of {@link UdfTestSetup}. + * + * @param testSetup Exasol test setup + * @param exasolConnection connection to the Exasol database. Make sure that your tests use the same connection + */ + public UdfTestSetup(final ExasolTestSetup testSetup, final Connection exasolConnection) { + this(testSetup::makeLocalTcpServiceAccessibleFromDatabase, testSetup.getDefaultBucket(), exasolConnection); + } + + /** + * Get JVM options required for this setup. + * + * @return array of JVM options + */ + public String[] getJvmOptions() { + return this.enabledModules.stream().flatMap(Module::getJvmOptions).toArray(String[]::new); + } + + private void printInfoMessage() { + LOGGER.info(this::getInfoMessage); + } + + private String getInfoMessage() { + return "UDF debug config: " + AVAILABLE_MODULES.stream() + .map(module -> module.getModulePropertyName() + ": " + (module.isEnabled() ? "✓" : "✗")) + .collect(Collectors.joining("; ")); + } + + @Override + public void close() { + for (final Module enabledModule : this.enabledModules) { + try { + enabledModule.close(); + } catch (final Exception exception) { + // at least we tried + } + } + } +} diff --git a/src/main/java/com/exasol/udfdebugging/modules/AbstractModuleFactory.java b/src/main/java/com/exasol/udfdebugging/modules/AbstractModuleFactory.java new file mode 100644 index 0000000..9bc0bfc --- /dev/null +++ b/src/main/java/com/exasol/udfdebugging/modules/AbstractModuleFactory.java @@ -0,0 +1,30 @@ +package com.exasol.udfdebugging.modules; + +import com.exasol.udfdebugging.Module; +import com.exasol.udfdebugging.ModuleFactory; + +/** + * Abstract basis for {@link Module}. + */ +public abstract class AbstractModuleFactory implements ModuleFactory { + private final String moduleProperty; + + /** + * Create a new instance of {@link AbstractModuleFactory}. + * + * @param moduleName name of the module + */ + protected AbstractModuleFactory(final String moduleName) { + this.moduleProperty = "test." + moduleName; + } + + @Override + public final boolean isEnabled() { + return System.getProperty(this.moduleProperty, "false").equals("true"); + } + + @Override + public String getModulePropertyName() { + return this.moduleProperty; + } +} diff --git a/src/main/java/com/exasol/udfdebugging/modules/coverage/CoverageModule.java b/src/main/java/com/exasol/udfdebugging/modules/coverage/CoverageModule.java new file mode 100644 index 0000000..055bd1a --- /dev/null +++ b/src/main/java/com/exasol/udfdebugging/modules/coverage/CoverageModule.java @@ -0,0 +1,68 @@ +package com.exasol.udfdebugging.modules.coverage; + +import java.io.FileNotFoundException; +import java.net.InetSocketAddress; +import java.nio.file.Path; +import java.util.concurrent.TimeoutException; +import java.util.stream.Stream; + +import com.exasol.bucketfs.Bucket; +import com.exasol.bucketfs.BucketAccessException; +import com.exasol.errorreporting.ExaError; +import com.exasol.udfdebugging.LocalServiceExposer; +import com.exasol.udfdebugging.Module; + +/** + * {@link Module} for measuring code coverage in UDFs. + */ +public class CoverageModule implements Module { + private static final String JACOCO_AGENT_NAME = "org.jacoco.agent-runtime.jar"; + private static final Path JACOCO_AGENT_PATH = Path.of("target", "jacoco-agent", JACOCO_AGENT_NAME); + private final String jvmOption; + + /** + * Create a new instance of {@link CoverageModule}. + * + * @param localServiceExposer Proxy factory that makes ports of the test host available in the container + * @param bucket Bucket to upload the agent to + */ + public CoverageModule(final LocalServiceExposer localServiceExposer, final Bucket bucket) { + assertJacocoAgentExists(); + uploadAgentToBucketFs(bucket); + JacocoServer.startIfNotRunning(); + final InetSocketAddress proxyForHostPort = localServiceExposer.exposeLocalServiceToDatabase(JacocoServer.PORT); + this.jvmOption = "-javaagent:/buckets/" + bucket.getBucketFsName() + "/" + bucket.getBucketName() + "/" + + JACOCO_AGENT_NAME + "=output=tcpclient,address=" + proxyForHostPort.getHostName() + ",port=" + + proxyForHostPort.getPort(); + } + + private void assertJacocoAgentExists() { + if (!JACOCO_AGENT_PATH.toFile().exists()) { + throw new IllegalArgumentException(ExaError.messageBuilder("E-UDJ-1") + .message( + "Could not find jacoco agent ({{PATH}}). The agent should we generated by the maven build.") + .parameter("PATH", JACOCO_AGENT_PATH.toString()) + .mitigation("Add the 'udf_coverage' module to the project-keeper plugin.").toString()); + } + } + + @Override + public Stream getJvmOptions() { + return Stream.of(this.jvmOption); + } + + private void uploadAgentToBucketFs(final Bucket bucket) { + try { + bucket.uploadFile(JACOCO_AGENT_PATH, JACOCO_AGENT_NAME); + } catch (final TimeoutException | BucketAccessException | FileNotFoundException exception) { + throw new IllegalStateException( + ExaError.messageBuilder("E-UDJ-5").message("Failed to upload jacoco agent to BucketFS.").toString(), + exception); + } + } + + @Override + public void close() { + // nothing to close + } +} diff --git a/src/main/java/com/exasol/udfdebugging/modules/coverage/CoverageModuleFactory.java b/src/main/java/com/exasol/udfdebugging/modules/coverage/CoverageModuleFactory.java new file mode 100644 index 0000000..7db5a28 --- /dev/null +++ b/src/main/java/com/exasol/udfdebugging/modules/coverage/CoverageModuleFactory.java @@ -0,0 +1,27 @@ +package com.exasol.udfdebugging.modules.coverage; + +import java.sql.Connection; + +import com.exasol.bucketfs.Bucket; +import com.exasol.udfdebugging.LocalServiceExposer; +import com.exasol.udfdebugging.Module; +import com.exasol.udfdebugging.modules.AbstractModuleFactory; + +/** + * Factory for {@link CoverageModule}. + */ +public class CoverageModuleFactory extends AbstractModuleFactory { + + /** + * Create a new instance of {@link CoverageModuleFactory}. + */ + public CoverageModuleFactory() { + super("coverage"); + } + + @Override + public Module buildModule(final LocalServiceExposer localServiceExposer, final Bucket bucket, + final Connection exasolConnection) { + return new CoverageModule(localServiceExposer, bucket); + } +} diff --git a/src/main/java/com/exasol/udfdebugging/modules/coverage/JacocoServer.java b/src/main/java/com/exasol/udfdebugging/modules/coverage/JacocoServer.java new file mode 100644 index 0000000..46a1b81 --- /dev/null +++ b/src/main/java/com/exasol/udfdebugging/modules/coverage/JacocoServer.java @@ -0,0 +1,125 @@ +package com.exasol.udfdebugging.modules.coverage; + +/* + * ***************************************************************************** + * Modified example from {@link https://raw.githubusercontent.com/jacoco/jacoco/master/org.jacoco.examples/src/org/jacoco/examples/ExecutionDataServer.java} + * + * Original license: + * + * Copyright (c) 2009, 2020 Mountainminds GmbH & Co. KG and Contributors + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Marc R. Hoffmann - initial API and implementation + * + *******************************************************************************/ + +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.ServerSocket; +import java.net.Socket; +import java.nio.file.Path; + +import org.jacoco.core.data.*; +import org.jacoco.core.runtime.RemoteControlReader; +import org.jacoco.core.runtime.RemoteControlWriter; + +import com.exasol.errorreporting.ExaError; + +/** + * This class starts a socket server to collect the code coverage data from the jacoco agent in the udfs. The collected + * data is dumped to a local file. + */ +final class JacocoServer implements Runnable { + + static final int PORT = 3002; + static final Path COVERAGE_REPORT_PATH = Path.of("target", "jacoco-udf.exec"); + private static JacocoServer instance; + private final ExecutionDataWriter fileWriter; + + private JacocoServer() throws IOException { + this.fileWriter = new ExecutionDataWriter(new FileOutputStream(COVERAGE_REPORT_PATH.toFile())); + } + + static void startIfNotRunning() { + if (instance == null) { + try { + instance = new JacocoServer(); + new Thread(instance).start(); + } catch (final IOException exception) { + throw new IllegalStateException(ExaError.messageBuilder("E-UDJ-2") + .message("Failed to create jacoco log server thread.").toString(), exception); + } + } + } + + @SuppressWarnings("java:S2189") // while loop has no end condition since the server should run forever (until test + // are done) + @Override + public void run() { + try (final ServerSocket server = new ServerSocket(PORT)) { + while (true) { + final Handler handler = new Handler(server.accept(), this.fileWriter); + new Thread(handler).start(); + } + } catch (final IOException exception) { + throw new IllegalStateException( + ExaError.messageBuilder("E-UDJ-3").message("Failed to start jacoco log server.").toString(), + exception); + } + } + + private static class Handler implements Runnable, ISessionInfoVisitor, IExecutionDataVisitor { + + private final Socket socket; + private final RemoteControlReader reader; + private final ExecutionDataWriter fileWriter; + + Handler(final Socket socket, final ExecutionDataWriter fileWriter) throws IOException { + this.socket = socket; + this.fileWriter = fileWriter; + + // Just send a valid header: + new RemoteControlWriter(socket.getOutputStream()); + + this.reader = new RemoteControlReader(socket.getInputStream()); + this.reader.setSessionInfoVisitor(this); + this.reader.setExecutionDataVisitor(this); + } + + @Override + public void run() { + try { + while (this.reader.read()) { + // read everything so that visitors are invoked + } + this.socket.close(); + synchronized (this.fileWriter) { + this.fileWriter.flush(); + } + } catch (final IOException exception) { + throw new IllegalStateException( + ExaError.messageBuilder("E-UDJ-7").message("Failed to write jacoco report.").toString(), + exception); + } + } + + @Override + public void visitSessionInfo(final SessionInfo info) { + synchronized (this.fileWriter) { + this.fileWriter.visitSessionInfo(info); + } + } + + @Override + public void visitClassExecution(final ExecutionData data) { + synchronized (this.fileWriter) { + this.fileWriter.visitClassExecution(data); + } + } + } +} \ No newline at end of file diff --git a/src/main/java/com/exasol/udfdebugging/modules/debugging/DebuggingModule.java b/src/main/java/com/exasol/udfdebugging/modules/debugging/DebuggingModule.java new file mode 100644 index 0000000..14f0010 --- /dev/null +++ b/src/main/java/com/exasol/udfdebugging/modules/debugging/DebuggingModule.java @@ -0,0 +1,38 @@ +package com.exasol.udfdebugging.modules.debugging; + +import java.net.InetSocketAddress; +import java.util.stream.Stream; + +import com.exasol.udfdebugging.LocalServiceExposer; +import com.exasol.udfdebugging.Module; + +/** + * This module configures a Java-UDF execution so that it connects to a remote debugger. + */ +public class DebuggingModule implements Module { + /** Port the remote-debugger listens on */ + public static final int DEBUGGING_PORT = 8000; + private final LocalServiceExposer localServiceExposer; + + /** + * Create a new instance of {@link DebuggingModule}. + * + * @param localServiceExposer Proxy factory that makes ports of the test host available in the container + */ + public DebuggingModule(final LocalServiceExposer localServiceExposer) { + this.localServiceExposer = localServiceExposer; + } + + @Override + public Stream getJvmOptions() { + final InetSocketAddress proxyForHostPort = this.localServiceExposer + .exposeLocalServiceToDatabase(DEBUGGING_PORT); + return Stream.of("-agentlib:jdwp=transport=dt_socket,server=n,address=" + proxyForHostPort.getHostName() + ":" + + proxyForHostPort.getPort() + ",suspend=y"); + } + + @Override + public void close() { + // nothing to close + } +} diff --git a/src/main/java/com/exasol/udfdebugging/modules/debugging/DebuggingModuleFactory.java b/src/main/java/com/exasol/udfdebugging/modules/debugging/DebuggingModuleFactory.java new file mode 100644 index 0000000..a6a8e2a --- /dev/null +++ b/src/main/java/com/exasol/udfdebugging/modules/debugging/DebuggingModuleFactory.java @@ -0,0 +1,26 @@ +package com.exasol.udfdebugging.modules.debugging; + +import java.sql.Connection; + +import com.exasol.bucketfs.Bucket; +import com.exasol.udfdebugging.LocalServiceExposer; +import com.exasol.udfdebugging.Module; +import com.exasol.udfdebugging.modules.AbstractModuleFactory; + +/** + * Factory for {@link DebuggingModule}. + */ +public class DebuggingModuleFactory extends AbstractModuleFactory { + /** + * Create a new instance of {@link DebuggingModuleFactory}. + */ + public DebuggingModuleFactory() { + super("debug"); + } + + @Override + public Module buildModule(final LocalServiceExposer localServiceExposer, final Bucket bucket, + final Connection exasolConnection) { + return new DebuggingModule(localServiceExposer); + } +} diff --git a/src/main/java/com/exasol/udfdebugging/modules/jprofiler/InArchiveProfilerAgentPathDetector.java b/src/main/java/com/exasol/udfdebugging/modules/jprofiler/InArchiveProfilerAgentPathDetector.java new file mode 100644 index 0000000..bf3fef4 --- /dev/null +++ b/src/main/java/com/exasol/udfdebugging/modules/jprofiler/InArchiveProfilerAgentPathDetector.java @@ -0,0 +1,49 @@ +package com.exasol.udfdebugging.modules.jprofiler; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +import org.apache.commons.compress.archivers.ArchiveEntry; +import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; +import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream; + +import com.exasol.errorreporting.ExaError; + +/** + * This class finds the path to the libjprofilerti.so in the jprofiler tar.gz archive. + */ +class InArchiveProfilerAgentPathDetector { + private static final String AGENT_NAME = "linux-x64/libjprofilerti.so"; + + /** + * Find the path to the libjprofilerti.so in the jprofiler tar.gz archive. + * + * @param jprofilerArchive path of the jprofiler tar.gz archive + * @return path to the agent lib inside of the archive + */ + String findPathToAgent(final Path jprofilerArchive) { + try (final TarArchiveInputStream tarInput = new TarArchiveInputStream( + new GzipCompressorInputStream(Files.newInputStream(jprofilerArchive)))) { + ArchiveEntry nextEntry = tarInput.getNextEntry(); + while (nextEntry != null) { + final String entryPath = nextEntry.getName(); + if (entryPath.endsWith(AGENT_NAME)) { + return entryPath; + } + nextEntry = tarInput.getNextEntry(); + } + } catch (final IOException exception) { + throw new IllegalStateException(ExaError.messageBuilder("F-UDJ-14") + .message("Failed to extract JProfiler tar.gz archive for extracting the version information.") + .ticketMitigation().toString(), exception); + } + throw new IllegalStateException(ExaError.messageBuilder("E-UDJ-15") + .message("Could not find " + AGENT_NAME + " in the provided jprofiler archive ({{archive file}}).", + jprofilerArchive) + .mitigation("Make sure that you specified the correct jprofiler archive.") + .mitigation( + "Future version of JProfiler could also have different agent file names. In that case, please open a ticket.") + .toString()); + } +} diff --git a/src/main/java/com/exasol/udfdebugging/modules/jprofiler/JProfilerModule.java b/src/main/java/com/exasol/udfdebugging/modules/jprofiler/JProfilerModule.java new file mode 100644 index 0000000..e6c80d5 --- /dev/null +++ b/src/main/java/com/exasol/udfdebugging/modules/jprofiler/JProfilerModule.java @@ -0,0 +1,75 @@ +package com.exasol.udfdebugging.modules.jprofiler; + +import java.io.FileNotFoundException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.concurrent.TimeoutException; +import java.util.stream.Stream; + +import com.exasol.bucketfs.Bucket; +import com.exasol.bucketfs.BucketAccessException; +import com.exasol.errorreporting.ExaError; +import com.exasol.udfdebugging.Module; + +/** + * {@link Module} for adding a JProfiler to an UDF instance. + */ +class JProfilerModule implements Module { + public static final String AGENT_OPTION = "jProfilerAgent"; + private final String jvmOption; + private final Path jprofilerArchive; + + /** + * Create a new instance of {@link JProfilerModule}. + * + * @param bucket bucket to upload the profiler to + */ + JProfilerModule(final Bucket bucket) { + this.jprofilerArchive = getJProfilerArchive(); + assertProfilerExists(this.jprofilerArchive); + final String inArchivePath = new InArchiveProfilerAgentPathDetector().findPathToAgent(this.jprofilerArchive); + uploadProfiler(bucket); + this.jvmOption = "-agentpath:" + "/buckets/" + bucket.getBucketFsName() + "/" + bucket.getBucketName() + + "/jprofiler/" + inArchivePath + "=port=11002"; + } + + private void uploadProfiler(final Bucket bucket) { + try { + bucket.uploadFile(this.jprofilerArchive, "jprofiler.tar.gz"); + } catch (final BucketAccessException | TimeoutException | FileNotFoundException exception) { + throw new IllegalStateException( + ExaError.messageBuilder("E-UDJ-13").message("Failed to upload jprofiler tar").toString(), + exception); + } + } + + private void assertProfilerExists(final Path jprofilerAgent) { + if (!Files.exists(jprofilerAgent)) { + throw new IllegalStateException(ExaError.messageBuilder("E-UDJ-8") + .message("Could not find jprofiler archive or open on path {{agent path}}).", jprofilerAgent) + .mitigation("Please download the JProfiler for Linux without JRE from the JProfiler website " + + "and specify the commandline option -D" + AGENT_OPTION + + "= or save it as ~/jprofiler.tar.gz.") + .toString()); + } + } + + private Path getJProfilerArchive() { + final String jProfilerAgentProperty = System.getProperty(AGENT_OPTION, ""); + if (jProfilerAgentProperty.isBlank()) { + return Path.of(System.getProperty("user.home")).resolve("jprofiler.tar.gz"); + } else { + return Path.of(jProfilerAgentProperty); + } + } + + @Override + public Stream getJvmOptions() { + return Stream.of(this.jvmOption); + } + + @Override + public void close() { + // nothing to close + } +} diff --git a/src/main/java/com/exasol/udfdebugging/modules/jprofiler/JProfilerModuleFactory.java b/src/main/java/com/exasol/udfdebugging/modules/jprofiler/JProfilerModuleFactory.java new file mode 100644 index 0000000..1a4c81a --- /dev/null +++ b/src/main/java/com/exasol/udfdebugging/modules/jprofiler/JProfilerModuleFactory.java @@ -0,0 +1,27 @@ +package com.exasol.udfdebugging.modules.jprofiler; + +import java.sql.Connection; + +import com.exasol.bucketfs.Bucket; +import com.exasol.udfdebugging.*; +import com.exasol.udfdebugging.Module; +import com.exasol.udfdebugging.modules.AbstractModuleFactory; + +/** + * {@link ModuleFactory} for {@link JProfilerModule}. + */ +public class JProfilerModuleFactory extends AbstractModuleFactory { + + /** + * Create a new instance of {@link JProfilerModuleFactory}. + */ + public JProfilerModuleFactory() { + super("jprofiler"); + } + + @Override + public Module buildModule(final LocalServiceExposer localServiceExposer, final Bucket bucket, + final Connection exasolConnection) { + return new JProfilerModule(bucket); + } +} diff --git a/src/main/java/com/exasol/udfdebugging/modules/udflogs/LogRecorder.java b/src/main/java/com/exasol/udfdebugging/modules/udflogs/LogRecorder.java new file mode 100644 index 0000000..01dee15 --- /dev/null +++ b/src/main/java/com/exasol/udfdebugging/modules/udflogs/LogRecorder.java @@ -0,0 +1,117 @@ +package com.exasol.udfdebugging.modules.udflogs; + +import java.io.*; +import java.net.ServerSocket; +import java.net.Socket; +import java.nio.file.*; +import java.time.Instant; +import java.util.function.Consumer; + +import com.exasol.errorreporting.ExaError; + +/** + * This class opens a TCP socket and dumps everything to {@code STDOUT}. It is used for printing logs from the UDF. + */ +public final class LogRecorder implements AutoCloseable { + private static final Path LOG_DIRECTORY = Path.of("target/udf-logs"); + private final Server server; + + /** + * Create a new instance of {@link LogRecorder}. + * + * @param logFileHandler callback to notify when a new log file is created + */ + public LogRecorder(final Consumer logFileHandler) { + try { + if (!Files.exists(LOG_DIRECTORY)) { + Files.createDirectory(LOG_DIRECTORY); + } + this.server = new Server(logFileHandler); + new Thread(this.server).start(); + } catch (final IOException exception) { + throw new UncheckedIOException( + ExaError.messageBuilder("E-UDJ-18") + .message("Failed to start server for retrieving UDF logs.", exception).toString(), + exception); + } + } + + @Override + public void close() throws IOException { + this.server.close(); + } + + /** + * Get the port the log recorder listens on. + * + * @return port number + */ + public int getPort() { + return this.server.getPort(); + } + + private static class Server implements Runnable, Closeable { + private final ServerSocket serverSocket; + private final Consumer logFileHandler; + private boolean running = true; + + public Server(final Consumer logFileHandler) throws IOException { + this.logFileHandler = logFileHandler; + this.serverSocket = new ServerSocket(0); + } + + int getPort() { + return this.serverSocket.getLocalPort(); + } + + @Override + public void run() { + try { + while (this.running) { + final Socket client = this.serverSocket.accept(); + new Thread(new Logger(client, this.logFileHandler)).start(); + } + } catch (final IOException exception) { + // ignore + } + } + + @Override + public void close() throws IOException { + this.serverSocket.close(); + this.running = false; + } + } + + private static class Logger implements Runnable { + private final Socket socket; + private final Consumer logFileHandler; + + private Logger(final Socket socket, final Consumer logFileHandler) { + this.socket = socket; + this.logFileHandler = logFileHandler; + } + + @Override + public void run() { + try { + final Path logFile = Files.createTempFile(LOG_DIRECTORY, "udf-log-" + Instant.now().toString() + "-", + ".log"); + this.logFileHandler.accept(logFile); + Files.copy(this.socket.getInputStream(), logFile, StandardCopyOption.REPLACE_EXISTING); + } catch (final IOException exception) { + throw new UncheckedIOException( + ExaError.messageBuilder("E-UDJ-17").message("Failed to read from log stream.").toString(), + exception); + } finally { + try { + if (!this.socket.isClosed()) { + this.socket.close(); + } + } catch (final IOException e) { + // ignore + } + } + } + } +} diff --git a/src/main/java/com/exasol/udfdebugging/modules/udflogs/UdfLogsModule.java b/src/main/java/com/exasol/udfdebugging/modules/udflogs/UdfLogsModule.java new file mode 100644 index 0000000..a9ae696 --- /dev/null +++ b/src/main/java/com/exasol/udfdebugging/modules/udflogs/UdfLogsModule.java @@ -0,0 +1,84 @@ +package com.exasol.udfdebugging.modules.udflogs; + +import java.net.InetSocketAddress; +import java.nio.file.Path; +import java.sql.*; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.stream.Stream; + +import com.exasol.errorreporting.ExaError; +import com.exasol.udfdebugging.LocalServiceExposer; +import com.exasol.udfdebugging.Module; + +/** + * This module redirects the STDOUT of UDFs to files on the test host. + *

+ * For that it uses the {@code ALTER SESSION SET SCRIPT_OUTPUT_ADDRESS} command of the Exasol database. + *

+ */ +public class UdfLogsModule implements Module { + private static final Logger LOGGER = Logger.getLogger(UdfLogsModule.class.getName()); + private final LogRecorder logRecorder; + private final List capturedLogFiles = new ArrayList<>(); + + /** + * Create a new instance of {@link UdfLogsModule}. + * + * @param localServiceExposer proxy factory that makes ports of the test host available in the container + * @param exasolConnection connection to the exasol database + */ + public UdfLogsModule(final LocalServiceExposer localServiceExposer, final Connection exasolConnection) { + final Consumer logFileHandler = file -> { + this.capturedLogFiles.add(file); + LOGGER.log(Level.INFO, "Created log file for UDF output: {0}", file); + }; + this.logRecorder = new LogRecorder(logFileHandler); + final InetSocketAddress inDbAddress = localServiceExposer + .exposeLocalServiceToDatabase(this.logRecorder.getPort()); + redirectLogging(exasolConnection, inDbAddress); + } + + @Override + public Stream getJvmOptions() { + return Stream.empty(); + } + + /** + * Get all log files that were captured. + * + * @return list of captured log files. + */ + public List getCapturedLogFiles() { + return this.capturedLogFiles; + } + + private void redirectLogging(final Connection exasolConnection, final InetSocketAddress logServerAddress) { + try (final Statement statement = exasolConnection.createStatement()) { + final String logServerAddressString = logServerAddress.getHostString() + ":" + logServerAddress.getPort(); + if (logServerAddressString.contains("'")) { + throw new IllegalArgumentException(ExaError.messageBuilder("F-UDJ-19") + .message("Invalid address {{address}}. The address must not contain a quotes.", + logServerAddressString) + .toString()); + } + statement.executeUpdate("ALTER SESSION SET SCRIPT_OUTPUT_ADDRESS = '" + logServerAddressString + "';"); + } catch (final SQLException exception) { + throw new IllegalStateException( + ExaError.messageBuilder("E-UDJ-16").message("Failed to set script output address.").toString(), + exception); + } + } + + @Override + public void close() { + try { + this.logRecorder.close(); + } catch (final Exception exception) { + // at least we tried + } + } +} diff --git a/src/main/java/com/exasol/udfdebugging/modules/udflogs/UdfLogsModuleFactory.java b/src/main/java/com/exasol/udfdebugging/modules/udflogs/UdfLogsModuleFactory.java new file mode 100644 index 0000000..4a4b6d9 --- /dev/null +++ b/src/main/java/com/exasol/udfdebugging/modules/udflogs/UdfLogsModuleFactory.java @@ -0,0 +1,26 @@ +package com.exasol.udfdebugging.modules.udflogs; + +import java.sql.Connection; + +import com.exasol.bucketfs.Bucket; +import com.exasol.udfdebugging.LocalServiceExposer; +import com.exasol.udfdebugging.Module; +import com.exasol.udfdebugging.modules.AbstractModuleFactory; + +/** + * Factory for {@link UdfLogsModule}. + */ +public class UdfLogsModuleFactory extends AbstractModuleFactory { + /** + * Create a new instance of {@link UdfLogsModuleFactory}. + */ + public UdfLogsModuleFactory() { + super("udf-logs"); + } + + @Override + public Module buildModule(final LocalServiceExposer localServiceExposer, final Bucket bucket, + final Connection exasolConnection) { + return new UdfLogsModule(localServiceExposer, exasolConnection); + } +} diff --git a/src/test/java/com/exasol/udfdebugging/UdfTestSetupTest.java b/src/test/java/com/exasol/udfdebugging/UdfTestSetupTest.java new file mode 100644 index 0000000..2090a56 --- /dev/null +++ b/src/test/java/com/exasol/udfdebugging/UdfTestSetupTest.java @@ -0,0 +1,106 @@ +package com.exasol.udfdebugging; + +import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.*; + +import java.net.InetSocketAddress; +import java.sql.*; +import java.util.List; + +import org.itsallcode.junit.sysextensions.SystemOutGuard; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentMatchers; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import com.exasol.bucketfs.Bucket; +import com.exasol.exasoltestsetup.ExasolTestSetup; + +@ExtendWith(MockitoExtension.class) +@ExtendWith(SystemOutGuard.class) +class UdfTestSetupTest { + public static final String COVERAGE_PROPERTY = "test.coverage"; + public static final String DEBUG_PROPERTY = "test.debug"; + public static final String UDF_LOGS_PROPERTY = "test.udf-logs"; + private static final String EXPECTED_DEBUG_JVM_OPTION = "-agentlib:jdwp=transport=dt_socket,server=n,address=1.2.3.4:8000,suspend=y"; + @Mock + private Connection connection; + + @BeforeEach + void before() { + System.clearProperty(DEBUG_PROPERTY); + System.clearProperty(COVERAGE_PROPERTY); + System.clearProperty(UDF_LOGS_PROPERTY); + } + + @Test + void testDebuggingEnabled() { + System.setProperty(DEBUG_PROPERTY, "true"); + try (final UdfTestSetup udfTestSetup = getUdfTestSetup()) { + final List jvmOptions = List.of(udfTestSetup.getJvmOptions()); + assertThat(jvmOptions, hasItem(EXPECTED_DEBUG_JVM_OPTION)); + } + } + + private UdfTestSetup getUdfTestSetup() { + return new UdfTestSetup("1.2.3.4", mock(Bucket.class), this.connection); + } + + @Test + void testGetTestSetupForETAJ() { + System.setProperty(COVERAGE_PROPERTY, "true"); + final ExasolTestSetup testSetup = mock(ExasolTestSetup.class); + final Bucket bucket = mock(Bucket.class); + when(testSetup.getDefaultBucket()).thenReturn(bucket); + when(testSetup.makeLocalTcpServiceAccessibleFromDatabase(anyInt())) + .thenReturn(new InetSocketAddress("4.3.2.1", 123)); + try (final UdfTestSetup udfTestSetup = new UdfTestSetup(testSetup, this.connection)) { + final List jvmOptions = List.of(udfTestSetup.getJvmOptions()); + assertThat(jvmOptions, hasItem( + "-javaagent:/buckets/null/null/org.jacoco.agent-runtime.jar=output=tcpclient,address=4.3.2.1,port=123")); + } + } + + @Test + void testCoverageEnabled() { + System.setProperty(COVERAGE_PROPERTY, "true"); + try (final UdfTestSetup udfTestSetup = getUdfTestSetup()) { + final List jvmOptions = List.of(udfTestSetup.getJvmOptions()); + assertThat(jvmOptions, hasItem( + "-javaagent:/buckets/null/null/org.jacoco.agent-runtime.jar=output=tcpclient,address=1.2.3.4,port=3002")); + } + } + + @Test + @SuppressWarnings("try") // Try-with-resources variable not used in try block + void testUdfLogsEnabled() throws SQLException { + final Statement statement = mock(Statement.class); + when(this.connection.createStatement()).thenReturn(statement); + System.setProperty(UDF_LOGS_PROPERTY, "true"); + try (final UdfTestSetup udfTestSetup = getUdfTestSetup()) { + verify(statement) + .executeUpdate(ArgumentMatchers.startsWith("ALTER SESSION SET SCRIPT_OUTPUT_ADDRESS = '1.2.3.4")); + } + } + + @Test + void testAllModulesAreDisabledByDefault() { + try (final UdfTestSetup udfTestSetup = getUdfTestSetup()) { + final List jvmOptions = List.of(udfTestSetup.getJvmOptions()); + assertThat(jvmOptions.isEmpty(), equalTo(true)); + } + } + + @Test + void testDebuggingDisabled() { + System.setProperty(DEBUG_PROPERTY, "false"); + try (final UdfTestSetup udfTestSetup = getUdfTestSetup()) { + final List jvmOptions = List.of(udfTestSetup.getJvmOptions()); + assertThat(jvmOptions, not(hasItem(EXPECTED_DEBUG_JVM_OPTION))); + } + } +} diff --git a/src/test/java/com/exasol/udfdebugging/modules/TestSetup.java b/src/test/java/com/exasol/udfdebugging/modules/TestSetup.java new file mode 100644 index 0000000..21b976b --- /dev/null +++ b/src/test/java/com/exasol/udfdebugging/modules/TestSetup.java @@ -0,0 +1,68 @@ +package com.exasol.udfdebugging.modules; + +import java.io.Closeable; +import java.sql.*; +import java.util.stream.Stream; + +import com.exasol.bucketfs.Bucket; +import com.exasol.containers.ExasolContainer; +import com.exasol.dbbuilder.dialects.exasol.*; +import com.exasol.dbbuilder.dialects.exasol.udf.UdfScript; +import com.exasol.udfdebugging.LocalServiceExposer; + +/** + * This class contains common integration test setup. + */ +public class TestSetup implements Closeable, AutoCloseable { + private static final String SCHEMA_NAME = "TEST"; + private static final String UDF_NAME = "HELLO_WORLD"; + + private final ExasolContainer> exasol = new ExasolContainer<>().withReuse(true); + private final Connection connection; + + public TestSetup() throws SQLException { + this.exasol.start(); + this.connection = this.exasol.createConnection(); + } + + public LocalServiceExposer getHostPortProxy() { + return LocalServiceExposer.forHost(this.exasol.getHostIp()); + } + + public Bucket getDefaultBucket() { + return this.exasol.getDefaultBucket(); + } + + public ExasolContainer> getExasolContainer() { + return this.exasol; + } + + public Connection getConnection() { + return this.connection; + } + + public void runJavaUdf(final Stream jvmOptions, final String lineToRun) throws SQLException { + try (final Statement statement = this.connection.createStatement()) { + final ExasolObjectFactory exasolObjectFactory = new ExasolObjectFactory(this.connection, + ExasolObjectConfiguration.builder().withJvmOptions(jvmOptions.toArray(String[]::new)).build()); + final ExasolSchema schema = exasolObjectFactory.createSchema(SCHEMA_NAME); + schema.createUdfBuilder(UDF_NAME).inputType(UdfScript.InputType.SCALAR).language(UdfScript.Language.JAVA) + .content("class HELLO_WORLD {\n" + + " static String run(ExaMetadata exa, ExaIterator ctx) throws Exception {\n" + // + lineToRun + "\n" + // + " \treturn \"\";\n" + " }\n" + "}") + .returns("VARCHAR(2000)").build(); + statement.executeQuery("SELECT " + SCHEMA_NAME + "." + UDF_NAME + "()").close(); + } + } + + @Override + public void close() { + try { + this.connection.close(); + } catch (final SQLException exception) { + // at least we tried + } + this.exasol.stop(); + } +} diff --git a/src/test/java/com/exasol/udfdebugging/modules/coverage/CoverageModuleIT.java b/src/test/java/com/exasol/udfdebugging/modules/coverage/CoverageModuleIT.java new file mode 100644 index 0000000..d3233e6 --- /dev/null +++ b/src/test/java/com/exasol/udfdebugging/modules/coverage/CoverageModuleIT.java @@ -0,0 +1,52 @@ +package com.exasol.udfdebugging.modules.coverage; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import java.io.*; +import java.sql.SQLException; +import java.util.concurrent.atomic.AtomicInteger; + +import org.jacoco.core.data.ExecutionDataReader; +import org.junit.jupiter.api.Test; + +import com.exasol.errorreporting.ExaError; +import com.exasol.udfdebugging.modules.TestSetup; + +class CoverageModuleIT { + + @Test + void testCoverageReportIsWritten() throws SQLException, IOException { + deleteExecutionFile(); + try (final TestSetup udfSetup = new TestSetup(); + final CoverageModule coverageModule = new CoverageModule(udfSetup.getHostPortProxy(), + udfSetup.getDefaultBucket())) { + udfSetup.runJavaUdf(coverageModule.getJvmOptions(), ""); + assertThat(countReportedJacocoSessions(), equalTo(1)); + } + } + + private int countReportedJacocoSessions() throws IOException { + final AtomicInteger sessionCounter = new AtomicInteger(0); + try (final InputStream inputStream = new FileInputStream(JacocoServer.COVERAGE_REPORT_PATH.toFile())) { + final ExecutionDataReader reader = new ExecutionDataReader(inputStream); + reader.setSessionInfoVisitor(sessionInfo -> sessionCounter.addAndGet(1)); + reader.setExecutionDataVisitor(executionData -> { + }); + while (reader.read()) { + // just read everything to invoke the callbacks + } + } + return sessionCounter.get(); + } + + private void deleteExecutionFile() { + if (JacocoServer.COVERAGE_REPORT_PATH.toFile().exists()) { + JacocoServer.COVERAGE_REPORT_PATH.toFile().delete(); + } + if (JacocoServer.COVERAGE_REPORT_PATH.toFile().exists()) { + throw new IllegalStateException(ExaError.messageBuilder("E-UDJ-4") + .message("Failed to delete coverage file before test execution.").toString()); + } + } +} diff --git a/src/test/java/com/exasol/udfdebugging/modules/coverage/CoverageModuleTest.java b/src/test/java/com/exasol/udfdebugging/modules/coverage/CoverageModuleTest.java new file mode 100644 index 0000000..7d09754 --- /dev/null +++ b/src/test/java/com/exasol/udfdebugging/modules/coverage/CoverageModuleTest.java @@ -0,0 +1,42 @@ +package com.exasol.udfdebugging.modules.coverage; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; +import static org.mockito.Mockito.*; + +import java.io.FileNotFoundException; +import java.net.InetSocketAddress; +import java.nio.file.Path; +import java.util.concurrent.TimeoutException; +import java.util.stream.Collectors; + +import org.junit.jupiter.api.Test; + +import com.exasol.bucketfs.Bucket; +import com.exasol.bucketfs.BucketAccessException; + +class CoverageModuleTest { + + @Test + @SuppressWarnings("try") // auto-closeable resource coverageModule is never referenced in body of try statement + void testUpload() throws BucketAccessException, TimeoutException, FileNotFoundException { + final Bucket bucket = mock(Bucket.class); + try (CoverageModule coverageModule = new CoverageModule(port -> new InetSocketAddress("1.2.3.4", port), + bucket)) { + verify(bucket).uploadFile(Path.of("target", "jacoco-agent", "org.jacoco.agent-runtime.jar"), + "org.jacoco.agent-runtime.jar"); + } + } + + @Test + void testGetJvmOptions() { + final Bucket bucket = mock(Bucket.class); + when(bucket.getBucketFsName()).thenReturn("my_bucketfs"); + when(bucket.getBucketName()).thenReturn("my_bucket"); + try (final CoverageModule coverageModule = new CoverageModule(port -> new InetSocketAddress("1.2.3.4", port), + bucket)) { + assertThat(coverageModule.getJvmOptions().collect(Collectors.toList()), contains( + "-javaagent:/buckets/my_bucketfs/my_bucket/org.jacoco.agent-runtime.jar=output=tcpclient,address=1.2.3.4,port=3002")); + } + } +} diff --git a/src/test/java/com/exasol/udfdebugging/modules/jprofiler/InArchiveProfilerAgentPathDetectorTest.java b/src/test/java/com/exasol/udfdebugging/modules/jprofiler/InArchiveProfilerAgentPathDetectorTest.java new file mode 100644 index 0000000..3a12816 --- /dev/null +++ b/src/test/java/com/exasol/udfdebugging/modules/jprofiler/InArchiveProfilerAgentPathDetectorTest.java @@ -0,0 +1,17 @@ +package com.exasol.udfdebugging.modules.jprofiler; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import java.nio.file.Path; + +import org.junit.jupiter.api.Test; + +class InArchiveProfilerAgentPathDetectorTest { + @Test + void testExtractPath() { + final Path exampleArchive = Path.of("src", "test", "resources", "jprofilerArchiveMock.tar.gz"); + assertThat(new InArchiveProfilerAgentPathDetector().findPathToAgent(exampleArchive), + equalTo("subfolderA/linux-x64/libjprofilerti.so")); + } +} \ No newline at end of file diff --git a/src/test/java/com/exasol/udfdebugging/modules/jprofiler/JProfilerModuleTest.java b/src/test/java/com/exasol/udfdebugging/modules/jprofiler/JProfilerModuleTest.java new file mode 100644 index 0000000..0e33f13 --- /dev/null +++ b/src/test/java/com/exasol/udfdebugging/modules/jprofiler/JProfilerModuleTest.java @@ -0,0 +1,47 @@ +package com.exasol.udfdebugging.modules.jprofiler; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; +import static org.mockito.Mockito.*; + +import java.io.FileNotFoundException; +import java.nio.file.Path; +import java.util.concurrent.TimeoutException; +import java.util.stream.Collectors; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import com.exasol.bucketfs.Bucket; +import com.exasol.bucketfs.BucketAccessException; + +class JProfilerModuleTest { + private static final Path MOCK_AGENT_ARCHIVE = Path.of("src", "test", "resources", "jprofilerArchiveMock.tar.gz"); + + @BeforeAll + static void beforeAll() { + System.setProperty(JProfilerModule.AGENT_OPTION, MOCK_AGENT_ARCHIVE.toString()); + } + + @Test + @SuppressWarnings("try") // Try-with-resources variable not used in try block + void testUpload() throws BucketAccessException, TimeoutException, FileNotFoundException { + final Bucket bucket = mock(Bucket.class); + try (final JProfilerModule jProfilerModule = new JProfilerModule(bucket)) { + verify(bucket).uploadFile(MOCK_AGENT_ARCHIVE, "jprofiler.tar.gz"); + } + } + + @Test + void testGetJvmOptions() { + final Bucket bucket = mock(Bucket.class); + when(bucket.getBucketFsName()).thenReturn("my_bucketfs"); + when(bucket.getBucketName()).thenReturn("my_bucket"); + try (final JProfilerModule jProfilerModule = new JProfilerModule(bucket)) { + assertThat(jProfilerModule.getJvmOptions().collect(Collectors.toList()), + contains( + "-agentpath:/buckets/my_bucketfs/my_bucket/jprofiler/subfolderA/linux-x64/libjprofilerti.so" + + "=port=11002")); + } + } +} diff --git a/src/test/java/com/exasol/udfdebugging/modules/udflogs/LogRecorderTest.java b/src/test/java/com/exasol/udfdebugging/modules/udflogs/LogRecorderTest.java new file mode 100644 index 0000000..f9dad16 --- /dev/null +++ b/src/test/java/com/exasol/udfdebugging/modules/udflogs/LogRecorderTest.java @@ -0,0 +1,68 @@ +package com.exasol.udfdebugging.modules.udflogs; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasSize; +import static org.junit.jupiter.api.Assertions.assertAll; + +import java.io.*; +import java.net.Socket; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; + +import org.junit.jupiter.api.Test; + +class LogRecorderTest { + + @Test + void testLogsAreWrittenAsFile() throws Exception { + final List logFiles = new ArrayList<>(); + try (final LogRecorder logRecorder = new LogRecorder(logFiles::add); + final StreamToLogger connection = new StreamToLogger(logRecorder.getPort());) { + connection.write("test"); + assertAll(() -> assertThat(logFiles, hasSize(1)), + () -> assertThat(Files.readString(logFiles.get(0)), equalTo("test"))); + } + } + + @Test + void testParallelStreams() throws Exception { + final List logFiles = new ArrayList<>(); + try (final LogRecorder logRecorder = new LogRecorder(logFiles::add); + final StreamToLogger connection1 = new StreamToLogger(logRecorder.getPort());) { + connection1.write("test"); + assertAll(() -> assertThat(logFiles, hasSize(1)), + () -> assertThat(Files.readString(logFiles.get(0)), equalTo("test"))); + try (final StreamToLogger connection2 = new StreamToLogger(logRecorder.getPort())) { + connection2.write("other"); + assertAll(() -> assertThat(logFiles, hasSize(2)), + () -> assertThat(Files.readString(logFiles.get(1)), equalTo("other"))); + } + } + } + + private static class StreamToLogger implements Closeable { + private final Socket socket; + private final PrintWriter writer; + + public StreamToLogger(final int port) throws IOException { + this.socket = new Socket("localhost", port); + this.writer = new PrintWriter(this.socket.getOutputStream()); + } + + @SuppressWarnings("java:S2925") // sleep is required + public void write(final String message) throws InterruptedException { + this.writer.write(message); + this.writer.flush(); + Thread.sleep(400); + } + + @Override + public void close() throws IOException { + this.writer.close(); + this.socket.close(); + } + } +} diff --git a/src/test/java/com/exasol/udfdebugging/modules/udflogs/UdfLogsModuleIT.java b/src/test/java/com/exasol/udfdebugging/modules/udflogs/UdfLogsModuleIT.java new file mode 100644 index 0000000..4cb0cc4 --- /dev/null +++ b/src/test/java/com/exasol/udfdebugging/modules/udflogs/UdfLogsModuleIT.java @@ -0,0 +1,27 @@ +package com.exasol.udfdebugging.modules.udflogs; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.MatcherAssert.assertThat; + +import java.io.IOException; +import java.nio.file.Files; +import java.sql.SQLException; + +import org.junit.jupiter.api.Test; + +import com.exasol.udfdebugging.modules.TestSetup; + +class UdfLogsModuleIT { + + // This will fail when the test does not run on Docker host, e.g. on Windows or macOS. + @Test + void testGetLog() throws SQLException, IOException { + try (final TestSetup testSetup = new TestSetup(); + final UdfLogsModule logsModule = new UdfLogsModule(testSetup.getHostPortProxy(), + testSetup.getConnection());) { + testSetup.runJavaUdf(logsModule.getJvmOptions(), "System.out.println(\"hello from udf\");"); + final String log = Files.readString(logsModule.getCapturedLogFiles().get(0)); + assertThat(log, containsString("hello from udf")); + } + } +} \ No newline at end of file diff --git a/src/test/java/com/exasol/udfdebugging/modules/udflogs/UdfLogsModuleTest.java b/src/test/java/com/exasol/udfdebugging/modules/udflogs/UdfLogsModuleTest.java new file mode 100644 index 0000000..c519223 --- /dev/null +++ b/src/test/java/com/exasol/udfdebugging/modules/udflogs/UdfLogsModuleTest.java @@ -0,0 +1,54 @@ +package com.exasol.udfdebugging.modules.udflogs; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.when; + +import java.net.InetSocketAddress; +import java.sql.*; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import com.exasol.udfdebugging.LocalServiceExposer; + +@ExtendWith(MockitoExtension.class) +class UdfLogsModuleTest { + @Mock + private LocalServiceExposer localServiceExposer; + @Mock + private Connection connection; + @Mock + private Statement statement; + + @BeforeEach + void setUp() throws SQLException { + when(this.connection.createStatement()).thenReturn(this.statement); + } + + @Test + void testSQlException() throws SQLException { + when(this.localServiceExposer.exposeLocalServiceToDatabase(anyInt())) + .thenReturn(new InetSocketAddress("my-host", 1234)); + when(this.statement.executeUpdate(anyString())).thenThrow(new SQLException("mock exception")); + final IllegalStateException exception = assertThrows(IllegalStateException.class, + () -> new UdfLogsModule(this.localServiceExposer, this.connection)); + assertThat(exception.getMessage(), equalTo("E-UDJ-16: Failed to set script output address.")); + } + + @Test + void testSqlInjection() { + when(this.localServiceExposer.exposeLocalServiceToDatabase(anyInt())) + .thenReturn(new InetSocketAddress("my-ho' + 'st", 1234)); + final IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, + () -> new UdfLogsModule(this.localServiceExposer, this.connection)); + assertThat(exception.getMessage(), + equalTo("F-UDJ-19: Invalid address 'my-ho' + 'st:1234'. The address must not contain a quotes.")); + } +} \ No newline at end of file diff --git a/src/test/resources/jprofilerArchiveMock.tar.gz b/src/test/resources/jprofilerArchiveMock.tar.gz new file mode 100644 index 0000000..8f99ba8 Binary files /dev/null and b/src/test/resources/jprofilerArchiveMock.tar.gz differ diff --git a/src/test/resources/logging.properties b/src/test/resources/logging.properties index ad3bc9a..8d41bf2 100644 --- a/src/test/resources/logging.properties +++ b/src/test/resources/logging.properties @@ -2,5 +2,5 @@ handlers=java.util.logging.ConsoleHandler .level=INFO java.util.logging.ConsoleHandler.level=ALL java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter -java.util.logging.SimpleFormatter.format=%1$tF %1$tT.%1$tL [%4$-7s] %5$s %n -com.exasol=ALL \ No newline at end of file +java.util.logging.SimpleFormatter.format=%1$tF %1$tT.%1$tL [%4$-7s] %5$s %6$s%n +com.exasol.level=ALL diff --git a/versionsMavenPluginRules.xml b/versionsMavenPluginRules.xml index c566b42..35bd03d 100644 --- a/versionsMavenPluginRules.xml +++ b/versionsMavenPluginRules.xml @@ -4,13 +4,14 @@ xsi:schemaLocation="http://mojo.codehaus.org/versions-maven-plugin/rule/2.0.0 http://mojo.codehaus.org/versions-maven-plugin/xsd/rule-2.0.0.xsd"> - (?i).*Alpha(?:-?\d+)? - (?i).*a(?:-?\d+)? - (?i).*Beta(?:-?\d+)? - (?i).*-B(?:-?\d+)? - (?i).*RC(?:-?\d+)? - (?i).*CR(?:-?\d+)? - (?i).*M(?:-?\d+)? + (?i).*Alpha(?:-?[\d.]+)? + (?i).*a(?:-?[\d.]+)? + (?i).*Beta(?:-?[\d.]+)? + (?i).*-B(?:-?[\d.]+)? + (?i).*-b(?:-?[\d.]+)? + (?i).*RC(?:-?[\d.]+)? + (?i).*CR(?:-?[\d.]+)? + (?i).*M(?:-?[\d.]+)?