diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 0c3b7b4..11a86f5 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -18,7 +18,7 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 - name: Gradle Cache uses: actions/cache@v3 @@ -31,10 +31,10 @@ jobs: ${{ runner.os }}-gradle- - name: Set up JDK - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: temurin - java-version: 11 + java-version: 21 - name: Build with Gradle run: ./gradlew build @@ -44,13 +44,13 @@ jobs: working-directory: build/distributions - name: Save artefacts - uses: actions/upload-artifact@v3.1.2 + uses: actions/upload-artifact@v4.0.0 with: name: Artefacts path: build/distributions - name: Save Coverage Report - uses: actions/upload-artifact@v3.1.2 + uses: actions/upload-artifact@v4.0.0 with: name: CoverageReport path: build/reports/tests/test diff --git a/.idea/misc.xml b/.idea/misc.xml index ee3319a..2758df8 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -4,7 +4,7 @@ - + \ No newline at end of file diff --git a/README.md b/README.md index b5edc73..dfb3030 100644 --- a/README.md +++ b/README.md @@ -53,11 +53,11 @@ unable to find valid certification path to requested target This is because the Java Keystore used by the admin console package does not recognize the Root CA certificate used to sign openEQUELLA's SSL certificate. -The admin-console-package uses its own copy of the JRE, in the `jdk-11.0.18+10-jre` folder. -The keystore we need to update is within this folder, at the path `jdk-11.0.18+10-jre/lib/security/cacerts`. +The admin-console-package uses its own copy of the JRE, in the `jdk-21.0.1+12-jre` folder. +The keystore we need to update is within this folder, at the path `jdk-21.0.1+12-jre/lib/security/cacerts`. The bundled JRE comes with a command line tool which you can use for updating these keystores, called `keytool`. -This should work in Mac, Linux and Windows. It is stored in `jdk-11.0.18+10-jre/bin`. +This should work in Mac, Linux and Windows. It is stored in `jdk-21.0.1+12-jre/bin`. **NOTE:** @@ -72,7 +72,7 @@ You will need a copy of the Root CA certificate used to sign your SSL certificat in which case you should use whatever it was set to. ``` -keytool -import -trustcacerts -keystore path/to/adminconsolepackage/jdk-11.0.18+10-jre/lib/security/cacerts -storepass changeit -alias giveYourCertANameHere -file path/to/rootCA.pem +keytool -import -trustcacerts -keystore path/to/adminconsolepackage/jdk-21.0.1+12-jre/lib/security/cacerts -storepass changeit -alias giveYourCertANameHere -file path/to/rootCA.pem ``` The command will display the certificate and prompt the user to `Trust this certificate? [no]:`. Type `yes` and hit Enter. diff --git a/build.gradle b/build.gradle index 7389d8d..6e55bf4 100644 --- a/build.gradle +++ b/build.gradle @@ -16,16 +16,18 @@ repositories { } dependencies { - implementation 'org.slf4j:slf4j-api:2.0.7' - implementation 'com.fasterxml.jackson.core:jackson-databind:2.15.2' + implementation 'org.slf4j:slf4j-api:2.0.11' + implementation 'com.fasterxml.jackson.core:jackson-databind:2.16.1' implementation 'org.jasypt:jasypt:1.9.3' - runtimeOnly 'org.slf4j:slf4j-simple:2.0.7' + runtimeOnly 'org.slf4j:slf4j-simple:2.0.11' testImplementation "junit:junit:$junitVersion" } group = 'org.apereo.openequella.adminconsole' version = System.getenv("TRAVIS_TAG") ?: artifactVersion -mainClassName = 'org.apereo.openequella.adminconsole.launcher.ClientLauncher' +application { + mainClass = 'org.apereo.openequella.adminconsole.launcher.ClientLauncher' +} license { strictCheck @@ -37,14 +39,15 @@ jar { manifest { attributes('Implementation-Title': project.name, 'Implementation-Version': project.version, - 'Main-Class': mainClassName, + 'Main-Class': application.mainClass, "Class-Path": configurations.runtimeClasspath.files.collect { it.getName() }.join(' ')) } } -final jreDownloadDir = file("$buildDir/jre-downloads") +final buildDirectory = getLayout().getBuildDirectory() +final jreDownloadDir = buildDirectory.dir("jre-downloads").get().asFile final jreExtractDir = {sys -> "${jreDownloadDir.absolutePath}/jre/${sys}"} -final jarDir = "${buildDir}/libs" +final jarDir = buildDirectory.dir("libs").get().asFile final launcherScripts = [ windows: 'Windows-launcher.bat', linux: 'Linux-launcher.sh', @@ -54,26 +57,27 @@ final launcherScripts = [ class JreProperties { String hash String fileName - String getDownloadUrl() {"https://github.com/adoptium/temurin11-binaries/releases/download/jdk-11.0.18%2B10/${fileName}"} + String getDownloadUrl() {"https://github.com/adoptium/temurin21-binaries/releases/download/jdk-21.0.1%2B12/${fileName}"} File getJre() {new File("build/jre-downloads/${fileName}")} } final jreProperties = [ windows: new JreProperties( - hash: 'dea0fe7fd5fc52cf5e1d3db08846b6a26238cfcc36d5527d1da6e3cb059071b3', - fileName: 'OpenJDK11U-jre_x64_windows_hotspot_11.0.18_10.zip'), + hash: '38bb68f9db9c85a63496570c53a1bcbac18c808677595d7e939d2f5b38e9a7aa', + fileName: 'OpenJDK21U-jre_x64_windows_hotspot_21.0.1_12.zip'), linux: new JreProperties( - hash: '0e7b196ef8603ac3d38caaf7768b7b0a3c613d60e15a6511bcfb2c894b609e99', - fileName: 'OpenJDK11U-jre_x64_linux_hotspot_11.0.18_10.tar.gz'), + hash: '277f4084bee875f127a978253cfbaad09c08df597feaf5ccc82d2206962279a3', + fileName: 'OpenJDK21U-jre_x64_linux_hotspot_21.0.1_12.tar.gz'), mac: new JreProperties( - hash: '7c73b1a731fc840f2ecb5633906d687bfee4346a8191d3cb1c4370168b16351f', - fileName: 'OpenJDK11U-jre_x64_mac_hotspot_11.0.18_10.tar.gz') + hash: 'c21a2648ec21bc4701acfb6b7a1fd90aca001db1efb8454e2980d4c8dcd9e310', + fileName: 'OpenJDK21U-jre_x64_mac_hotspot_21.0.1_12.tar.gz') ] task copyDependencies(type: Copy, description: 'Copy dependencies to /build/libs') { - from configurations.default + from configurations.runtimeClasspath into(jarDir) } +copyDependencies.mustRunAfter(startScripts) task downloadJre(description: 'Download OpenJRE of Linux, Windows and Mac') { doFirst { @@ -85,7 +89,7 @@ task downloadJre(description: 'Download OpenJRE of Linux, Windows and Mac') { .collect {String sys, JreProperties props -> Thread.start { println("Start downloading OpenJRE for ${sys}...") - new URL(props.downloadUrl as String).withInputStream { + new URI(props.downloadUrl as String).toURL().withInputStream { props.jre.newOutputStream() << it } } @@ -150,8 +154,8 @@ distributions { "${sys}Packages" { distributionBaseName = "admin-console-package-for-${sys}" contents { - from("${buildDir}") { - include "libs/*" + into("libs") { + from {jarDir} } from {file(jreExtractDir(sys))} from {file(scriptFileDir)} diff --git a/gradle.properties b/gradle.properties index de8ce80..d0cafdc 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1,2 @@ junitVersion=4.13.2 -artifactVersion=1.2.1 +artifactVersion=1.3.0 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 943f0cb..afba109 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 e8be595..829e1a5 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-all.zip networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/launcher-scripts/Linux-launcher.sh b/launcher-scripts/Linux-launcher.sh index e2e3838..bc1b288 100755 --- a/launcher-scripts/Linux-launcher.sh +++ b/launcher-scripts/Linux-launcher.sh @@ -1,6 +1,6 @@ #!/bin/bash OLD_JAVA_HOME=$JAVA_HOME SCRIPT_DIRECTORY=`readlink -f "$(dirname "$0")"` -export JAVA_HOME=$SCRIPT_DIRECTORY/jdk-11.0.18+10-jre +export JAVA_HOME=$SCRIPT_DIRECTORY/jdk-21.0.1+12-jre "$JAVA_HOME/bin/java" -DLAUNCHER_JAVA_PATH="$JAVA_HOME/bin/java" -jar "$SCRIPT_DIRECTORY/libs/admin.jar" export JAVA_HOME=$OLD_JAVA_HOME diff --git a/launcher-scripts/Mac-launcher.sh b/launcher-scripts/Mac-launcher.sh index 586edcb..41a07e8 100755 --- a/launcher-scripts/Mac-launcher.sh +++ b/launcher-scripts/Mac-launcher.sh @@ -1,6 +1,6 @@ #!/bin/zsh OLD_JAVA_HOME=$JAVA_HOME SCRIPT_DIRECTORY=${0:A:h} -export JAVA_HOME=$SCRIPT_DIRECTORY/jdk-11.0.18+10-jre/Contents/Home +export JAVA_HOME=$SCRIPT_DIRECTORY/jdk-21.0.1+12-jre/Contents/Home "$JAVA_HOME/bin/java" -DLAUNCHER_JAVA_PATH="$JAVA_HOME/bin/java" -jar "$SCRIPT_DIRECTORY/libs/admin.jar" export JAVA_HOME=$OLD_JAVA_HOME diff --git a/launcher-scripts/Windows-launcher.bat b/launcher-scripts/Windows-launcher.bat index 86efd96..3bef5ed 100755 --- a/launcher-scripts/Windows-launcher.bat +++ b/launcher-scripts/Windows-launcher.bat @@ -1,7 +1,7 @@ @echo off set OLD_JAVA_HOME="%JAVA_HOME%" set "BAT_DIRECTORY=%~dp0" -set "JAVA_HOME=%BAT_DIRECTORY%jdk-11.0.18+10-jre" +set "JAVA_HOME=%BAT_DIRECTORY%jdk-21.0.1+12-jre" start "Admin console launcher" /D "%BAT_DIRECTORY%\libs" "%JAVA_HOME%\bin\javaw" -DLAUNCHER_JAVA_PATH="%JAVA_HOME%\bin\java" -jar admin.jar set JAVA_HOME="%OLD_JAVA_HOME%" set OLD_JAVA_HOME="" diff --git a/settings.gradle b/settings.gradle index db95572..3f7d82c 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,2 +1 @@ rootProject.name = 'admin-console-launcher' -include 'launcher' diff --git a/src/main/java/org/apereo/openequella/adminconsole/launcher/ClientLauncher.java b/src/main/java/org/apereo/openequella/adminconsole/launcher/ClientLauncher.java index a25b01f..9f9c679 100644 --- a/src/main/java/org/apereo/openequella/adminconsole/launcher/ClientLauncher.java +++ b/src/main/java/org/apereo/openequella/adminconsole/launcher/ClientLauncher.java @@ -26,6 +26,7 @@ import org.apereo.openequella.adminconsole.swing.ServerPicker; import org.apereo.openequella.adminconsole.swing.TableLayout; import org.apereo.openequella.adminconsole.util.BlindSSLSocketFactory; +import org.apereo.openequella.adminconsole.util.IconUtil; import org.apereo.openequella.adminconsole.util.Proxy; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -72,7 +73,6 @@ public class ClientLauncher extends JFrame implements ActionListener, WindowList private final JButton makeDefaultServerButton; private final JButton editProxyButton; private final JButton launchButton; - private final Image icon; public static void main(String args[]) throws Exception { new ClientLauncher(); @@ -92,8 +92,8 @@ public ClientLauncher() { makeDefaultServerButton = new JButton(MAKE_DEFAULT_SERVER_BUTTON); launchButton = new JButton(LAUNCH_BUTTON); - icon = new ImageIcon(getClass().getResource("/adminconsoleicon.png")).getImage(); - setIconImage(icon); + setIconImages(IconUtil.ICONS); + setTitle(WINDOW_TITLE); setResizable(false); addWindowListener(this); @@ -194,7 +194,7 @@ private static Config readConfig() { private void launch(final ServerProfile serverProfile) { final SwingWorker worker = new SwingWorker() { - final LoadingDialog loadingDialog = new LoadingDialog(ClientLauncher.this, icon, LOADING_DIALOG_TITLE); + final LoadingDialog loadingDialog = new LoadingDialog(ClientLauncher.this, IconUtil.ICONS, LOADING_DIALOG_TITLE); @Override public Object doInBackground() throws Exception { diff --git a/src/main/java/org/apereo/openequella/adminconsole/launcher/LoadingDialog.java b/src/main/java/org/apereo/openequella/adminconsole/launcher/LoadingDialog.java index 35d21ae..21961b4 100644 --- a/src/main/java/org/apereo/openequella/adminconsole/launcher/LoadingDialog.java +++ b/src/main/java/org/apereo/openequella/adminconsole/launcher/LoadingDialog.java @@ -19,6 +19,7 @@ import java.awt.Dimension; import java.awt.Image; +import java.util.List; import javax.swing.JDialog; import javax.swing.JFrame; @@ -29,12 +30,12 @@ public class LoadingDialog extends JDialog { private static final long serialVersionUID = 1L; - public LoadingDialog(JFrame parent, Image icon, String title) { + public LoadingDialog(JFrame parent, List icons, String title) { super(parent); setTitle(title); setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); setUndecorated(true); - setIconImage(icon); + setIconImages(icons); setSize(new Dimension(200, 30)); final JProgressBar loadingProgressBar = new JProgressBar(); loadingProgressBar.setIndeterminate(true); diff --git a/src/main/java/org/apereo/openequella/adminconsole/service/JarService.java b/src/main/java/org/apereo/openequella/adminconsole/service/JarService.java index 1c4a4d3..5a623be 100644 --- a/src/main/java/org/apereo/openequella/adminconsole/service/JarService.java +++ b/src/main/java/org/apereo/openequella/adminconsole/service/JarService.java @@ -25,6 +25,7 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; +import java.net.URI; import java.net.URL; import java.nio.file.Files; import java.nio.file.StandardCopyOption; @@ -84,7 +85,7 @@ public void downloadJar(String jarName) { // hit the server to download //final URL url = new URL(baseUrl + "/console.do?jar=" + URLEncoder.encode(jarName + ".jar", "utf-8")); final String strUrl = baseUrl + (baseUrl.endsWith("/") ? "" : "/") + "adminconsole.jar"; - final URL url = new URL(strUrl); + final URL url = new URI(strUrl).toURL(); HttpURLConnection conn = null; try { conn = (HttpURLConnection) url.openConnection(); diff --git a/src/main/java/org/apereo/openequella/adminconsole/util/BlindSSLSocketFactory.java b/src/main/java/org/apereo/openequella/adminconsole/util/BlindSSLSocketFactory.java index dc85ed8..894a301 100644 --- a/src/main/java/org/apereo/openequella/adminconsole/util/BlindSSLSocketFactory.java +++ b/src/main/java/org/apereo/openequella/adminconsole/util/BlindSSLSocketFactory.java @@ -36,7 +36,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class BlindSSLSocketFactory extends SSLSocketFactory { +public class BlindSSLSocketFactory extends SSLSocketFactory implements AutoCloseable { private static final Logger LOGGER = LoggerFactory.getLogger(BlindSSLSocketFactory.class); private static SSLSocketFactory originalFactory; private static HostnameVerifier originalHostnameVerifier; @@ -101,17 +101,6 @@ public boolean verify(String hostname, SSLSession session) { } } - @Override - protected void finalize() throws Throwable { - if (originalFactory != null) { - HttpsURLConnection.setDefaultSSLSocketFactory(originalFactory); - } - if (originalHostnameVerifier != null) { - HttpsURLConnection.setDefaultHostnameVerifier(originalHostnameVerifier); - } - super.finalize(); - } - @Override public Socket createSocket(String arg0, int arg1) throws IOException { return blindFactory.createSocket(arg0, arg1); @@ -147,4 +136,14 @@ public String[] getDefaultCipherSuites() { public String[] getSupportedCipherSuites() { return blindFactory.getSupportedCipherSuites(); } + + @Override + public void close() { + if (originalFactory != null) { + HttpsURLConnection.setDefaultSSLSocketFactory(originalFactory); + } + if (originalHostnameVerifier != null) { + HttpsURLConnection.setDefaultHostnameVerifier(originalHostnameVerifier); + } + } } diff --git a/src/main/java/org/apereo/openequella/adminconsole/util/IconUtil.java b/src/main/java/org/apereo/openequella/adminconsole/util/IconUtil.java new file mode 100644 index 0000000..b6b0934 --- /dev/null +++ b/src/main/java/org/apereo/openequella/adminconsole/util/IconUtil.java @@ -0,0 +1,63 @@ +/* + * Licensed to The Apereo Foundation under one or more contributor license + * agreements. See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * The Apereo Foundation 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: + * + * 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. + */ +package org.apereo.openequella.adminconsole.util; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.imageio.ImageIO; +import java.awt.*; +import java.io.IOException; +import java.net.URL; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +public final class IconUtil { + private static final Logger LOGGER = LoggerFactory.getLogger(IconUtil.class); + private static final int[] ICON_SIZES = {16, 24, 32, 48, 64, 72, 96, 128, 256}; + public static final List ICONS; + + static { + ICONS = + Arrays.stream(ICON_SIZES) + .mapToObj(IconUtil::getIconURL) + .map( + icon -> { + try { + return ImageIO.read(icon); + } catch (IOException e) { + LOGGER.error("Failed to load icon: ", e); + return null; + } + }) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + } + + private static URL getIconURL(int dim) { + String path = "/adminconsoleicon." + dim + "x" + dim + "px.png"; + return Objects.requireNonNull( + IconUtil.class.getResource(path), "Failed to get icon of: " + path); + } + + private IconUtil() { + throw new UnsupportedOperationException("Utility class cannot be instantiated"); + } +} diff --git a/src/main/resources/adminconsoleicon.128x128px.png b/src/main/resources/adminconsoleicon.128x128px.png new file mode 100644 index 0000000..0adb51f Binary files /dev/null and b/src/main/resources/adminconsoleicon.128x128px.png differ diff --git a/src/main/resources/adminconsoleicon.16x16px.png b/src/main/resources/adminconsoleicon.16x16px.png new file mode 100644 index 0000000..12c8577 Binary files /dev/null and b/src/main/resources/adminconsoleicon.16x16px.png differ diff --git a/src/main/resources/adminconsoleicon.24x24px.png b/src/main/resources/adminconsoleicon.24x24px.png new file mode 100644 index 0000000..c0628cc Binary files /dev/null and b/src/main/resources/adminconsoleicon.24x24px.png differ diff --git a/src/main/resources/adminconsoleicon.256x256px.png b/src/main/resources/adminconsoleicon.256x256px.png new file mode 100644 index 0000000..ecb3490 Binary files /dev/null and b/src/main/resources/adminconsoleicon.256x256px.png differ diff --git a/src/main/resources/adminconsoleicon.32x32px.png b/src/main/resources/adminconsoleicon.32x32px.png new file mode 100644 index 0000000..e08b53c Binary files /dev/null and b/src/main/resources/adminconsoleicon.32x32px.png differ diff --git a/src/main/resources/adminconsoleicon.48x48px.png b/src/main/resources/adminconsoleicon.48x48px.png new file mode 100644 index 0000000..06aa4c8 Binary files /dev/null and b/src/main/resources/adminconsoleicon.48x48px.png differ diff --git a/src/main/resources/adminconsoleicon.64x64px.png b/src/main/resources/adminconsoleicon.64x64px.png new file mode 100644 index 0000000..5642690 Binary files /dev/null and b/src/main/resources/adminconsoleicon.64x64px.png differ diff --git a/src/main/resources/adminconsoleicon.72x72px.png b/src/main/resources/adminconsoleicon.72x72px.png new file mode 100644 index 0000000..ca5f2df Binary files /dev/null and b/src/main/resources/adminconsoleicon.72x72px.png differ diff --git a/src/main/resources/adminconsoleicon.96x96px.png b/src/main/resources/adminconsoleicon.96x96px.png new file mode 100644 index 0000000..e50211f Binary files /dev/null and b/src/main/resources/adminconsoleicon.96x96px.png differ diff --git a/src/main/resources/adminconsoleicon.png b/src/main/resources/adminconsoleicon.png deleted file mode 100644 index afee059..0000000 Binary files a/src/main/resources/adminconsoleicon.png and /dev/null differ