This is an automated email from the ASF dual-hosted git repository.

hsluoyz pushed a commit to branch master
in repository 
https://gitbox.apache.org/repos/asf/casbin-jcasbin-jdbc-adapter.git


The following commit(s) were added to refs/heads/master by this push:
     new 0b24efa  build: prepare Apache release with tag-driven version
0b24efa is described below

commit 0b24efa59abc205110311978e8a7b63ea113d44f
Author: Yang Luo <[email protected]>
AuthorDate: Thu Sep 17 22:47:35 2026 +0800

    build: prepare Apache release with tag-driven version
---
 .github/scripts/test_verify_release.py             | 147 ++++++++++
 .github/scripts/verify_release.py                  | 109 ++++++++
 .github/workflows/maven-ci.yml                     |  33 ++-
 .github/workflows/maven-publish.yml                |  89 ++++++
 .github/workflows/release.yml                      | 309 +++++++++++++--------
 .gitignore                                         |   9 +-
 README.md                                          |  39 +++
 RELEASING.md                                       | 124 +++++++++
 examples/rbac_model.conf                           |  17 ++
 examples/rbac_policy.csv                           |  17 ++
 examples/rbac_with_domains_model.conf              |  17 ++
 examples/rbac_with_domains_policy.csv              |  17 ++
 pom.xml                                            | 129 +++++++--
 src/main/java/org/casbin/adapter/JDBCAdapter.java  |  25 +-
 .../java/org/casbin/adapter/JDBCBaseAdapter.java   |  25 +-
 .../java/org/casbin/adapter/JDBCDataSource.java    |  25 +-
 .../java/org/casbin/adapter/AdapterCreator.java    |  48 +---
 .../java/org/casbin/adapter/JDBCAdapterTest.java   |  25 +-
 .../org/casbin/adapter/JDBCAdapterTestSets.java    |  25 +-
 19 files changed, 987 insertions(+), 242 deletions(-)

diff --git a/.github/scripts/test_verify_release.py 
b/.github/scripts/test_verify_release.py
new file mode 100644
index 0000000..4efffdd
--- /dev/null
+++ b/.github/scripts/test_verify_release.py
@@ -0,0 +1,147 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+#     https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+import hashlib
+import io
+import os
+from pathlib import Path
+import subprocess
+import tarfile
+import tempfile
+import unittest
+from unittest.mock import patch
+import zipfile
+
+import verify_release as release
+
+
+class ReleaseVerificationTest(unittest.TestCase):
+    def setUp(self):
+        self.temp = tempfile.TemporaryDirectory()
+        self.addCleanup(self.temp.cleanup)
+        self.previous = Path.cwd()
+        self.repo = Path(self.temp.name)
+        os.chdir(self.repo)
+        self.addCleanup(os.chdir, self.previous)
+        self.git('init', '-q')
+        Path('pom.xml').write_text('<project 
xmlns="http://maven.apache.org/POM/4.0.0";><version>${revision}</version></project>')
+        Path('LICENSE').write_text('Test fixture')
+        self.git('add', '.')
+        self.git('-c', 'user.name=Release test', '-c', 
'[email protected]', 'commit', '-qm', 'test: fixture')
+        self.name = 'apache-casbin-' + release.COMPONENT + 
'-1.0.0-incubating-src'
+        self.remote = {release.ASF + 'KEYS': b'test public key'}
+        for extension in ('tar.gz', 'zip'):
+            data = self.git('archive', '--format=' + extension, '--prefix=' + 
self.name + '/', 'HEAD')
+            self.put_archive(extension, data)
+
+    def git(self, *args):
+        return subprocess.check_output(['git', *args], stderr=subprocess.PIPE)
+
+    def put_archive(self, extension, data):
+        filename = self.name + '.' + extension
+        url = release.ASF + release.COMPONENT + '-1.0.0-incubating/' + filename
+        self.remote[url] = data
+        self.remote[url + '.sha512'] = (hashlib.sha512(data).hexdigest() + '  
' + filename + '\n').encode()
+        self.remote[url + '.asc'] = b'test signature'
+
+    def invoke(self, signature_error=None):
+        # No live downloads or signing material: exercise real Git/archive/hash
+        # verification and inject only the external network/GPG boundaries.
+        real_run = subprocess.run
+        def run_command(command, **kwargs):
+            if command[0] == 'gpg':
+                return subprocess.CompletedProcess(command, 0)
+            return real_run(command, **kwargs)
+        with patch.object(release, 'download', 
side_effect=self.remote.__getitem__), \
+             patch.object(release.subprocess, 'run', side_effect=run_command) 
as calls, \
+             patch.object(release, 'verify_signature', 
side_effect=signature_error) as signature:
+            release.verify('1.0.0', Path('dist'))
+        self.assertEqual(sum(call.args[0][0] == 'gpg' for call in 
calls.call_args_list), 1)
+        self.assertEqual(signature.call_count, 2)
+
+    def test_preserves_all_six_promoted_files(self):
+        self.invoke()
+        files = list(Path('dist').iterdir())
+        self.assertEqual(len(files), 6)
+        for file in files:
+            self.assertEqual(file.read_bytes(), self.remote[release.ASF + 
release.COMPONENT + '-1.0.0-incubating/' + file.name])
+
+    def test_rejects_missing_signature(self):
+        self.remote.pop(release.ASF + release.COMPONENT + '-1.0.0-incubating/' 
+ self.name + '.tar.gz.asc')
+        with self.assertRaises(KeyError):
+            self.invoke()
+
+    def test_rejects_signature_failure(self):
+        with self.assertRaises(subprocess.CalledProcessError):
+            self.invoke(subprocess.CalledProcessError(1, 'gpg'))
+
+    def test_rejects_corrupt_archive(self):
+        self.remote[release.ASF + release.COMPONENT + '-1.0.0-incubating/' + 
self.name + '.tar.gz'] += b'corrupt'
+        with self.assertRaises(ValueError):
+            self.invoke()
+
+    def test_rejects_different_source_with_valid_checksum(self):
+        Path('LICENSE').write_text('Changed after vote')
+        self.git('add', 'LICENSE')
+        self.git('-c', 'user.name=Release test', '-c', 
'[email protected]', 'commit', '-qm', 'test: changed tree')
+        with self.assertRaises(ValueError):
+            self.invoke()
+
+    def test_rejects_zip_missing_file_with_valid_checksum(self):
+        buf = io.BytesIO()
+        with zipfile.ZipFile(buf, 'w') as archive:
+            archive.writestr(self.name + '/pom.xml', 
Path('pom.xml').read_bytes())
+        self.put_archive('zip', buf.getvalue())
+        with self.assertRaises(ValueError):
+            self.invoke()
+
+    def test_rejects_overwriting_existing_output(self):
+        Path('dist').mkdir()
+        Path('dist/sentinel').write_text('keep')
+        with self.assertRaises(FileExistsError):
+            self.invoke()
+        self.assertEqual(Path('dist/sentinel').read_text(), 'keep')
+
+    def test_rejects_invalid_version_before_network(self):
+        for version in ('1.0.0-rc1', '../1.0.0', 'v1.0.0'):
+            with self.subTest(version=version), patch.object(release, 
'download') as network:
+                with self.assertRaises(ValueError):
+                    release.verify(version, Path('dist'))
+                network.assert_not_called()
+
+    def test_rejects_bad_checksum_filename(self):
+        with self.assertRaises(ValueError):
+            release.check_checksum(b'x', (hashlib.sha512(b'x').hexdigest() + ' 
 other\n').encode(), 'expected')
+
+    def test_rejects_archive_traversal_and_links(self):
+        for name, kind in (('../escape', tarfile.REGTYPE), ('root/link', 
tarfile.SYMTYPE)):
+            buf = io.BytesIO()
+            with tarfile.open(fileobj=buf, mode='w') as archive:
+                item = tarfile.TarInfo(name)
+                item.type = kind
+                archive.addfile(item)
+            with self.assertRaises(ValueError):
+                release.source_files(buf.getvalue(), 'tar')
+
+    def test_gpg_verification_is_checked_and_uses_isolated_home(self):
+        with patch.object(release.subprocess, 'run') as gpg:
+            release.verify_signature(Path('isolated'), Path('source.asc'), 
Path('source'))
+        gpg.assert_called_once_with(['gpg', '--batch', '--homedir', 
'isolated', '--verify', 'source.asc', 'source'], check=True)
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/.github/scripts/verify_release.py 
b/.github/scripts/verify_release.py
new file mode 100644
index 0000000..dca03bf
--- /dev/null
+++ b/.github/scripts/verify_release.py
@@ -0,0 +1,109 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+#     https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+"""Verify promoted ASF source files before GitHub or Maven publication."""
+
+import argparse
+import hashlib
+import io
+from pathlib import Path, PurePosixPath
+import re
+import subprocess
+import tarfile
+import tempfile
+import urllib.request
+import zipfile
+
+ASF = 'https://downloads.apache.org/incubator/casbin/'
+COMPONENT = 'jcasbin-jdbc-adapter'
+
+
+def source_files(data, extension):
+    files = {}
+    def safe_name(name):
+        if '\\' in name or PurePosixPath(name).is_absolute() or '..' in 
PurePosixPath(name).parts:
+            raise ValueError('Unsafe archive path')
+    if extension == 'zip':
+        with zipfile.ZipFile(io.BytesIO(data)) as archive:
+            for item in archive.infolist():
+                safe_name(item.filename)
+                if (item.external_attr >> 16) & 0o170000 == 0o120000:
+                    raise ValueError('ZIP symlink is unsupported')
+                if not item.is_dir():
+                    if item.filename in files:
+                        raise ValueError('Duplicate ZIP member')
+                    files[item.filename] = archive.read(item)
+    else:
+        with tarfile.open(fileobj=io.BytesIO(data), mode='r:*') as archive:
+            for item in archive:
+                safe_name(item.name)
+                if item.isdir():
+                    continue
+                if not item.isfile() or item.name in files:
+                    raise ValueError('Unsupported or duplicate TAR member')
+                files[item.name] = archive.extractfile(item).read()
+    return files
+
+
+def check_checksum(data, checksum, filename):
+    match = re.fullmatch(r'([0-9a-fA-F]{128}) [ *]' + re.escape(filename) + 
r'\r?\n?', checksum.decode('ascii'))
+    if not match or hashlib.sha512(data).hexdigest() != match[1].lower():
+        raise ValueError('Invalid SHA-512 for ' + filename)
+
+
+def download(url):
+    with urllib.request.urlopen(url, timeout=60) as response:
+        return response.read()
+
+
+def verify_signature(home, signature, archive):
+    subprocess.run(['gpg', '--batch', '--homedir', str(home), '--verify', 
str(signature), str(archive)], check=True)
+
+
+def verify(version, output):
+    if not re.fullmatch(r'[0-9]+\.[0-9]+\.[0-9]+', version):
+        raise ValueError('Expected final version X.Y.Z')
+    commit = subprocess.check_output(['git', 'rev-parse', 'HEAD'], 
text=True).strip()
+    name = 'apache-casbin-' + COMPONENT + '-' + version + '-incubating-src'
+    expected = source_files(subprocess.check_output(['git', 'archive', 
'--format=tar', '--prefix=' + name + '/', commit]), 'tar')
+    output.mkdir(parents=True, exist_ok=False)
+    url = ASF + COMPONENT + '-' + version + '-incubating/'
+    with tempfile.TemporaryDirectory(prefix=COMPONENT + '-public-keys-') as 
temp:
+        home = Path(temp)
+        home.chmod(0o700)
+        keys = home / 'KEYS'
+        keys.write_bytes(download(ASF + 'KEYS'))
+        subprocess.run(['gpg', '--batch', '--homedir', str(home), '--import', 
str(keys)], check=True)
+        for extension in ('tar.gz', 'zip'):
+            filename = name + '.' + extension
+            archive = output / filename
+            for suffix in ('', '.sha512', '.asc'):
+                (output / (filename + suffix)).write_bytes(download(url + 
filename + suffix))
+            data = archive.read_bytes()
+            check_checksum(data, (output / (filename + 
'.sha512')).read_bytes(), filename)
+            verify_signature(home, output / (filename + '.asc'), archive)
+            if source_files(data, extension) != expected:
+                raise ValueError('Promoted archive does not match final Git 
commit: ' + filename)
+    print('Verified promoted ASF originals for ' + commit)
+
+
+if __name__ == '__main__':
+    parser = argparse.ArgumentParser(description=__doc__)
+    parser.add_argument('version')
+    parser.add_argument('--output', type=Path, default=Path('dist'))
+    args = parser.parse_args()
+    verify(args.version, args.output)
diff --git a/.github/workflows/maven-ci.yml b/.github/workflows/maven-ci.yml
index e1b1d9f..57f59d6 100644
--- a/.github/workflows/maven-ci.yml
+++ b/.github/workflows/maven-ci.yml
@@ -1,3 +1,20 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+#     https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
 name: build
 
 on: [push, pull_request]
@@ -35,7 +52,7 @@ jobs:
 
     steps:
       - name: Checkout
-        uses: actions/checkout@v2
+        uses: actions/checkout@v4
         with:
           fetch-depth: '0'
 
@@ -50,15 +67,19 @@ jobs:
       - name: Create database for sqlserver
         run: /opt/mssql-tools18/bin/sqlcmd -S 127.0.0.1,1433 -U sa -P 
'9G3iqmzQDw9zCXII' -Q "CREATE DATABASE casbin" -C
 
-      - name: Set up JDK 1.8
-        uses: actions/setup-java@v1
+      - name: Set up JDK 8
+        uses: actions/setup-java@v4
         with:
-          java-version: 1.8
+          distribution: temurin
+          java-version: 8
 
       - name: Build with Maven
-        run: mvn clean test cobertura:cobertura
+        run: mvn -B -ntp clean verify cobertura:cobertura -Dgpg.skip=true
+
+      - name: Test release verification
+        run: python3 -m unittest discover -s .github/scripts -p 'test_*.py'
 
       - name: Codecov
-        uses: codecov/codecov-action@v1
+        uses: codecov/codecov-action@v5
         with:
           token: ${{ secrets.CODECOV_TOKEN }}
diff --git a/.github/workflows/maven-publish.yml 
b/.github/workflows/maven-publish.yml
new file mode 100644
index 0000000..a7124be
--- /dev/null
+++ b/.github/workflows/maven-publish.yml
@@ -0,0 +1,89 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+#     https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+name: Publish Maven
+
+on:
+  workflow_call:
+    inputs:
+      maven_version:
+        required: true
+        type: string
+  workflow_dispatch:
+    inputs:
+      maven_version:
+        description: Maven release version to publish, for example 2.14.0
+        required: true
+        type: string
+
+permissions:
+  contents: read
+
+jobs:
+  publish-maven:
+    name: Publish Maven
+    if: ${{ github.repository == 'apache/casbin-jcasbin-jdbc-adapter' }}
+    runs-on: ubuntu-latest
+    concurrency:
+      group: maven-${{ github.ref }}
+      cancel-in-progress: false
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v4
+        with:
+          fetch-depth: 0
+
+      - name: Verify the requested release version
+        env:
+          MAVEN_VERSION: ${{ inputs.maven_version }}
+        run: |
+          set -euo pipefail
+          python3 - <<'PY'
+          import os
+          import re
+          requested = os.environ['MAVEN_VERSION']
+          if not re.fullmatch(r'[0-9]+\.[0-9]+\.[0-9]+', requested):
+              raise SystemExit('Expected a final Maven release version X.Y.Z')
+          if os.environ['GITHUB_REF'] != f'refs/tags/v{requested}':
+              raise SystemExit('Publish only from the matching final release 
tag after the vote')
+          PY
+
+      - name: Verify promoted ASF release before loading signing credentials
+        env:
+          MAVEN_VERSION: ${{ inputs.maven_version }}
+        run: python3 .github/scripts/verify_release.py "${MAVEN_VERSION}" 
--output verified-release
+
+      - name: Set up JDK 1.8
+        uses: actions/setup-java@v4
+        with:
+          distribution: temurin
+          java-version: 8
+          server-id: ossrh
+          server-username: OSSRH_JIRA_USERNAME
+          server-password: OSSRH_JIRA_PASSWORD
+          gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }}
+          gpg-passphrase: GPG_PASSPHRASE
+
+      - name: Publish Maven
+        run: |
+          mvn -B -ntp deploy -DskipTests "-Drevision=${MAVEN_VERSION}"
+        env:
+          MAVEN_VERSION: ${{ inputs.maven_version }}
+          GPG_KEY_NAME: ${{ secrets.GPG_KEY_NAME }}
+          GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
+          OSSRH_JIRA_USERNAME: ${{ secrets.OSSRH_JIRA_USERNAME }}
+          OSSRH_JIRA_PASSWORD: ${{ secrets.OSSRH_JIRA_PASSWORD }}
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index d2c64a8..dbd4111 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -1,155 +1,222 @@
-name: release
-
-# Releases are triggered manually, by pushing a git tag. There is no automatic
-# release on merge/commit: as an Apache (incubating) project, every release 
must
-# pass a formal vote before it can be published.
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+#     https://www.apache.org/licenses/LICENSE-2.0
 #
-#   v1.4.0-rc1  -> GitHub *pre-release* only (the candidate used for voting)
-#   v1.4.0      -> GitHub release + publish to Maven Central
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+name: Release
+
+# Releases are cut manually by pushing a git tag:
+#   v2.14.0-rc1 -> GitHub pre-release only (source package for the Apache vote)
+#   v2.14.0     -> GitHub release + publish to Maven Central
 #
-# In both cases the release carries the source package that the release manager
-# downloads, signs locally (.asc / .sha512) and uploads to dist.apache.org for
-# the vote. This workflow deliberately does not touch anything on the Apache
-# side - no signing, no svn, no re-upload of signed artifacts.
+# The release manager downloads the source package from the release, signs it
+# locally, and uses it for voting. This workflow does not sign anything.
+# Push the final tag only after the voted originals have been promoted to
+# downloads.apache.org/incubator/casbin/jcasbin-jdbc-adapter-X.Y.Z-incubating/.
 
 on:
   push:
     tags:
-      - 'v*'
+      - "v*"
 
 permissions:
   contents: write
 
+concurrency:
+  group: release-${{ github.ref }}
+  cancel-in-progress: false
+
 jobs:
-  release:
+  prepare:
+    name: Prepare Release
+    if: ${{ github.repository == 'apache/casbin-jcasbin-jdbc-adapter' }}
     runs-on: ubuntu-latest
+    outputs:
+      tag: ${{ steps.meta.outputs.tag }}
+      version: ${{ steps.meta.outputs.version }}
+      maven_version: ${{ steps.meta.outputs.maven_version }}
+      basename: ${{ steps.meta.outputs.basename }}
+      prerelease: ${{ steps.meta.outputs.prerelease }}
+      previous_tag: ${{ steps.meta.outputs.previous_tag }}
     steps:
       - name: Checkout
         uses: actions/checkout@v4
+        with:
+          fetch-depth: 0
 
-      - name: Resolve version from tag
-        id: version
+      - name: Compute release metadata
+        id: meta
         run: |
           set -euo pipefail
-          TAG="${GITHUB_REF_NAME}"
-          if [[ ! "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-rc[0-9]+)?$ ]]; then
-            echo "::error::Tag '$TAG' has an unexpected format. Use v<x.y.z> 
(e.g. v1.4.0) or v<x.y.z>-rc<n> (e.g. v1.4.0-rc1)."
-            exit 1
-          fi
+          TAG_NAME="${GITHUB_REF_NAME}"
 
-          BASE="${TAG#v}"           # 1.4.0  |  1.4.0-rc1
-          VERSION="${BASE%%-rc*}"   # 1.4.0
-          if [[ "$BASE" == *-rc* ]]; then
-            IS_RC=true
-            RC="${BASE##*-}"        # rc1
+          if [[ "${TAG_NAME}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
+            PRERELEASE=false
+          elif [[ "${TAG_NAME}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+-rc[0-9]+$ ]]; then
+            PRERELEASE=true
           else
-            IS_RC=false
-            RC=""
+            echo "Unsupported release tag: ${TAG_NAME}. Use v2.14.0 or 
v2.14.0-rc1." >&2
+            exit 1
           fi
 
-          # The Maven coordinates keep the plain version - the "-incubating"
-          # suffix is only carried by the Apache source package, which is the
-          # artifact the incubator actually votes on.
-          #
-          # Apache source package naming: apache-<project>-<version>-src.tar.gz
-          # The RC number is not part of the file name, it only appears in the
-          # vote thread and in the dist.apache.org staging path.
-          SRC_NAME="apache-casbin-jdbc-adapter-${VERSION}-incubating-src"
-
-          {
-            echo "tag=$TAG"
-            echo "is_rc=$IS_RC"
-            echo "rc=$RC"
-            echo "version=$VERSION"
-            echo "src_name=$SRC_NAME"
-          } >> "$GITHUB_OUTPUT"
-
-          echo "Tag=$TAG version=$VERSION is_rc=$IS_RC ${RC:+rc=$RC}"
-
-      - name: Set up JDK 1.8
-        uses: actions/setup-java@v4
+          VERSION="${TAG_NAME#v}"
+          BASE_VERSION="${VERSION%%-rc*}"
+          # Keep the voted source bytes stable when the same commit is 
promoted.
+          
BASENAME="apache-casbin-jcasbin-jdbc-adapter-${BASE_VERSION}-incubating-src"
+          PREVIOUS_TAG="$(
+            {
+              git tag --list 'v*' | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$'
+              echo "v${BASE_VERSION}"
+            } |
+              sort -V -u |
+              awk -v current="v${BASE_VERSION}" '
+                $0 == current {
+                  print previous
+                  exit
+                }
+                {
+                  previous = $0
+                }
+              '
+          )"
+
+          echo "tag=${TAG_NAME}" >> "${GITHUB_OUTPUT}"
+          echo "version=${VERSION}" >> "${GITHUB_OUTPUT}"
+          echo "maven_version=${BASE_VERSION}" >> "${GITHUB_OUTPUT}"
+          echo "basename=${BASENAME}" >> "${GITHUB_OUTPUT}"
+          echo "prerelease=${PRERELEASE}" >> "${GITHUB_OUTPUT}"
+          echo "previous_tag=${PREVIOUS_TAG}" >> "${GITHUB_OUTPUT}"
+
+          echo "Tag: ${TAG_NAME} (pre-release: ${PRERELEASE})"
+          echo "Source package: ${BASENAME}.tar.gz"
+
+  github-release:
+    name: GitHub Release
+    needs: prepare
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v4
         with:
-          distribution: temurin
-          java-version: '8'
-          server-id: ossrh
-          server-username: MAVEN_USERNAME
-          server-password: MAVEN_PASSWORD
-          gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }}
-          gpg-passphrase: MAVEN_GPG_PASSPHRASE
-
-      - name: Stamp the release version into the POM
-        run: mvn -B versions:set -DnewVersion=${{ 
steps.version.outputs.version }} -DgenerateBackupPoms=false
-
-      - name: Build the source package
-        env:
-          SRC_NAME: ${{ steps.version.outputs.src_name }}
-        run: |
-          set -euo pipefail
-          # The file list comes from git, so the package holds exactly the
-          # tracked sources of the tag - no build output, no VCS metadata.
-          # The contents are read from the working tree, so the POM already
-          # carries the release version and the package builds as-is.
-          git ls-files -z | tar --null -T - \
-            --transform "s,^,$SRC_NAME/," \
-            -czf "$SRC_NAME.tar.gz"
-          ls -l "$SRC_NAME.tar.gz"
-          tar -tzf "$SRC_NAME.tar.gz"
-
-      # Only a passed vote may be published, so release candidates never reach
-      # the package registry.
-      - name: Publish to Maven Central
-        if: steps.version.outputs.is_rc == 'false'
-        env:
-          MAVEN_USERNAME: ${{ secrets.OSSRH_JIRA_USERNAME }}
-          MAVEN_PASSWORD: ${{ secrets.OSSRH_JIRA_PASSWORD }}
-          MAVEN_GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
-        run: mvn -B clean deploy -DskipTests
+          fetch-depth: 0
 
-      - name: Write release notes
+      - name: Generate release notes
         env:
-          TAG: ${{ steps.version.outputs.tag }}
-          IS_RC: ${{ steps.version.outputs.is_rc }}
-          RC: ${{ steps.version.outputs.rc }}
-          VERSION: ${{ steps.version.outputs.version }}
-          SRC_NAME: ${{ steps.version.outputs.src_name }}
+          CURRENT_TAG: ${{ needs.prepare.outputs.tag }}
+          CURRENT_VERSION: ${{ needs.prepare.outputs.version }}
+          PREVIOUS_TAG: ${{ needs.prepare.outputs.previous_tag }}
+          PRERELEASE: ${{ needs.prepare.outputs.prerelease }}
         run: |
-          set -euo pipefail
-          if [[ "$IS_RC" == "true" ]]; then
-            cat > release-notes.md <<EOF
-          Release candidate \`$RC\` for **$VERSION**.
-
-          This is *not* an official Apache release. It is the candidate put up 
for
-          the Apache Casbin (incubating) release vote, published here so the 
release
-          manager can download \`$SRC_NAME.tar.gz\`, sign it locally and stage 
it on
-          dist.apache.org. It is not published to Maven Central.
-          EOF
-          else
-            cat > release-notes.md <<EOF
-          Apache Casbin (incubating) JDBC Adapter **$VERSION**.
+          RELEASE_DATE="$(date -u +%F)"
+          RANGE="${CURRENT_TAG}"
 
-          The source package \`$SRC_NAME.tar.gz\` is attached, and the 
convenience
-          binaries are published to Maven Central as 
\`org.casbin:jdbc-adapter:$VERSION\`.
-          EOF
+          if [ -n "${PREVIOUS_TAG}" ]; then
+            RANGE="${PREVIOUS_TAG}..${CURRENT_TAG}"
           fi
-          cat release-notes.md
 
-      - name: Publish GitHub pre-release (RC)
-        if: steps.version.outputs.is_rc == 'true'
+          FEATURES="$(git log --pretty=format:'%s (%h)' "${RANGE}" | grep -Ei 
'^(feat)(\(.+\))?: ' || true)"
+          FIXES="$(git log --pretty=format:'%s (%h)' "${RANGE}" | grep -Ei 
'^(fix)(\(.+\))?: ' || true)"
+          DOCS="$(git log --pretty=format:'%s (%h)' "${RANGE}" | grep -Ei 
'^(docs?|doc)(\(.+\))?: ' || true)"
+
+          {
+            if [ -n "${PREVIOUS_TAG}" ]; then
+              echo "# 
[${CURRENT_VERSION}](https://github.com/${GITHUB_REPOSITORY}/compare/${PREVIOUS_TAG}...${CURRENT_TAG})
 (${RELEASE_DATE})"
+            else
+              echo "# ${CURRENT_VERSION} (${RELEASE_DATE})"
+            fi
+            echo
+
+            if [ "${PRERELEASE}" = "true" ]; then
+              echo "Release candidate for the Apache voting process. This is 
not a released version."
+              echo
+            fi
+
+            if [ -n "${PREVIOUS_TAG}" ]; then
+              echo "Changes since ${PREVIOUS_TAG}."
+              echo
+            fi
+
+            if [ -n "${FEATURES}" ]; then
+              echo "## Features"
+              echo
+              printf '%s\n' "${FEATURES}" | sed 's/^/- /'
+              echo
+            fi
+
+            if [ -n "${FIXES}" ]; then
+              echo "## Fixes"
+              echo
+              printf '%s\n' "${FIXES}" | sed 's/^/- /'
+              echo
+            fi
+
+            if [ -n "${DOCS}" ]; then
+              echo "## Docs"
+              echo
+              printf '%s\n' "${DOCS}" | sed 's/^/- /'
+              echo
+            fi
+
+            if [ -z "${FEATURES}${FIXES}${DOCS}" ]; then
+              echo "## Notes"
+              echo
+              echo "- No feat/fix/doc commits were found in this release 
range."
+            fi
+          } > RELEASE_NOTES.md
+
+      - name: Create source packages
+        if: needs.prepare.outputs.prerelease == 'true'
         env:
-          GH_TOKEN: ${{ github.token }}
+          TAG: ${{ needs.prepare.outputs.tag }}
+          BASENAME: ${{ needs.prepare.outputs.basename }}
         run: |
-          gh release create "${{ steps.version.outputs.tag }}" \
-            "${{ steps.version.outputs.src_name }}.tar.gz" \
-            --title "${{ steps.version.outputs.tag }}" \
-            --notes-file release-notes.md \
-            --prerelease
-
-      - name: Publish GitHub release
-        if: steps.version.outputs.is_rc == 'false'
+          mkdir -p dist
+          git archive --format=tar.gz --prefix="${BASENAME}/" -o 
"dist/${BASENAME}.tar.gz" "${TAG}"
+          git archive --format=zip --prefix="${BASENAME}/" -o 
"dist/${BASENAME}.zip" "${TAG}"
+          cd dist
+          sha512sum "${BASENAME}.tar.gz" > "${BASENAME}.tar.gz.sha512"
+          sha512sum "${BASENAME}.zip" > "${BASENAME}.zip.sha512"
+
+      - name: Verify and reuse promoted ASF source packages
+        if: needs.prepare.outputs.prerelease == 'false'
+        env:
+          VERSION: ${{ needs.prepare.outputs.maven_version }}
+        run: python3 .github/scripts/verify_release.py "${VERSION}"
+
+      - name: Create GitHub release
         env:
           GH_TOKEN: ${{ github.token }}
+          TAG: ${{ needs.prepare.outputs.tag }}
+          PRERELEASE: ${{ needs.prepare.outputs.prerelease }}
         run: |
-          gh release create "${{ steps.version.outputs.tag }}" \
-            "${{ steps.version.outputs.src_name }}.tar.gz" \
-            --title "${{ steps.version.outputs.tag }}" \
-            --notes-file release-notes.md
+          set -euo pipefail
+          FLAGS=()
+          if [ "${PRERELEASE}" = "true" ]; then
+            FLAGS+=(--prerelease --latest=false)
+          fi
+          # Creation fails if this release exists; never replace its assets.
+          gh release create "${TAG}" dist/* --verify-tag \
+            --title "jCasbin JDBC Adapter ${TAG}" --notes-file 
RELEASE_NOTES.md "${FLAGS[@]}"
+
+  publish-maven:
+    name: Publish Maven
+    needs:
+      - prepare
+      - github-release
+    if: ${{ needs.prepare.outputs.prerelease == 'false' }}
+    uses: ./.github/workflows/maven-publish.yml
+    with:
+      maven_version: ${{ needs.prepare.outputs.maven_version }}
+    secrets: inherit
diff --git a/.gitignore b/.gitignore
index da715af..9fcb3fd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -25,4 +25,11 @@ hs_err_pid*
 target
 
 .idea/
-*.iml
\ No newline at end of file
+*.iml
+
+# Python release-script caches
+__pycache__/
+*.pyc
+
+# flatten-maven-plugin output
+.flattened-pom.xml
diff --git a/README.md b/README.md
index fa7a6e4..8b48b3b 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,22 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+    https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+
 JDBC Adapter
 ====
 
@@ -37,6 +56,17 @@ Since version 2.0.2, jdbc-adapter adds an ``id`` field to 
the database table str
 
 If you want to upgrade to 2.0.2 - 2.2.0, you have to add the ``id`` field 
manually. It is recommended to add the ``id`` field. If you don't want to add 
the ``id`` field, please use 2.2.1+.
 
+## Oracle driver
+
+The Oracle JDBC driver is not redistributable, so this adapter does not pull it
+in as a dependency. Oracle support in the adapter itself is unchanged:
+applications using Oracle obtain a driver matching their Java and database
+versions from [Oracle JDBC 
downloads](https://www.oracle.com/database/technologies/appdev/jdbc-downloads.html),
+review its terms, and add it to their own runtime classpath. Then pass the
+configured `javax.sql.DataSource` to `new JDBCAdapter(dataSource)`, or use the
+driver-name/URL constructor. Applications using other databases need no extra
+driver, and the automated MySQL/PostgreSQL/SQL Server tests do not need Oracle.
+
 ## Simple Example
 
 ```java
@@ -87,6 +117,15 @@ public class Test {
 
 - [jCasbin](https://github.com/casbin/jcasbin)
 
+
+## Incubation status
+
+Apache Casbin (Incubating) is an effort undergoing incubation at the Apache 
Software Foundation (ASF), sponsored by the Apache Incubator PMC.
+
+Incubation is required of all newly accepted projects until a further review 
indicates that the infrastructure, communications, and decision making process 
have stabilized in a manner consistent with other successful ASF projects.
+
+While incubation status is not necessarily a reflection of the completeness or 
stability of the code, it does indicate that the project has yet to be fully 
endorsed by the ASF.
+
 ## License
 
 This project is under Apache 2.0 License. See the [LICENSE](LICENSE) file for 
the full license text.
diff --git a/RELEASING.md b/RELEASING.md
new file mode 100644
index 0000000..bdf0611
--- /dev/null
+++ b/RELEASING.md
@@ -0,0 +1,124 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+    https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+
+# Releasing the jCasbin JDBC Adapter
+
+This project follows the same release process as
+[jCasbin](https://github.com/apache/casbin-jcasbin/blob/master/RELEASING.md).
+Prepare dependency, licensing and workflow changes together in one
+release-preparation PR, and complete the scoped checks before requesting merge.
+The release workflows require Python 3 and GnuPG, provided by Ubuntu runners.
+
+## Versioning
+
+The version is **not** committed to the source tree. `pom.xml` declares
+`<version>${revision}</version>` with the placeholder `0.0.0`, and the release
+version comes from the git tag: `vX.Y.Z-rcN` and `vX.Y.Z` both map to Maven
+version `X.Y.Z`. The Maven publish job passes `-Drevision=X.Y.Z`, and
+`flatten-maven-plugin` writes the resolved version into the POM that is
+deployed to Maven Central. Nothing in the repository needs to change between
+releases except the tag.
+
+## Building and testing locally
+
+Use Java 8 and Maven 3.9.x. The tests need MySQL, PostgreSQL and SQL Server on
+the default ports 3306, 5432 and 1433, with the disposable credentials in
+`src/test/java/org/casbin/adapter/AdapterCreator.java`. Use dedicated empty
+databases; never point these tests at production data. The build does not
+require an Oracle driver and Oracle is not part of the automated test suite.
+
+```sh
+mvn -B -ntp clean verify -Dgpg.skip=true
+python3 -m unittest discover -s .github/scripts -p 'test_*.py'
+```
+
+Local artifacts carry the `0.0.0` placeholder version. To build a specific
+version locally, pass `-Drevision=X.Y.Z`. Do not use `deploy` for verification.
+
+## Before creating an RC tag
+
+1. Check the latest releases/tags and choose the next `X.Y.Z`.
+   Resolve relevant dependency updates and legal/source-archive findings in the
+   preparation PR. The approved release scope determines which changes are 
included.
+2. After merge, record the exact merged SHA and verify its build. Check the
+   final source archive with Apache RAT and review LICENSE, NOTICE, DISCLAIMER,
+   third-party material and any exclusions. New merged bytes need new evidence.
+3. Confirm that a maintainer can create the tag, the release manager can sign
+   and write the Casbin ASF distribution directories, and the signing public
+   key is in the official Casbin KEYS file.
+4. The Maven job uses existing repository secrets `GPG_PRIVATE_KEY`,
+   `GPG_PASSPHRASE`, `GPG_KEY_NAME`, `OSSRH_JIRA_USERNAME` and
+   `OSSRH_JIRA_PASSWORD`. The last two names are retained for compatibility:
+   their values must be the Central Publisher Portal user-token username and
+   password with publishing permission for `org.casbin`, not old OSSRH login
+   credentials. Check configuration without disclosing secret values.
+
+## RC and community vote
+
+Create `vX.Y.Z-rcN` at the reviewed merged SHA. The tag workflow creates a
+GitHub prerelease containing:
+
+- `apache-casbin-jcasbin-jdbc-adapter-X.Y.Z-incubating-src.tar.gz` and its 
`.sha512`;
+- `apache-casbin-jcasbin-jdbc-adapter-X.Y.Z-incubating-src.zip` and its 
`.sha512`.
+
+Download and verify these exact archives; independently inspect/unpack/build
+them. Sign **both** archives, adding each `.asc`. Stage all six files under
+`https://dist.apache.org/repos/dist/dev/incubator/casbin/jcasbin-jdbc-adapter-X.Y.Z-incubating-rcN/`.
+Verify the public downloads, signatures and checksums, then conduct the
+applicable Casbin/Incubator votes on these immutable files. Never overwrite a
+staged candidate. If candidate bytes must change, use a new RC number.
+
+GitHub refuses creation if that Release already exists. A failed or partial
+run needs its actual uploaded state inspected; do not delete and recreate a
+candidate already used for voting as a retry mechanism.
+
+## Promote and publish after approval
+
+1. Record the successful applicable vote results. Promote the same six files to
+   the ASF release directory 
`incubator/casbin/jcasbin-jdbc-adapter-X.Y.Z-incubating/`.
+2. Wait until all six files are available at
+   
`https://downloads.apache.org/incubator/casbin/jcasbin-jdbc-adapter-X.Y.Z-incubating/`.
+3. Create the final `vX.Y.Z` tag at the same reviewed RC commit. This workflow
+   downloads the promoted ASF originals, verifies SHA-512 and detached
+   signatures against Casbin KEYS, and compares both archive file sets with
+   the tagged Git source. It does not rebuild or replace those source archives.
+4. GitHub Release creation fails if the Release already exists. Maven Central
+   publishing follows only after the final GitHub Release job succeeds.
+   A Maven-only retry is available through **Publish Maven** on the matching
+   final tag. It repeats the ASF-source verification before loading private
+   signing credentials; never dispatch it from master or an RC tag. Check
+   whether the Maven version already exists before retrying a failed publish.
+5. Verify the published distributions, update download links, send the release
+   announcement as authorized, and retain the vote/artifact evidence.
+
+Missing ASF files, mismatched source, bad checksums or invalid signatures stop
+publication. Availability in ASF's release directory is an execution gate;
+the release manager remains responsible for the actual vote and promotion.
+These operations require no additional source PR after the preparation merges.
+
+## Distribution naming
+
+The ASF source archive carries the `-incubating` suffix required of podling
+releases. The Maven coordinates stay `org.casbin:jdbc-adapter` for consumer
+compatibility, matching `org.casbin:jcasbin`. Record the project's disposition
+of the [Incubator distribution 
guidance](https://incubator.apache.org/guides/distribution.html#maven-distribution)
+with the release evidence.
+
+References: [ASF release 
policy](https://www.apache.org/legal/release-policy.html)
+and [Central Maven 
publishing](https://central.sonatype.org/publish/publish-portal-maven/).
diff --git a/examples/rbac_model.conf b/examples/rbac_model.conf
index 71159e3..cca84c1 100644
--- a/examples/rbac_model.conf
+++ b/examples/rbac_model.conf
@@ -1,3 +1,20 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+#     https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
 [request_definition]
 r = sub, obj, act
 
diff --git a/examples/rbac_policy.csv b/examples/rbac_policy.csv
index f93d6df..f24fa61 100644
--- a/examples/rbac_policy.csv
+++ b/examples/rbac_policy.csv
@@ -1,3 +1,20 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+#     https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
 p, alice, data1, read
 p, bob, data2, write
 p, data2_admin, data2, read
diff --git a/examples/rbac_with_domains_model.conf 
b/examples/rbac_with_domains_model.conf
index 57c3721..1eead55 100644
--- a/examples/rbac_with_domains_model.conf
+++ b/examples/rbac_with_domains_model.conf
@@ -1,3 +1,20 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+#     https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
 [request_definition]
 r = sub, dom, obj, act
 
diff --git a/examples/rbac_with_domains_policy.csv 
b/examples/rbac_with_domains_policy.csv
index 8558d17..5a04d9b 100644
--- a/examples/rbac_with_domains_policy.csv
+++ b/examples/rbac_with_domains_policy.csv
@@ -1,3 +1,20 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+#     https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
 p, admin, domain1, data1, read
 p, admin, domain1, data1, write
 p, admin, domain2, data2, read
diff --git a/pom.xml b/pom.xml
index 9ecb15d..cbf5176 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,4 +1,22 @@
 <?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+    https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
 <project xmlns="http://maven.apache.org/POM/4.0.0";
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
@@ -6,11 +24,12 @@
 
     <groupId>org.casbin</groupId>
     <artifactId>jdbc-adapter</artifactId>
-    <version>2.6.0</version>
+    <!-- The real version is supplied at release time with -Drevision=X.Y.Z 
(see RELEASING.md). -->
+    <version>${revision}</version>
 
-    <name>JDBC Adapter for JCasbin</name>
+    <name>Apache jCasbin JDBC Adapter</name>
     <description>Load policy from JDBC supported database or save policy to 
it</description>
-    <url>https://github.com/apache/casbin-jcasbin-jdbc-adapter</url>
+    <url>https://casbin.apache.org/</url>
     <inceptionYear>2018</inceptionYear>
 
     <issueManagement>
@@ -32,8 +51,8 @@
     </licenses>
     <scm>
         <url>https://github.com/apache/casbin-jcasbin-jdbc-adapter</url>
-        
<connection>[email protected]:apache/casbin-jcasbin-jdbc-adapter.git</connection>
-        <developerConnection>https://github.com/hsluoyz</developerConnection>
+        
<connection>scm:git:https://github.com/apache/casbin-jcasbin-jdbc-adapter.git</connection>
+        
<developerConnection>scm:git:ssh://[email protected]/apache/casbin-jcasbin-jdbc-adapter.git</developerConnection>
     </scm>
     <developers>
         <developer>
@@ -44,22 +63,78 @@
     </developers>
 
     <properties>
+        <revision>0.0.0</revision>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
     </properties>
 
-    <distributionManagement>
-        <snapshotRepository>
-            <id>ossrh</id>
-            <url>https://central.sonatype.com</url>
-        </snapshotRepository>
-    </distributionManagement>
-
     <build>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+            </resource>
+            <resource>
+                <directory>${project.basedir}</directory>
+                <targetPath>META-INF</targetPath>
+                <includes>
+                    <include>LICENSE</include>
+                    <include>NOTICE</include>
+                    <include>DISCLAIMER</include>
+                </includes>
+            </resource>
+        </resources>
         <plugins>
+            <plugin>
+                <!-- Resolve ${revision} in the POM that gets 
installed/deployed. -->
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>flatten-maven-plugin</artifactId>
+                <version>1.7.0</version>
+                <configuration>
+                    <flattenMode>ossrh</flattenMode>
+                    <updatePomFile>true</updatePomFile>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>flatten</id>
+                        <phase>process-resources</phase>
+                        <goals><goal>flatten</goal></goals>
+                    </execution>
+                    <execution>
+                        <id>flatten-clean</id>
+                        <phase>clean</phase>
+                        <goals><goal>clean</goal></goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <!-- The generated Javadoc JAR carries the project legal files 
too. -->
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-resources-plugin</artifactId>
+                <version>3.4.0</version>
+                <executions>
+                    <execution>
+                        <id>javadoc-legal-files</id>
+                        <phase>prepare-package</phase>
+                        <goals><goal>copy-resources</goal></goals>
+                        <configuration>
+                            
<outputDirectory>${project.build.directory}/reports/apidocs/META-INF</outputDirectory>
+                            <resources>
+                                <resource>
+                                    <directory>${project.basedir}</directory>
+                                    <includes>
+                                        <include>LICENSE</include>
+                                        <include>NOTICE</include>
+                                        <include>DISCLAIMER</include>
+                                    </includes>
+                                </resource>
+                            </resources>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-gpg-plugin</artifactId>
-                <version>1.5</version>
+                <version>3.2.7</version>
                 <executions>
                     <execution>
                         <id>sign-artifacts</id>
@@ -99,12 +174,12 @@
                 <!-- Allow attaching Javadoc during releases -->
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-javadoc-plugin</artifactId>
-                <version>2.10.4</version>
+                <version>3.11.1</version>
                 <configuration>
-                    <source>11</source>
+                    <source>8</source>
                     <detectJavaApiLink>false</detectJavaApiLink>
                     <!-- Turn off Java 8 strict Javadoc checking -->
-                    <additionalparam>-Xdoclint:none</additionalparam>
+                    <doclint>none</doclint>
                     <tags>
                         <tag>
                             <name>notnull</name>
@@ -132,6 +207,7 @@
                 <!-- Include zipped source code in releases -->
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-source-plugin</artifactId>
+                <version>3.4.0</version>
                 <executions>
                     <execution>
                         <id>attach-sources</id>
@@ -145,7 +221,7 @@
                 <!-- Automatically close and deploy from OSSRH -->
                 <groupId>org.sonatype.central</groupId>
                 <artifactId>central-publishing-maven-plugin</artifactId>
-                <version>0.5.0</version>
+                <version>0.6.0</version>
                 <extensions>true</extensions>
                 <configuration>
                     <publishingServerId>ossrh</publishingServerId>
@@ -157,11 +233,17 @@
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.15.0</version>
                 <configuration>
                     <source>1.8</source>
                     <target>1.8</target>
                 </configuration>
             </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <version>3.2.5</version>
+            </plugin>
             <plugin>
                 <groupId>org.codehaus.mojo</groupId>
                 <artifactId>cobertura-maven-plugin</artifactId>
@@ -193,7 +275,7 @@
         <dependency>
             <groupId>org.casbin</groupId>
             <artifactId>jcasbin</artifactId>
-            <version>1.85.1</version>
+            <version>1.99.0</version>
         </dependency>
         <dependency>
             <groupId>com.mysql</groupId>
@@ -201,17 +283,14 @@
             <version>8.3.0</version>
             <scope>test</scope>
         </dependency>
-        <!-- https://mvnrepository.com/artifact/com.oracle/ojdbc -->
-        <dependency>
-            <groupId>com.oracle.database.jdbc</groupId>
-            <artifactId>ojdbc6</artifactId>
-            <version>11.2.0.4</version>
-        </dependency>
+        <!-- The Oracle driver is not redistributable, so applications using
+             Oracle add their own driver to the runtime classpath instead.
+             See the "Oracle driver" section of README.md. -->
         <!-- https://mvnrepository.com/artifact/org.postgresql/postgresql -->
         <dependency>
             <groupId>org.postgresql</groupId>
             <artifactId>postgresql</artifactId>
-            <version>42.7.2</version>
+            <version>42.7.13</version>
         </dependency>
         <!-- 
https://mvnrepository.com/artifact/com.microsoft.sqlserver/mssql-jdbc -->
         <dependency>
diff --git a/src/main/java/org/casbin/adapter/JDBCAdapter.java 
b/src/main/java/org/casbin/adapter/JDBCAdapter.java
index 38705c2..7a67091 100644
--- a/src/main/java/org/casbin/adapter/JDBCAdapter.java
+++ b/src/main/java/org/casbin/adapter/JDBCAdapter.java
@@ -1,16 +1,19 @@
-// Copyright 2021 The casbin Authors. All Rights Reserved.
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
 //
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
+//     https://www.apache.org/licenses/LICENSE-2.0
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
 
 package org.casbin.adapter;
 
diff --git a/src/main/java/org/casbin/adapter/JDBCBaseAdapter.java 
b/src/main/java/org/casbin/adapter/JDBCBaseAdapter.java
index de2776b..1980d81 100644
--- a/src/main/java/org/casbin/adapter/JDBCBaseAdapter.java
+++ b/src/main/java/org/casbin/adapter/JDBCBaseAdapter.java
@@ -1,16 +1,19 @@
-// Copyright 2018 The casbin Authors. All Rights Reserved.
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
 //
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
+//     https://www.apache.org/licenses/LICENSE-2.0
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
 
 package org.casbin.adapter;
 
diff --git a/src/main/java/org/casbin/adapter/JDBCDataSource.java 
b/src/main/java/org/casbin/adapter/JDBCDataSource.java
index 69b8984..f1278e8 100644
--- a/src/main/java/org/casbin/adapter/JDBCDataSource.java
+++ b/src/main/java/org/casbin/adapter/JDBCDataSource.java
@@ -1,16 +1,19 @@
-// Copyright 2020 The casbin Authors. All Rights Reserved.
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
 //
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
+//     https://www.apache.org/licenses/LICENSE-2.0
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
 
 package org.casbin.adapter;
 
diff --git a/src/test/java/org/casbin/adapter/AdapterCreator.java 
b/src/test/java/org/casbin/adapter/AdapterCreator.java
index 0d10906..f2c446d 100644
--- a/src/test/java/org/casbin/adapter/AdapterCreator.java
+++ b/src/test/java/org/casbin/adapter/AdapterCreator.java
@@ -1,22 +1,24 @@
-// Copyright 2020 The casbin Authors. All Rights Reserved.
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
 //
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
+//     https://www.apache.org/licenses/LICENSE-2.0
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
 
 package org.casbin.adapter;
 
 import com.microsoft.sqlserver.jdbc.SQLServerDataSource;
 import com.mysql.cj.jdbc.MysqlDataSource;
-import oracle.jdbc.pool.OracleDataSource;
 import org.postgresql.ds.PGSimpleDataSource;
 
 public interface AdapterCreator {
@@ -60,28 +62,6 @@ class MySQLAdapterCreator implements AdapterCreator {
     }
 }
 
-class OracleAdapterCreator implements AdapterCreator {
-    private String url = "jdbc:oracle:thin:@//localhost:1521/orcl";
-    private String username = "system";
-    private String password = "oracle";
-    private String driver = "oracle.jdbc.driver.OracleDriver";
-
-    @Override
-    public JDBCAdapter create() throws Exception {
-        return new JDBCAdapter(driver, url, username, password);
-    }
-
-    @Override
-    public JDBCAdapter createViaDataSource() throws Exception {
-        OracleDataSource dataSource = new OracleDataSource();
-        dataSource.setURL(url);
-        dataSource.setUser(username);
-        dataSource.setPassword(password);
-
-        return new JDBCAdapter(dataSource);
-    }
-}
-
 class PgAdapterCreator implements AdapterCreator {
     private String url = "jdbc:postgresql://localhost:5432/casbin";
     private String username = "casbin_test";
diff --git a/src/test/java/org/casbin/adapter/JDBCAdapterTest.java 
b/src/test/java/org/casbin/adapter/JDBCAdapterTest.java
index 7e1d02d..00b54d1 100644
--- a/src/test/java/org/casbin/adapter/JDBCAdapterTest.java
+++ b/src/test/java/org/casbin/adapter/JDBCAdapterTest.java
@@ -1,16 +1,19 @@
-// Copyright 2018 The casbin Authors. All Rights Reserved.
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
 //
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
+//     https://www.apache.org/licenses/LICENSE-2.0
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
 
 package org.casbin.adapter;
 
diff --git a/src/test/java/org/casbin/adapter/JDBCAdapterTestSets.java 
b/src/test/java/org/casbin/adapter/JDBCAdapterTestSets.java
index 51524ca..a8aa34a 100644
--- a/src/test/java/org/casbin/adapter/JDBCAdapterTestSets.java
+++ b/src/test/java/org/casbin/adapter/JDBCAdapterTestSets.java
@@ -1,16 +1,19 @@
-// Copyright 2020 The casbin Authors. All Rights Reserved.
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
 //
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
+//     https://www.apache.org/licenses/LICENSE-2.0
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
 
 package org.casbin.adapter;
 


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to