diff --git a/.sdkmanrc b/.sdkmanrc index 7d78586f00..32af361268 100644 --- a/.sdkmanrc +++ b/.sdkmanrc @@ -1,3 +1,3 @@ # Enable auto-env through the sdkman_auto_env config # Add key=value pairs of SDKs to use below -java=17.0.17.fx-zulu +java=25.0.5.0+8-tem diff --git a/Dockerfile b/Dockerfile index a59672f5ee..7c4cf0ab20 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,32 +5,24 @@ # Stages: # 1. Builder Stage: Compiles the application and resolves dependencies. Produces # JAR files that can be deployed. -# 1a. Install dependencies +# 1a. Drop root # 1b. Build the application # 2. Runner Stage: Creates a lightweight image that runs the application using the JRE. -FROM ubuntu:noble-20251013 AS builder +# Keep the JDK in sync with .sdkmanrc, which pins the same version for +# local development. +FROM eclipse-temurin:25.0.4.1_1-jdk-noble AS builder WORKDIR /app -# sdkman requires bash -SHELL ["/bin/bash", "-c"] ARG GRADLE_BUILD_ARGS="-PdisableSigning=true" -# Stage 1a: Install dependencies -# Install necessary tools, then drop root. The base image ships a -# pre-created "ubuntu" user (uid 1000, the same one the runner stage -# below renames to "engine") — reuse it so Gradle doesn't run as root, -# which ignores POSIX permission bits and breaks tests that depend on -# them (e.g. Log4jMigrationsTest's read-only-file assertion). -RUN apt-get update\ - && apt-get install -y zip curl\ - && rm -rf /var/lib/apt/lists/* \ - && chown ubuntu:ubuntu /app +# Stage 1a: Drop root. The base image ships a pre-created "ubuntu" user +# (uid 1000, the same one the runner stage below renames to "engine") +# — reuse it so Gradle doesn't run as root, which ignores POSIX +# permission bits and breaks tests that depend on them (e.g. +# Log4jMigrationsTest's read-only-file assertion). +RUN chown ubuntu:ubuntu /app USER ubuntu -COPY --chown=ubuntu:ubuntu .sdkmanrc . -RUN curl -s "https://get.sdkman.io?ci=true" | bash \ - && source "$HOME/.sdkman/bin/sdkman-init.sh" && sdk env install - # Stage 1b: Build the application # Copy the entire source tree (excluding .dockerignore files), and build # (file encoding is pinned to UTF-8 in gradle.properties) @@ -41,8 +33,7 @@ COPY --chown=ubuntu:ubuntu . . RUN mkdir -p /home/ubuntu/.gradle RUN --mount=type=cache,target=/home/ubuntu/.gradle/caches,sharing=locked,uid=1000,gid=1000 \ --mount=type=cache,target=/home/ubuntu/.gradle/wrapper,sharing=locked,uid=1000,gid=1000 \ - source "$HOME/.sdkman/bin/sdkman-init.sh" \ - && ./gradlew --no-daemon build :smoketest:installHarnessDist ${GRADLE_BUILD_ARGS} + ./gradlew --no-daemon build :smoketest:installHarnessDist ${GRADLE_BUILD_ARGS} # Stage 1c: Present artifacts for export if not running within docker FROM scratch AS build-output-export @@ -53,7 +44,7 @@ COPY --from=builder /app/donkey/build/test-results /app/donkey/build/test-result COPY --from=builder /app/server/build/test-results /app/server/build/test-results/ # Stage 1d: Smoke Test Harness -FROM eclipse-temurin:21.0.9_10-jre-noble AS smoketest-harness +FROM eclipse-temurin:25.0.4.1_1-jre-noble AS smoketest-harness COPY --from=builder /app/server/setup/server-lib /opt/engine/server-lib COPY --from=builder /app/server/setup/extensions /opt/engine/extensions @@ -72,7 +63,7 @@ ENTRYPOINT ["/bin/bash", "/harness/run-harness.sh"] # ########################################## -FROM eclipse-temurin:21.0.9_10-jdk-noble AS jdk-run +FROM eclipse-temurin:25.0.4.1_1-jdk-noble AS jdk-run RUN groupadd engine \ && usermod -l engine ubuntu \ @@ -104,7 +95,7 @@ CMD ["./oieserver"] # ########################################## -FROM eclipse-temurin:21.0.9_10-jre-alpine AS jre-run +FROM eclipse-temurin:25.0.4.1_1-jre-alpine AS jre-run # Alpine does not include bash by default, so we install it RUN apk add --no-cache bash diff --git a/README.md b/README.md index e70808b567..45c928a18f 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ The **Open Integration Engine Project** is an open-source initiative committed t ## Building from Source -The build is driven by Gradle through the committed wrapper; the only prerequisite is JDK 17 (see [.sdkmanrc](.sdkmanrc)): +The build is driven by Gradle through the committed wrapper; the only prerequisite is JDK 25 (see [.sdkmanrc](.sdkmanrc)): ```bash ./gradlew build # full build + tests; distribution lands in server/setup diff --git a/build.gradle b/build.gradle index 83d7e13a66..38672aa606 100644 --- a/build.gradle +++ b/build.gradle @@ -158,7 +158,7 @@ subprojects { java { toolchain { - languageVersion = JavaLanguageVersion.of(17) + languageVersion = JavaLanguageVersion.of(25) } } @@ -178,6 +178,7 @@ subprojects { tasks.withType(JavaCompile).configureEach { options.encoding = 'UTF-8' options.debug = true + options.release = 21 } // Match Ant's javac invocation: -sourcepath defaults to srcdir, and // annotation processors are discovered on the compile classpath @@ -275,7 +276,7 @@ subprojects { if (rootProject.coverageEnabled) { apply plugin: 'jacoco' - jacoco { toolVersion = '0.8.8' } + jacoco { toolVersion = '0.8.16' } tasks.withType(Test).configureEach { finalizedBy tasks.named('jacocoTestReport') } tasks.named('jacocoTestReport') { reports.xml.required = true diff --git a/ci/Dockerfile.rebase-alpine b/ci/Dockerfile.rebase-alpine new file mode 100644 index 0000000000..82e9613382 --- /dev/null +++ b/ci/Dockerfile.rebase-alpine @@ -0,0 +1,32 @@ +# syntax=docker/dockerfile:1.19.0 +# SPDX-License-Identifier: MPL-2.0 +# SPDX-FileCopyrightText: 2026 Mitch Gaffigan + +############################################################################### +# Rebases the already-assembled server image onto a different alpine JRE. +############################################################################### +ARG OIE_IMAGE=oie-ci-server:local-alpine-temurin25 +ARG JRE_IMAGE + +FROM ${OIE_IMAGE} AS source +FROM ${JRE_IMAGE} + +# Mirrors the jre-run stage of the root Dockerfile; keep the two in step. +RUN apk add --no-cache bash +RUN addgroup -S engine \ + && adduser -S -g engine engine \ + && mkdir -p /opt/engine/appdata \ + && chown -R engine:engine /opt/engine + +WORKDIR /opt/engine + +COPY --from=source --chown=engine:engine /opt/engine /opt/engine + +VOLUME /opt/engine/appdata +VOLUME /opt/engine/custom-extensions + +EXPOSE 8443 + +USER engine +ENTRYPOINT ["./configure-from-env"] +CMD ["./oieserver"] diff --git a/ci/README.md b/ci/README.md index 1fd3f24e94..61f45b43c0 100644 --- a/ci/README.md +++ b/ci/README.md @@ -70,8 +70,8 @@ A fixture case runs in every configuration by default. To limit it, add a `configurations` file at the case root with one configuration name per line: ```text -alpine-temurin21-postgres -ubuntu-temurin21-postgres +alpine-temurin123-postgres +ubuntu-temurin123-postgres ``` ### Parse Batch @@ -96,7 +96,7 @@ messages/ Add a Compose file at `ci/configurations/.compose.yml`. Configuration names normally follow `--`, such as -`alpine-temurin21-postgres`. +`alpine-temurin123-postgres`. The Compose file must: @@ -127,7 +127,7 @@ ci/runtests.sh Run one configuration: ```sh -ci/runtests.sh alpine-temurin21-derby +ci/runtests.sh alpine-temurin25-derby ``` To iterate against an already-running server, pass that server's admin password. diff --git a/ci/configurations/alpine-temurin21-derby.compose.yml b/ci/configurations/alpine-temurin21-derby.compose.yml index 5aa8ebe77e..98325ccc61 100644 --- a/ci/configurations/alpine-temurin21-derby.compose.yml +++ b/ci/configurations/alpine-temurin21-derby.compose.yml @@ -1,6 +1,11 @@ services: oie: - image: ${OIE_IMAGE} + build: + context: .. + dockerfile: Dockerfile.rebase-alpine + args: + OIE_IMAGE: ${OIE_IMAGE} + JRE_IMAGE: eclipse-temurin:21.0.9_10-jre-alpine ports: - "8443:8443" healthcheck: diff --git a/ci/configurations/ubuntu-temurin21-derby.compose.yml b/ci/configurations/alpine-temurin25-derby.compose.yml similarity index 100% rename from ci/configurations/ubuntu-temurin21-derby.compose.yml rename to ci/configurations/alpine-temurin25-derby.compose.yml diff --git a/ci/configurations/alpine-temurin21-mysql.compose.yml b/ci/configurations/alpine-temurin25-mysql.compose.yml similarity index 100% rename from ci/configurations/alpine-temurin21-mysql.compose.yml rename to ci/configurations/alpine-temurin25-mysql.compose.yml diff --git a/ci/configurations/alpine-temurin21-oracle.compose.yml b/ci/configurations/alpine-temurin25-oracle.compose.yml similarity index 100% rename from ci/configurations/alpine-temurin21-oracle.compose.yml rename to ci/configurations/alpine-temurin25-oracle.compose.yml diff --git a/ci/configurations/alpine-temurin21-postgres.compose.yml b/ci/configurations/alpine-temurin25-postgres.compose.yml similarity index 100% rename from ci/configurations/alpine-temurin21-postgres.compose.yml rename to ci/configurations/alpine-temurin25-postgres.compose.yml diff --git a/ci/configurations/alpine-temurin21-sqlserver.compose.yml b/ci/configurations/alpine-temurin25-sqlserver.compose.yml similarity index 100% rename from ci/configurations/alpine-temurin21-sqlserver.compose.yml rename to ci/configurations/alpine-temurin25-sqlserver.compose.yml diff --git a/ci/configurations/ubuntu-temurin25-derby.compose.yml b/ci/configurations/ubuntu-temurin25-derby.compose.yml new file mode 100644 index 0000000000..5aa8ebe77e --- /dev/null +++ b/ci/configurations/ubuntu-temurin25-derby.compose.yml @@ -0,0 +1,13 @@ +services: + oie: + image: ${OIE_IMAGE} + ports: + - "8443:8443" + healthcheck: + test: + - CMD-SHELL + - bash -lc 'exec 3<>/dev/tcp/127.0.0.1/8443' + interval: 3s + timeout: 5s + retries: 30 + start_period: 40s diff --git a/ci/configurations/ubuntu-temurin21-postgres.compose.yml b/ci/configurations/ubuntu-temurin25-postgres.compose.yml similarity index 100% rename from ci/configurations/ubuntu-temurin21-postgres.compose.yml rename to ci/configurations/ubuntu-temurin25-postgres.compose.yml diff --git a/ci/run-configuration.sh b/ci/run-configuration.sh index 7881f57bbd..df27156253 100755 --- a/ci/run-configuration.sh +++ b/ci/run-configuration.sh @@ -23,6 +23,9 @@ export HOST_UID="$(id -u)" export HOST_GID="$(id -g)" mkdir -p "$WORKSPACE/ci/test-results" +# To access the manually restored images (remove if we move to ghcr) +export BUILDX_BUILDER="${BUILDX_BUILDER:-$(docker context show)}" + compose=(docker compose -f "$1" -f ci/harness.compose.yml -p "oie-ci-${OIE_CONFIGURATION//[^a-z0-9-]/-}-$$") cleanup() { diff --git a/ci/runtests.sh b/ci/runtests.sh index 68ad444b9a..ac24342a3d 100755 --- a/ci/runtests.sh +++ b/ci/runtests.sh @@ -4,8 +4,8 @@ set -euo pipefail cd "$(dirname "${BASH_SOURCE[0]}")/.." -ALPINE_IMAGE="oie-ci-server:local-alpine-temurin21" -UBUNTU_IMAGE="oie-ci-server:local-ubuntu-temurin21" +ALPINE_IMAGE="oie-ci-server:local-alpine-temurin25" +UBUNTU_IMAGE="oie-ci-server:local-ubuntu-temurin25" if [[ $# -gt 1 ]]; then echo "Usage: $0 [configuration]" >&2 diff --git a/client/build.gradle b/client/build.gradle index a3ffca4acc..b71cbb395a 100644 --- a/client/build.gradle +++ b/client/build.gradle @@ -112,8 +112,7 @@ tasks.register('devClient', JavaExec) { workingDir = projectDir classpath = sourceSets.main.runtimeClasspath args 'https://localhost:8443', '0.0.0', 'admin', 'admin' - jvmArgs '-Dcom.sun.webkit.useHTTP2Loader=false', - '--add-modules=java.sql.rowset,javafx.controls,javafx.fxml', + jvmArgs '--add-modules=java.sql.rowset', '--add-exports=java.base/com.sun.crypto.provider=ALL-UNNAMED', '--add-exports=java.base/sun.security.provider=ALL-UNNAMED', '--add-opens=java.base/java.lang=ALL-UNNAMED', diff --git a/client/lib/openjfx.jar b/client/lib/openjfx.jar deleted file mode 100644 index bf39bdfd2d..0000000000 Binary files a/client/lib/openjfx.jar and /dev/null differ diff --git a/client/src/main/java/com/mirth/connect/client/ui/AboutMirth.java b/client/src/main/java/com/mirth/connect/client/ui/AboutMirth.java index d2bb42a792..866bf48605 100644 --- a/client/src/main/java/com/mirth/connect/client/ui/AboutMirth.java +++ b/client/src/main/java/com/mirth/connect/client/ui/AboutMirth.java @@ -84,7 +84,6 @@ public void loadContent() { content.append("This product includes software developed by the JDOM Project (http://www.jdom.org/).\n\n"); content.append("This product includes software developed by xerial.org (Taro L. Saito) (https://github.com/xerial/sqlite-jdbc).\n\n"); content.append("This product includes the SwingLabs SwingX library, copyright (c) 2005-2006 Sun Microsystems, Inc., licensed under the LGPL version 2.1 (http://www.gnu.org/licenses/lgpl-2.1.html).\n\n"); - content.append("This product includes libraries from OpenJFX, which is licensed under the GNU General Public License version 2, with the Classpath Exception (http://openjdk.java.net/legal/gplv2+ce.html). The source code for OpenJFX is available at: http://jdk.java.net/openjfx/\n\n"); aboutContent.setText(content.toString()); } diff --git a/client/src/main/java/com/mirth/connect/client/ui/BrandingConstants.java b/client/src/main/java/com/mirth/connect/client/ui/BrandingConstants.java index 6e3f81c7ca..eb3ee74387 100644 --- a/client/src/main/java/com/mirth/connect/client/ui/BrandingConstants.java +++ b/client/src/main/java/com/mirth/connect/client/ui/BrandingConstants.java @@ -30,9 +30,6 @@ public class BrandingConstants { // The URL that is opened when clicking "Help" button in Administrator public static String HELP_URL_LOCATION = "https://github.com/OpenIntegrationEngine/engine/discussions"; - // The URL that is opened when clicking "System Requirements" button in the error dialog when an unsupported Java version is detected - public static final String SYSTEM_REQUIREMENTS_URL = "https://docs.openintegrationengine.org/engine/getting_started.html#system-requirements"; - // The "More info" in Server settings "Provide usage statistics" public static final String PRIVACY_URL = "https://github.com/openintegrationengine"; public static final String PRIVACY_TOOLTIP = "Privacy Information"; diff --git a/client/src/main/java/com/mirth/connect/client/ui/ClientPrerequisites.java b/client/src/main/java/com/mirth/connect/client/ui/ClientPrerequisites.java deleted file mode 100644 index 2af4ed38a2..0000000000 --- a/client/src/main/java/com/mirth/connect/client/ui/ClientPrerequisites.java +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 -// SPDX-FileCopyrightText: Mitch Gaffigan - -package com.mirth.connect.client.ui; - -/** Utility class to check if the client prerequisites are met. */ -public class ClientPrerequisites { - - private ClientPrerequisites() { - } - - /** Checks if the client prerequisites are met. */ - public static String getMissing() { - // Can't meaningfully check for Java 17 since the entrypoint is compiled with - // class file version 61, which will fail to load on Java 8. - if (!hasJavaFx()) { - return "JavaFX"; - } - - return null; - } - - private static boolean hasJavaFx() { - // Use JPMS to check for JavaFX - the classes are on the classpath - // even in Java SE, but the module will not be present except in FX - return ModuleLayer.boot().findModule("javafx.graphics").isPresent(); - } -} \ No newline at end of file diff --git a/client/src/main/java/com/mirth/connect/client/ui/Frame.java b/client/src/main/java/com/mirth/connect/client/ui/Frame.java index 7663e346a3..525dc99bb9 100644 --- a/client/src/main/java/com/mirth/connect/client/ui/Frame.java +++ b/client/src/main/java/com/mirth/connect/client/ui/Frame.java @@ -164,8 +164,6 @@ import com.mirth.connect.util.JavaScriptSharedUtil; import com.mirth.connect.util.MigrationUtil; -import javafx.application.Platform; - /** * The main content frame for the Mirth Client Application. Extends JXFrame and sets up all content. */ @@ -256,8 +254,6 @@ public class Frame extends JXFrame { private static final int REFRESH_BLOCK_SIZE = 100; public Frame() { - Platform.setImplicitExit(false); - // Load RSyntaxTextArea language support LanguageSupportFactory.get().addLanguageSupport(SyntaxConstants.SYNTAX_STYLE_JAVASCRIPT, MirthJavaScriptLanguageSupport.class.getName()); diff --git a/client/src/main/java/com/mirth/connect/client/ui/Mirth.java b/client/src/main/java/com/mirth/connect/client/ui/Mirth.java index 60a74e85c5..eacb683313 100644 --- a/client/src/main/java/com/mirth/connect/client/ui/Mirth.java +++ b/client/src/main/java/com/mirth/connect/client/ui/Mirth.java @@ -7,14 +7,12 @@ import java.awt.Toolkit; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; -import java.awt.Desktop; import java.io.IOException; import java.util.prefs.Preferences; import javax.imageio.ImageIO; import javax.swing.ImageIcon; import javax.swing.InputMap; -import javax.swing.JOptionPane; import javax.swing.KeyStroke; import javax.swing.SwingUtilities; import javax.swing.ToolTipManager; @@ -255,13 +253,6 @@ public static void initUIManager() { * String[] */ public static void main(String[] args) { - var missingPrerequisite = ClientPrerequisites.getMissing(); - if (missingPrerequisite != null) { - showUnsupportedJreDialog(missingPrerequisite); - System.exit(1); - return; - } - CommandLineOptions opts = new CommandLineOptions(args); if (StringUtils.isNotBlank(opts.getProtocols())) { @@ -276,23 +267,6 @@ public static void main(String[] args) { start(opts.getServer(), opts.getVersion(), opts.getUsername(), opts.getPassword()); } - private static void showUnsupportedJreDialog(String missingPrerequisite) { - try { - var message = String.format( - "%s Client requires %s%nPlease review the system requirements and try again.", - BrandingConstants.PRODUCT_NAME, missingPrerequisite); - var options = new Object[] { "View System Requirements", "Exit" }; - var result = JOptionPane.showOptionDialog( - null, message, "Unsupported Java Runtime", JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE, null, options, options[0]); - - if (result == 0) { - Desktop.getDesktop().browse(java.net.URI.create(BrandingConstants.SYSTEM_REQUIREMENTS_URL)); - } - } catch (Throwable t) { - System.err.println(String.format("Missing prerequisite: %s", missingPrerequisite)); - } - } - private static void start(final String server, final String version, final String username, final String password) { // disable the velocity logging Logger velocityLogger = LogManager.getLogger(RuntimeConstants.DEFAULT_RUNTIME_LOG_NAME); diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9eb0f3a5db..2c56d39f81 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -14,7 +14,7 @@ asm = "9.6" awssdk = "2.15.28" bouncycastle = "1.78.1" -byte-buddy = "1.14.13" +byte-buddy = "1.17.7" derby = "10.10.2.0" flying-saucer = "9.0.1" hapi = "2.3" @@ -31,7 +31,7 @@ jetty = "9.4.57.v20241219" jna = "4.5.2" log4j = "2.26.1" miglayout = "4.2" -mockito = "5.1.1" +mockito = "5.24.0" netty = "4.1.137.Final" netty-reactive-streams = "2.0.8" openhtmltopdf = "1.0.9" @@ -209,7 +209,6 @@ miglayout-core = { module = "com.miglayout:miglayout-core", version.ref = "migla miglayout-swing = { module = "com.miglayout:miglayout-swing", version.ref = "miglayout" } mimepull = { module = "org.jvnet.mimepull:mimepull", version = "1.9.7" } mockito-core = { module = "org.mockito:mockito-core", version.ref = "mockito" } -mockito-inline = { module = "org.mockito:mockito-inline", version.ref = "mockito" } mssql-jdbc = { module = "com.microsoft.sqlserver:mssql-jdbc", version = "10.2.4.jre11" } mybatis = { module = "org.mybatis:mybatis", version = "3.1.1" } mysql-connector-j = { module = "com.mysql:mysql-connector-j", version = "8.4.0" } @@ -225,7 +224,7 @@ netty-resolver = { module = "io.netty:netty-resolver", version.ref = "netty" } netty-transport = { module = "io.netty:netty-transport", version.ref = "netty" } netty-transport-native-epoll = { module = "io.netty:netty-transport-native-epoll", version.ref = "netty" } netty-transport-native-unix-common = { module = "io.netty:netty-transport-native-unix-common", version.ref = "netty" } -objenesis = { module = "org.objenesis:objenesis", version = "2.5.1" } +objenesis = { module = "org.objenesis:objenesis", version = "3.3" } ojdbc8 = { module = "com.oracle.database.jdbc:ojdbc8", version = "12.2.0.1" } openhtmltopdf-core = { module = "com.openhtmltopdf:openhtmltopdf-core", version.ref = "openhtmltopdf" } openhtmltopdf-pdfbox = { module = "com.openhtmltopdf:openhtmltopdf-pdfbox", version.ref = "openhtmltopdf" } @@ -647,7 +646,6 @@ server-test = [ "hamcrest", "junit", "mockito-core", - "mockito-inline", "objenesis", ] diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index a55f913c97..25f6759f93 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1,5 +1,5 @@ - + true false @@ -1246,25 +1246,25 @@ - - - + + + - - + + - - - + + + - - + + - - - + + + @@ -2533,41 +2533,41 @@ - - - + + + - - + + - - - + + + - - + + - - - + + + - - - + + + - - + + - - - + + + - - + + @@ -2769,20 +2769,12 @@ - - - + + + - - - - - - - - - - + + @@ -2827,17 +2819,17 @@ - - - + + + - - + + - - - + + + @@ -2858,12 +2850,12 @@ - - - + + + - - + + @@ -2874,14 +2866,6 @@ - - - - - - - - @@ -2890,12 +2874,17 @@ - - - + + + + + + + + - - + + @@ -2906,12 +2895,12 @@ - - - + + + - - + + diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 1b33c55baa..9fa7f28828 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 9128c7d428..5907d39c37 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,8 +1,10 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionSha256Sum=845952a9d6afa783db70bb3b0effaae45ae5542ca2bb7929619e8af49cb634cf -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.1-bin.zip +distributionSha256Sum=21bd5da2de49b642904077f38c0efdc7778e92b3ed0889392dca61b97e389607 +distributionUrl=https\://services.gradle.org/distributions/gradle-9.8.2-bin.zip networkTimeout=10000 +retries=0 +retryBackOffMs=500 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 23d15a9367..249efbb032 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright © 2015 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -20,7 +20,7 @@ ############################################################################## # -# Gradle start up script for POSIX generated by Gradle. +# gradlew start up script for POSIX generated by Gradle. # # Important for running: # @@ -29,7 +29,7 @@ # bash, then to run this script, type that shell name before the whole # command line, like: # -# ksh Gradle +# ksh gradlew # # Busybox and similar reduced shells will NOT work, because this script # requires all of these POSIX shell features: @@ -57,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/3d91ce3b8caaf77ad09f381f43615b715b53f72c/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -114,7 +114,6 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH="\\\"\\\"" # Determine the Java command to use to start the JVM. @@ -172,7 +171,6 @@ fi # For Cygwin or MSYS, switch paths to Windows format before running java if "$cygwin" || "$msys" ; then APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) JAVACMD=$( cygpath --unix "$JAVACMD" ) @@ -212,7 +210,6 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" diff --git a/gradlew.bat b/gradlew.bat index db3a6ac207..3185a43f78 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -19,12 +19,39 @@ @if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem -@rem Gradle startup script for Windows +@rem gradlew startup script for Windows @rem @rem ########################################################################## -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal +@rem Set local scope for the variables, and ensure extensions are enabled +setlocal EnableExtensions + +@rem Catch executions from older scripts and ensure they exit cleanly. +@rem This can be removed once we can be reasonably confident that few people +@rem will be migrating directly to this new wrapper. +goto afterSafetyNet +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +goto exitWithErrorLevel +:afterSafetyNet set DIRNAME=%~dp0 if "%DIRNAME%"=="" set DIRNAME=. @@ -45,13 +72,14 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. 1>&2 -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 +1>&2 echo. +1>&2 echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +1>&2 echo. +1>&2 echo Please set the JAVA_HOME variable in your environment to match the +1>&2 echo location of your Java installation. -goto fail +"%COMSPEC%" /c exit 1 +goto exitWithErrorLevel :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% @@ -59,36 +87,26 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. 1>&2 -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 +1>&2 echo. +1>&2 echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +1>&2 echo. +1>&2 echo Please set the JAVA_HOME variable in your environment to match the +1>&2 echo location of your Java installation. -goto fail +"%COMSPEC%" /c exit 1 +goto exitWithErrorLevel :execute @rem Setup the command line -set CLASSPATH= -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* +@rem Execute gradlew +@rem endlocal doesn't take effect until after the line is parsed and variables are expanded +@rem which allows us to clear the local environment before executing the java command +endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel & goto exitWithErrorLevel -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@rem This label must not be changed. We rely on old scripts being able to jump to this point. +:exitWithErrorLevel +@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts +"%COMSPEC%" /c exit %ERRORLEVEL% diff --git a/server/basedir-includes/oieserver b/server/basedir-includes/oieserver index e8f7b63740..22a8b9ed30 100755 --- a/server/basedir-includes/oieserver +++ b/server/basedir-includes/oieserver @@ -12,8 +12,8 @@ # server. It prepares the Java environment and executes the server launcher # JAR file. # -# The script automatically finds a compatible Java runtime (version 17+ by -# default) by searching for a valid executable in the following priority order: +# The script automatically finds a compatible Java runtime by searching for +# a valid executable in the following priority order: # 1. The OIE_JAVA_PATH environment variable. # 2. The -java-cmd directive in the oieserver.vmoptions file or included # .vmoptions files. Must specify the path to the 'java' executable. @@ -42,7 +42,7 @@ # ============================================================================= APP_ARGS=("$@") -MIN_JAVA_VERSION=17 +MIN_JAVA_VERSION=21 # Set OIE_HOME to the script directory OIE_HOME="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" @@ -127,7 +127,7 @@ is_valid_java_version() { fi # Execute 'java -version' and capture the output from stderr - # Example output: openjdk version "17.0.2" 2022-07-19 + # Example output: openjdk version "123.0.2" 2022-07-19 local version_output version_output=$("$java_cmd" -version 2>&1) @@ -136,7 +136,7 @@ is_valid_java_version() { return 1 fi - # Extract the major version number. This works for formats like "1.8.0" and "17.0.2". + # Extract the major version number. This works for formats like "1.8.0" and "123.0.2". local major_version major_version=$(echo "$version_output" | head -n 1 | cut -d '"' -f 2 | cut -d '.' -f 1) diff --git a/server/basedir-includes/oieserver.ps1 b/server/basedir-includes/oieserver.ps1 index 301d006f3c..cc06137d98 100644 --- a/server/basedir-includes/oieserver.ps1 +++ b/server/basedir-includes/oieserver.ps1 @@ -12,8 +12,8 @@ server. It prepares the Java environment and executes the server launcher JAR file. - The script automatically finds a compatible Java runtime (version 17+ by - default) by searching for a valid executable in the following priority order: + The script automatically finds a compatible Java runtime by searching for + a valid executable in the following priority order: 1. The OIE_JAVA_PATH environment variable. 2. The -java-cmd directive in the oieserver.vmoptions file or included .vmoptions @@ -53,7 +53,7 @@ param( # Stop on any error and exit non-zero $ErrorActionPreference = "Stop" -$MinJavaVersion = 17 +$MinJavaVersion = 21 # Set OieHome to the script directory using PowerShell's built-in variable $OieHome = $PSScriptRoot @@ -141,7 +141,7 @@ function Test-IsValidJavaVersion([string] $JavaCmd) { } # Execute 'java -version' and capture the output from stderr - # Example output: openjdk version "17.0.2" 2022-07-19 + # Example output: openjdk version "123.4.5" 2022-07-19 try { $versionOutput = & { $ErrorActionPreference = 'Continue'; @@ -156,7 +156,7 @@ function Test-IsValidJavaVersion([string] $JavaCmd) { return $false } - # Extract the major version number. This works for formats like "1.8.0" and "17.0.2". + # Extract the major version number. This works for formats like "1.8.0" and "123.4.5". $match = $versionOutput | Select-String -Pattern '"(\d+)\.' return ($match -and ($match.Matches[0].Groups[1].Value -as [int]) -ge $MinJavaVersion) } diff --git a/server/build.gradle b/server/build.gradle index d928023bb5..e29cbe9aef 100644 --- a/server/build.gradle +++ b/server/build.gradle @@ -41,12 +41,7 @@ def syncDonkeyLibs = tasks.register('syncDonkeyLibs', Sync) { compileJava.dependsOn syncDonkeyLibs compileTestJava { - options.compilerArgs += [ - '--add-modules=java.sql.rowset', - '--add-exports=java.sql.rowset/com.sun.rowset=ALL-UNNAMED', - '--add-exports=java.base/com.sun.crypto.provider=ALL-UNNAMED', - '--add-exports=java.base/sun.security.provider=ALL-UNNAMED', - ] + options.compilerArgs += ['--add-modules=java.sql.rowset'] } @@ -509,7 +504,7 @@ def userApiJavadoc = tasks.register('userApiJavadoc') { '-notimestamp', '-classpath', (configurations.compileClasspath + fileTree(dir: 'lib', include: '**/*.jar')).asPath, '-sourcepath', file('src/main/java').absolutePath, - '-link', 'https://docs.oracle.com/en/java/javase/17/docs/api/', + '-link', 'https://docs.oracle.com/en/java/javase/21/docs/api/', '-bottom', '\n\t\t\t\tLicensed under the Mozilla Public License 2.0.\n\t\t\t', '--add-modules=java.sql.rowset', '--add-exports=java.sql.rowset/com.sun.rowset=ALL-UNNAMED', diff --git a/server/docs/thirdparty/THIRD-PARTY-README.txt b/server/docs/thirdparty/THIRD-PARTY-README.txt index e8a549a155..e198fae473 100644 --- a/server/docs/thirdparty/THIRD-PARTY-README.txt +++ b/server/docs/thirdparty/THIRD-PARTY-README.txt @@ -1204,16 +1204,6 @@ SOFTWARE. -------------------------------------------------------------------------------- -Unmodified libraries from OpenJFX are licensed under the GNU General Public -License version 2, with the Classpath Exception. A copy of this license is -available in the file named GPLv2+CE.txt. - -The source code for OpenJFX is available at: http://jdk.java.net/openjfx/ - - --------------------------------------------------------------------------------- - - The OSHI library is licensed under the Eclipse Public License version 1.0. A copy of this license is available in the file named EPL-1.0.txt. diff --git a/server/src/test/java/com/mirth/commons/encryption/test/KeyEncryptorTest.java b/server/src/test/java/com/mirth/commons/encryption/test/KeyEncryptorTest.java index a2d0f12763..efa38bf28a 100644 --- a/server/src/test/java/com/mirth/commons/encryption/test/KeyEncryptorTest.java +++ b/server/src/test/java/com/mirth/commons/encryption/test/KeyEncryptorTest.java @@ -35,9 +35,9 @@ import com.mirth.commons.encryption.Output; import com.mirth.commons.encryption.util.EncryptionUtil; import com.mirth.connect.model.EncryptionSettings; -import com.sun.crypto.provider.SunJCE; public class KeyEncryptorTest { + private static final String SUNJCE_PROVIDER_CLASS = "com.sun.crypto.provider.SunJCE"; @Test public void testAESCBC128BC() throws Exception { @@ -65,7 +65,7 @@ public void testAESCBC128SunJCE() throws Exception { EncryptionSettings encryptionSettings = new EncryptionSettings(); encryptionSettings.setEncryptionAlgorithm("AES/CBC/PKCS5Padding"); encryptionSettings.setEncryptionKeyLength(128); - encryptionSettings.setSecurityProvider(SunJCE.class.getName()); + encryptionSettings.setSecurityProvider(SUNJCE_PROVIDER_CLASS); encryptionSettings.setEncryptionCharset(StandardCharsets.UTF_8.name()); testEncryptAndDecrypt(encryptionSettings); } @@ -76,7 +76,7 @@ public void testAESCBC128SunJCE() throws Exception { // EncryptionSettings encryptionSettings = new EncryptionSettings(); // encryptionSettings.setEncryptionAlgorithm("AES/CBC/PKCS5Padding"); // encryptionSettings.setEncryptionKeyLength(256); -// encryptionSettings.setSecurityProvider(SunJCE.class.getName()); +// encryptionSettings.setSecurityProvider(SUNJCE_PROVIDER_CLASS); // encryptionSettings.setEncryptionCharset(StandardCharsets.UTF_8.name()); // testEncryptAndDecrypt(encryptionSettings); // } @@ -161,7 +161,7 @@ public void testAESCBC128SunJCE_AESGCM128BC() throws Exception { EncryptionSettings oldEncryptionSettings = new EncryptionSettings(); oldEncryptionSettings.setEncryptionAlgorithm("AES/CBC/PKCS5Padding"); oldEncryptionSettings.setEncryptionKeyLength(128); - oldEncryptionSettings.setSecurityProvider(SunJCE.class.getName()); + oldEncryptionSettings.setSecurityProvider(SUNJCE_PROVIDER_CLASS); oldEncryptionSettings.setEncryptionCharset(StandardCharsets.UTF_8.name()); EncryptionSettings encryptionSettings = new EncryptionSettings(); @@ -225,7 +225,7 @@ public void testDESCBC56SunJCE() throws Exception { EncryptionSettings encryptionSettings = new EncryptionSettings(); encryptionSettings.setEncryptionAlgorithm("DES/CBC/PKCS5Padding"); encryptionSettings.setEncryptionKeyLength(56); - encryptionSettings.setSecurityProvider(SunJCE.class.getName()); + encryptionSettings.setSecurityProvider(SUNJCE_PROVIDER_CLASS); encryptionSettings.setEncryptionCharset(StandardCharsets.UTF_8.name()); testEncryptAndDecrypt(encryptionSettings); } diff --git a/tools/install4j/oie-installer-config.install4j b/tools/install4j/oie-installer-config.install4j index d38a5ab842..4cabf23c44 100644 --- a/tools/install4j/oie-installer-config.install4j +++ b/tools/install4j/oie-installer-config.install4j @@ -1,10 +1,10 @@ - + - +