diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0f73c175a..f5a7b15b8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,19 +11,27 @@ env: MVN_CMD: ./mvnw --no-transfer-progress -B jobs: + # Oracle only provides JDK 17+, so test against 17, 21, and 25 oracle: - strategy: - matrix: - java: [ '17' ] runs-on: 'ubuntu-latest' - name: jdk-${{ matrix.java }}-oracle + name: oracle steps: - uses: actions/checkout@v4 + # Install test-only JDKs first; each call appends an entry to ~/.m2/toolchains.xml - name: Set up JDK - uses: actions/setup-java@v4.7.0 + uses: actions/setup-java@v4 + with: + distribution: oracle + java-version: | + 21 + 25 + # Build JDK last so it ends up as the active JAVA_HOME / PATH entry + - name: Set up JDK 17 (build) + uses: actions/setup-java@v4 with: distribution: oracle - java-version: ${{ matrix.java }} + java-version: '17' + cache: 'maven' - name: Install softhsm2 run: sudo apt-get install -y softhsm2 - name: Install opensc @@ -35,51 +43,29 @@ jobs: - name: Build # run a full build, just as we would for a release (i.e. the `ossrh` profile), but don't use gpg # to sign artifacts, since we don't want to mess with storing signing credentials in CI: - run: ${{env.MVN_CMD}} verify -Possrh -Dgpg.skip=true + run: ${{env.MVN_CMD}} verify -Possrh -Dgpg.skip=true -P jdk-17,jdk-21,jdk-25 temurin: - strategy: - matrix: - java: [ '8', '11', '17', '18' ] runs-on: 'ubuntu-latest' - name: jdk-${{ matrix.java }}-temurin + name: temurin steps: - uses: actions/checkout@v4 + # Install test-only JDKs first; each call appends an entry to ~/.m2/toolchains.xml - name: Set up JDK uses: actions/setup-java@v4 with: - java-version: ${{ matrix.java }} distribution: 'temurin' - cache: 'maven' - check-latest: true - - name: Install softhsm2 - run: sudo apt-get install -y softhsm2 - - name: Install opensc - run: sudo apt-get install -y opensc - - name: Ensure SoftHSM user configuration - run: impl/src/test/scripts/softhsm configure - - name: Populate SoftHSM with JJWT test keys - run: impl/src/test/scripts/softhsm import - - name: Build - # run a full build, just as we would for a release (i.e. the `ossrh` profile), but don't use gpg - # to sign artifacts, since we don't want to mess with storing signing credentials in CI: - run: ${{env.MVN_CMD}} verify -Possrh -Dgpg.skip=true - - zulu: - strategy: - matrix: - java: [ '7', '8', '9', '11', '12', '13', '14', '15', '16', '17', '18', '21' ] - runs-on: 'ubuntu-latest' - env: - JDK_MAJOR_VERSION: ${{ matrix.java }} - name: jdk-${{ matrix.java }}-zulu - steps: - - uses: actions/checkout@v4 - - name: Set up JDK + java-version: | + 8 + 11 + 21 + 25 + # Build JDK last so it ends up as the active JAVA_HOME / PATH entry + - name: Set up JDK 17 (build) uses: actions/setup-java@v4 with: - java-version: ${{ matrix.java }} - distribution: 'zulu' + java-version: '17' + distribution: 'temurin' cache: 'maven' check-latest: true - name: Install softhsm2 @@ -93,9 +79,7 @@ jobs: - name: Build # run a full build, just as we would for a release (i.e. the `ossrh` profile), but don't use gpg # to sign artifacts, since we don't want to mess with storing signing credentials in CI: - run: | - if [ "$JDK_MAJOR_VERSION" == "7" ]; then export MAVEN_OPTS="-Xmx512m -XX:MaxPermSize=128m"; fi - ${{env.MVN_CMD}} verify -Possrh -Dgpg.skip=true + run: ${{env.MVN_CMD}} verify -Possrh -Dgpg.skip=true -P jdk-8,jdk-11,jdk-17,jdk-21,jdk-25 # ensure all of our files have the correct/updated license header license-check: @@ -107,8 +91,8 @@ jobs: - name: Set up JDK uses: actions/setup-java@v4 with: - distribution: 'zulu' - java-version: '8' + distribution: 'temurin' + java-version: '17' cache: 'maven' check-latest: true - name: License Check @@ -117,14 +101,14 @@ jobs: ${{env.MVN_CMD}} license:check code-coverage: - needs: [oracle, temurin, zulu] + needs: [oracle, temurin] runs-on: 'ubuntu-latest' steps: - uses: actions/checkout@v4 - name: Set up JDK uses: actions/setup-java@v4 with: - distribution: 'zulu' + distribution: 'temurin' java-version: '17' cache: 'maven' check-latest: true diff --git a/impl/src/test/groovy/io/jsonwebtoken/impl/security/JcaTemplateTest.groovy b/impl/src/test/groovy/io/jsonwebtoken/impl/security/JcaTemplateTest.groovy index bf1037276..549df50f6 100644 --- a/impl/src/test/groovy/io/jsonwebtoken/impl/security/JcaTemplateTest.groovy +++ b/impl/src/test/groovy/io/jsonwebtoken/impl/security/JcaTemplateTest.groovy @@ -266,12 +266,8 @@ class JcaTemplateTest { template.generatePrivate(new X509EncodedKeySpec(invalid)) fail() } catch (SecurityException expected) { - boolean jdk11OrLater = Classes.isAvailable('java.security.interfaces.XECPrivateKey') - String msg = 'KeyFactory callback execution failed: key spec not recognized' - if (jdk11OrLater) { - msg = 'KeyFactory callback execution failed: Only PKCS8EncodedKeySpec and XECPrivateKeySpec supported' - } - assertEquals msg, expected.getMessage() + String msg = expected.getMessage() + assertTrue msg, msg.startsWith('KeyFactory callback execution failed:') } } diff --git a/impl/src/test/groovy/io/jsonwebtoken/impl/security/TestProvider.groovy b/impl/src/test/java/io/jsonwebtoken/impl/security/TestProvider.java similarity index 50% rename from impl/src/test/groovy/io/jsonwebtoken/impl/security/TestProvider.groovy rename to impl/src/test/java/io/jsonwebtoken/impl/security/TestProvider.java index 197a253ec..ce8d18aca 100644 --- a/impl/src/test/groovy/io/jsonwebtoken/impl/security/TestProvider.groovy +++ b/impl/src/test/java/io/jsonwebtoken/impl/security/TestProvider.java @@ -13,17 +13,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.jsonwebtoken.impl.security +package io.jsonwebtoken.impl.security; -import java.security.Provider +import java.security.Provider; -class TestProvider extends Provider { +/** + * Test-only {@link Provider} subclass. Defined in Java (not Groovy) because Groovy 4 cannot resolve + * the {@code protected} {@code Provider} constructor via its meta-class on JDK 17+. + */ +public class TestProvider extends Provider { - TestProvider() { - this('test') + public TestProvider() { + this("test"); } - TestProvider(String name) { - super(name, 1.0d, 'info') + public TestProvider(String name) { + //noinspection deprecation - double constructor used for Java 8 source compatibility; + // the (String, String, String) replacement was added in Java 9 + super(name, 1.0d, "info"); } } diff --git a/install-test-jdks.sh b/install-test-jdks.sh new file mode 100755 index 000000000..4aa0dc2c2 --- /dev/null +++ b/install-test-jdks.sh @@ -0,0 +1,63 @@ +#!/usr/bin/env bash +# install-test-jdks.sh +# +# Installs all JDK versions needed to run the full multi-JDK test matrix locally via SDKMAN, +# then generates ~/.m2/toolchains.xml from the discovered JDKs. +# +# Usage: +# ./install-test-jdks.sh +# +# After running this script, activate each profile you want to test against, e.g.: +# ./mvnw verify -P jdk-8,jdk-11,jdk-21,jdk-25 +# +# The build JDK must be JDK 17+. If you are not already on JDK 17: +# sdk use java <17.x.x-tem> + +set -euo pipefail + +# ============================================================ +# JDK versions to install. +# Update these when new patch releases are available. +# Find current versions with: sdk list java +# +# NOTE: Temurin does not provide JDK 8 on all platforms (e.g. +# macOS/ARM). Zulu is used for JDK 8 as a reliable fallback. +# ============================================================ +JDKS=( + "8.0.492-zulu" # JDK 8 - minimum supported runtime + "11.0.31-tem" # JDK 11 + "17.0.19-tem" # JDK 17 - required build JDK + "21.0.11-tem" # JDK 21 + "25.0.3-tem" # JDK 25 +) +# ============================================================ + +if ! command -v sdk &>/dev/null; then + echo "ERROR: SDKMAN not found. Install it from https://sdkman.io" >&2 + exit 1 +fi + +# Source SDKMAN so 'sdk' commands work in this script +# shellcheck disable=SC1090 +source "${SDKMAN_DIR:-$HOME/.sdkman}/bin/sdkman-init.sh" + +echo "Installing test JDKs via SDKMAN..." +echo "(Already-installed versions will be skipped)" +echo + +for jdk in "${JDKS[@]}"; do + sdk install java "$jdk" || true +done + +echo +echo "Done. Generating ~/.m2/toolchains.xml from discovered JDKs..." +./mvnw --no-transfer-progress -q \ + org.apache.maven.plugins:maven-toolchains-plugin:3.2.0:generate-jdk-toolchains-xml \ + -Dtoolchain.file="${HOME}/.m2/toolchains.xml" + +echo +echo "To run the full multi-JDK test matrix:" +echo " ./mvnw verify -P jdk-8,jdk-11,jdk-17,jdk-21,jdk-25" +echo +echo "To run a single JDK profile (e.g., JDK 8 only):" +echo " ./mvnw verify -P jdk-8" diff --git a/pom.xml b/pom.xml index e3124e814..92d56ec90 100644 --- a/pom.xml +++ b/pom.xml @@ -97,16 +97,27 @@ 3.3.0 3.11.0 - 3.1.1 + 3.6.3 3.2.1 3.1.0 - 1.6 - 0.13.1 - 1.6.1 + 3.1.0 + 0.15.6 + 3.2.0 + 4.2.0 4.2.rc3 true - 7 + + 8 + + 8 + + + false + false ${user.name}-${maven.build.timestamp} 2.12.7.1 @@ -114,22 +125,24 @@ 2.11.0 - 1.78.1 bcprov-jdk18on bcpkix-jdk18on - 2.5.16 - 3.6 + 4.0.31 + 4.2 4.12 - 2.0.0-beta.5 - 3.0.0-M5 - 3.0.0-M5 - 4.3.1 + 2.0.7 + 3.1.2 + 3.1.2 + 4.3.1 ${jjwt.root}/target/clover/clover.db - + + false + ${test.addOpens} --add-opens java.base/java.lang=ALL-UNNAMED, --add-opens java.desktop/java.beans=ALL-UNNAMED, @@ -211,7 +224,7 @@ - org.codehaus.groovy + org.apache.groovy groovy ${groovy.version} test @@ -321,7 +334,8 @@ **/*.test.override **/*.bnd LICENSE - **/mvnw + **/mvnw + **/install-test-jdks.sh **/lombok.config .gitattributes **/genkeys @@ -362,16 +376,8 @@ ${jdk.version} true false - ${maven.javadoc.additionalOptions} + -html5 ${maven.javadoc.additionalOptions} - - - - commons-lang - commons-lang - 2.6 - - org.apache.maven.plugins @@ -496,7 +502,7 @@ org.apache.maven.plugins maven-enforcer-plugin - 1.4.1 + 3.4.1 enforce-banned-dependencies @@ -515,49 +521,30 @@ true + + enforce-java-17 + + enforce + + + + + + [17,) + Build requires JDK 17 or later. Use SDKMAN: sdk install java 17.x.x-tem + + + true + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - org.apache.maven.plugins maven-compiler-plugin ${maven.compiler.version} - ${jdk.version} - ${jdk.version} + ${jdk.release.version} ${project.build.sourceEncoding} @@ -582,7 +569,7 @@ - org.codehaus.groovy + org.apache.groovy groovy ${groovy.version} @@ -594,6 +581,7 @@ ${surefire.plugin.version} ${surefire.argLine} + once @@ -681,91 +669,157 @@ + + + - jdk7 - - 1.7 - - - 3.2.2 - 3.8.1 - 20230618 - bcprov-jdk15to18 - bcpkix-jdk15to18 - + jdk-8 + + + + org.apache.maven.plugins + maven-surefire-plugin + ${surefire.plugin.version} + + + test-jdk-8 + test + + ${module.skip.jdk8.tests} + + [1.8,1.9),[8,9) + + + + once + + + + + + + + - jdk8AndLater - - [1.8,) - - - 3.0.2 - 3.0.19 - 4.2 - 2.0.7 - 0.15.6 - 3.1.2 - 3.1.2 - + jdk-11 + + + + org.apache.maven.plugins + maven-surefire-plugin + ${surefire.plugin.version} + + + test-jdk-11 + test + + ${module.skip.jdk11.tests} + + [11,12) + + ${test.addOpens} + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - + + + - - jdk9AndLater - - [1.9,) - - - 3.11.0 - false - -html5 - ${test.addOpens}, --illegal-access=debug - + jdk-17 + + + + org.apache.maven.plugins + maven-surefire-plugin + ${surefire.plugin.version} + + + test-jdk-17 + test + + + [17,18) + + ${test.addOpens} + + + + + + + + - jdk17AndLater - - [17,) - - - -html5 - ${test.addOpens} - + jdk-21 + + + + org.apache.maven.plugins + maven-surefire-plugin + ${surefire.plugin.version} + + + test-jdk-21 + test + + + [21,22) + + ${test.addOpens} + + + + + + + + - jdk21AndLater - - [21,) - - - - 8 - + jdk-25 + + + + org.apache.maven.plugins + maven-surefire-plugin + ${surefire.plugin.version} + + + test-jdk-25 + test + + + [25,26) + + ${test.addOpens} + + + + + + + docs