From: Ben Soares Date: Mon, 24 Jun 2024 23:23:00 +0000 (+0100) Subject: JAL-3631 Check Implementation-Version of getdown-launcher.jar in installation appdir... X-Git-Tag: Release_2_11_4_0~24^2~22 X-Git-Url: http://source.jalview.org/gitweb/?a=commitdiff_plain;h=1cf32cdac3840df102b4f4b9261a310dc18e14bc;p=jalview.git JAL-3631 Check Implementation-Version of getdown-launcher.jar in installation appdir and user's appdir, and only use the user one if it's newer. Remove content digest check for getdown-launcher.jar comparison since version now being checked. --- diff --git a/getdown/lib/FJVL_VERSION b/getdown/lib/FJVL_VERSION index 21df89d..5658c0d 100644 --- a/getdown/lib/FJVL_VERSION +++ b/getdown/lib/FJVL_VERSION @@ -1 +1 @@ -1.8.3-1.4.0_FJVL +1.8.3-1.4.1_FJVL diff --git a/getdown/lib/JVL_VERSION b/getdown/lib/JVL_VERSION index 2d02e7a..de777a1 100644 --- a/getdown/lib/JVL_VERSION +++ b/getdown/lib/JVL_VERSION @@ -1 +1 @@ -1.8.3-1.4.0_JVL +1.8.3-1.4.1_JVL diff --git a/getdown/lib/getdown-core.jar b/getdown/lib/getdown-core.jar index 7be6374..7cb005e 100644 Binary files a/getdown/lib/getdown-core.jar and b/getdown/lib/getdown-core.jar differ diff --git a/getdown/lib/getdown-launcher-local.jar b/getdown/lib/getdown-launcher-local.jar index dca82cd..cd0824c 100644 Binary files a/getdown/lib/getdown-launcher-local.jar and b/getdown/lib/getdown-launcher-local.jar differ diff --git a/getdown/lib/getdown-launcher.jar b/getdown/lib/getdown-launcher.jar index f2f681d..d30f084 100644 Binary files a/getdown/lib/getdown-launcher.jar and b/getdown/lib/getdown-launcher.jar differ diff --git a/getdown/src/getdown/ant/pom.xml b/getdown/src/getdown/ant/pom.xml index ce84058..75ec538 100644 --- a/getdown/src/getdown/ant/pom.xml +++ b/getdown/src/getdown/ant/pom.xml @@ -4,7 +4,7 @@ com.threerings.getdown getdown - 1.8.3-1.4.0_FJVL + 1.8.3-1.4.1_FJVL getdown-ant diff --git a/getdown/src/getdown/core/pom.xml b/getdown/src/getdown/core/pom.xml index c926ab2..4670d8d 100644 --- a/getdown/src/getdown/core/pom.xml +++ b/getdown/src/getdown/core/pom.xml @@ -4,7 +4,7 @@ com.threerings.getdown getdown - 1.8.3-1.4.0_FJVL + 1.8.3-1.4.1_FJVL getdown-core diff --git a/getdown/src/getdown/core/src/main/java/com/threerings/getdown/data/Application.java b/getdown/src/getdown/core/src/main/java/com/threerings/getdown/data/Application.java index 9429efc..74814c6 100644 --- a/getdown/src/getdown/core/src/main/java/com/threerings/getdown/data/Application.java +++ b/getdown/src/getdown/core/src/main/java/com/threerings/getdown/data/Application.java @@ -1104,6 +1104,12 @@ public class Application if (System.getProperty("installer.extrainfo") != null) { args.add("-Dinstaller.extrainfo=" + System.getProperty("installer.extrainfo")); } + + // backward compatibility (old getdown-launcher.jar) + args.add("-Dgetdownappdir=" + getAppDir()); + args.add("-Dgetdowninstanceappbase=" + getAppbase().toString()); + args.add("-Dinstaller_template_version=" + System.getProperty("installer.template_version")); + args.add("-Dlauncher_version=" + Build.version()); // set HiDPI property if wanted String scalePropertyArg = HiDPISetting.getScalePropertyArg(); diff --git a/getdown/src/getdown/core/src/main/java/com/threerings/getdown/data/EnvConfig.java b/getdown/src/getdown/core/src/main/java/com/threerings/getdown/data/EnvConfig.java index 735ce8d..e644565 100644 --- a/getdown/src/getdown/core/src/main/java/com/threerings/getdown/data/EnvConfig.java +++ b/getdown/src/getdown/core/src/main/java/com/threerings/getdown/data/EnvConfig.java @@ -15,6 +15,9 @@ import java.security.cert.Certificate; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.*; +import java.util.jar.Attributes; +import java.util.jar.JarInputStream; +import java.util.jar.Manifest; import com.threerings.getdown.util.Config; import com.threerings.getdown.util.LaunchUtil; @@ -184,39 +187,36 @@ public final class EnvConfig { File appdirGetdown = new File(appDir, getdown); if (appdirGetdown.exists()) { File installerGetdown = new File(installerAppdir, getdown); - try { - Resource appdirGetdownResource = new Resource(appdirGetdown.getAbsolutePath(), null, appdirGetdown, Resource.NORMAL); - Resource installerGetdownResource = new Resource(installerGetdown.getAbsolutePath(), null, installerGetdown, Resource.NORMAL); - MessageDigest md = Digest.getMessageDigest(1); - String appdirGetdownDigest = appdirGetdownResource.computeDigest(1, md, null); - String installerGetdownDigest = installerGetdownResource.computeDigest(1, md, null); - if (!appdirGetdownDigest.equals(installerGetdownDigest)) { // not the same file content - // change classpath and restart. A null startClass looks it up from system property "sun.java.command" - String javaBin = LaunchUtils.findJavaBin(false); - List removeClasspath = new ArrayList<>(); - removeClasspath.add(installerGetdown.getAbsolutePath()); - List prependClasspath = new ArrayList<>(); - prependClasspath.add(appdirGetdown.getAbsolutePath()); - // ensure the appdir and appid are also added as command line arguments for backwards compatibility (earlier versions of getdown-launcher.jar) - List removeArgs = new ArrayList<>(); - removeArgs.add(argvAppDir); - removeArgs.add(argvAppId); - List addArgs = new ArrayList<>(); - addArgs.add(appDir); - addArgs.add(appId); - String startClassName = startClass == null ? null : startClass.getName(); - int exitValue = LaunchUtils.startNewJvm(javaBin, null, null, prependClasspath, null, removeClasspath, startClassName, removeArgs, addArgs, Arrays.asList(argv), true, true, false, true, false); - - if (exitValue == 0) { - notes.add(Note.info("Relaunching getdown succeeded. Original getdown exiting now.")); - setRelaunched(true); - return null; - } else { - notes.add(Note.warn("Relaunching getdown did not seem to succeed with exit value " + exitValue + ". Continuing with this getdown process.")); - } + int launcherVersionComparison = LaunchUtils.compareGetdownLauncherJarVersions(installerGetdown, appdirGetdown); + notes.add(Note.info("Comparing launchers: installation launcher '" + installerGetdown.getAbsolutePath() + + "', user launcher '" + appdirGetdown.getAbsoluteFile() + "', comparison=" + launcherVersionComparison)); + if (launcherVersionComparison > 0) { + notes.add(Note.info("Using user appdir launcher at '" + appdirGetdown.getAbsolutePath() + "'")); + // change classpath and restart. A null startClass looks it up from system property "sun.java.command" + String javaBin = LaunchUtils.findJavaBin(false); + List removeClasspath = new ArrayList<>(); + removeClasspath.add(installerGetdown.getAbsolutePath()); + List prependClasspath = new ArrayList<>(); + prependClasspath.add(appdirGetdown.getAbsolutePath()); + // ensure the appdir and appid are also added as command line arguments for backwards compatibility (earlier versions of getdown-launcher.jar) + List removeArgs = new ArrayList<>(); + removeArgs.add(argvAppDir); + removeArgs.add(argvAppId); + List addArgs = new ArrayList<>(); + addArgs.add(appDir); + addArgs.add(appId); + String startClassName = startClass == null ? null : startClass.getName(); + int exitValue = LaunchUtils.startNewJvm(javaBin, null, null, prependClasspath, null, removeClasspath, startClassName, removeArgs, addArgs, Arrays.asList(argv), true, true, false, true, false); + + if (exitValue == 0) { + notes.add(Note.info("Relaunching getdown succeeded. Original getdown exiting now.")); + setRelaunched(true); + return null; + } else { + notes.add(Note.warn("Relaunching getdown did not seem to succeed with exit value " + exitValue + ". Continuing with this getdown process.")); } - } catch (IOException e) { - notes.add(Note.warn("IOException opening '" + appdirGetdown.getAbsolutePath() + "' and '" + installerGetdown.getAbsolutePath() + "' as Resources. Continuing without restart. " + e.getMessage())); + } else { + notes.add(Note.info("Using user installion launcher at '" + appdirGetdown.getAbsolutePath() + "'")); } } } @@ -403,7 +403,7 @@ public final class EnvConfig { static { // paths from user.home with application folder added to end. '/' replaced with file.separator osAppDataPathMap = new HashMap<>(); - osAppDataPathMap.put("macos", "Library/Application Support/Jaview-Desktop"); + osAppDataPathMap.put("macos", "Library/Application Support/Jalview-Desktop"); osAppDataPathMap.put("linux", ".local/share/jalview-desktop"); osAppDataPathMap.put("windows", "AppData/Local/Jalview-Desktop"); osAppDataPathMap.put("other", ".jalview-desktop"); diff --git a/getdown/src/getdown/core/src/main/java/jalview/util/LaunchUtils.java b/getdown/src/getdown/core/src/main/java/jalview/util/LaunchUtils.java index 0b18c6c..dc8961f 100644 --- a/getdown/src/getdown/core/src/main/java/jalview/util/LaunchUtils.java +++ b/getdown/src/getdown/core/src/main/java/jalview/util/LaunchUtils.java @@ -37,6 +37,9 @@ import java.util.Locale; import java.util.Properties; import java.util.Set; import java.util.concurrent.TimeUnit; +import java.util.jar.Attributes; +import java.util.jar.JarInputStream; +import java.util.jar.Manifest; public class LaunchUtils { @@ -672,6 +675,137 @@ public class LaunchUtils } */ + /** + * Look for Implementation-Version in two jar manifests and compare according + * to the getdown-launcher version spec (1.8.3-1.4.0_JVL or _FJVL) returns -1 + * if f0 is newer (or more "valid"), +1 if f1 is newer (or more "valid"), 0 if + * the same or both equally "invalid" + * + * @param f0 + * @param f1 + * @return int + */ + public static int compareGetdownLauncherJarVersions(File f0, File f1) + { + if (!f0.exists() && !f1.exists()) + { + return 0; + } + if (!f0.exists()) + { + return 1; + } + if (!f1.exists()) + { + return -1; + } + String v0 = getJarImplementationVersion(f0); + String v1 = getJarImplementationVersion(f1); + syserr(true, false, + "Got launcher versions '" + v0 + "' and '" + v1 + "'"); + if (v0 == null && v1 == null) + { + return 0; + } + if (v0 == null) + { + return 1; + } + if (v1 == null) + { + return -1; + } + // now for the fun + if (v0.endsWith("JVL")) + { + v0 = v0.substring(0, v0.lastIndexOf('_')); + } + if (v1.endsWith("JVL")) + { + v1 = v1.substring(0, v1.lastIndexOf('_')); + } + + String[] v0parts = v0.split("-"); + String[] v1parts = v1.split("-"); + + int compare = 0; + for (int j = 0; j < Math.min(v0parts.length, v1parts.length); j++) + { + compare = 0; + try + { + compare = compareVersions(v0parts[j], v1parts[j]); + } catch (NumberFormatException e) + { + syserr(true, false, + "Problem parsing one of the getdown launcher version numbers: '" + + v0 + "', '" + v1 + "'"); + } + + if (compare != 0 + || (v0parts.length == j + 1 && v1parts.length == j + 1)) + { + return compare; + } + } + + return v1parts.length - v0parts.length; + } + + // just comparing 1.2.3.4...n + public static int compareVersions(String v0, String v1) + throws NumberFormatException + { + if (v0 == null && v1 == null) + { + return 0; + } + if (v0 == null) + { + return 1; + } + if (v1 == null) + { + return -1; + } + String[] v0dots = v0.split("\\."); + String[] v1dots = v1.split("\\."); + for (int i = 0; i < Math.min(v0dots.length, v1dots.length); i++) + { + if (!v0dots[i].equals(v1dots[i])) + { + return Integer.parseInt(v1dots[i]) - Integer.parseInt(v0dots[i]); + } + } + // all numbers match up to min length. If one has more dots, assume it's + // bigger. + return v1dots.length - v0dots.length; + } + + public static String getJarImplementationVersion(File jarFile) + { + String implementationVersion = null; + try + { + JarInputStream j0 = new JarInputStream(new FileInputStream(jarFile)); + Manifest m0 = j0.getManifest(); + if (m0 == null) + { + System.err.println("No manifest in " + jarFile.getAbsolutePath()); + } + else + { + implementationVersion = m0.getMainAttributes() + .getValue(Attributes.Name.IMPLEMENTATION_VERSION); + } + } catch (IOException e) + { + System.err.println("Exception opening " + jarFile.getAbsolutePath() + + " to check version: " + e.getMessage()); + } + return implementationVersion; + } + public static void syserr(boolean debug, boolean quiet, String message) { if (debug && !quiet) diff --git a/getdown/src/getdown/launcher/pom.xml b/getdown/src/getdown/launcher/pom.xml index 876efd2..13303fa 100644 --- a/getdown/src/getdown/launcher/pom.xml +++ b/getdown/src/getdown/launcher/pom.xml @@ -4,7 +4,7 @@ com.threerings.getdown getdown - 1.8.3-1.4.0_FJVL + 1.8.3-1.4.1_FJVL getdown-launcher diff --git a/getdown/src/getdown/mvn_cmd b/getdown/src/getdown/mvn_cmd index 52b4b40..50e69d6 100755 --- a/getdown/src/getdown/mvn_cmd +++ b/getdown/src/getdown/mvn_cmd @@ -3,7 +3,7 @@ if [ x$JVLVERSION != x ]; then export VERSION=$JVLVERSION else - export VERSION=1.8.3-1.4.0_JVL + export VERSION=1.8.3-1.4.1_JVL fi if [ x${VERSION%_JVL} = x$VERSION ]; then diff --git a/getdown/src/getdown/pom.xml b/getdown/src/getdown/pom.xml index c3c6fc3..4d7b0ec 100644 --- a/getdown/src/getdown/pom.xml +++ b/getdown/src/getdown/pom.xml @@ -10,7 +10,7 @@ com.threerings.getdown getdown pom - 1.8.3-1.4.0_FJVL + 1.8.3-1.4.1_FJVL getdown An application installer and updater. diff --git a/j11lib/getdown-core.jar b/j11lib/getdown-core.jar index 7be6374..7cb005e 100644 Binary files a/j11lib/getdown-core.jar and b/j11lib/getdown-core.jar differ diff --git a/j8lib/getdown-core.jar b/j8lib/getdown-core.jar index 7be6374..7cb005e 100644 Binary files a/j8lib/getdown-core.jar and b/j8lib/getdown-core.jar differ diff --git a/src/jalview/util/LaunchUtils.java b/src/jalview/util/LaunchUtils.java index 0b18c6c..dc8961f 100644 --- a/src/jalview/util/LaunchUtils.java +++ b/src/jalview/util/LaunchUtils.java @@ -37,6 +37,9 @@ import java.util.Locale; import java.util.Properties; import java.util.Set; import java.util.concurrent.TimeUnit; +import java.util.jar.Attributes; +import java.util.jar.JarInputStream; +import java.util.jar.Manifest; public class LaunchUtils { @@ -672,6 +675,137 @@ public class LaunchUtils } */ + /** + * Look for Implementation-Version in two jar manifests and compare according + * to the getdown-launcher version spec (1.8.3-1.4.0_JVL or _FJVL) returns -1 + * if f0 is newer (or more "valid"), +1 if f1 is newer (or more "valid"), 0 if + * the same or both equally "invalid" + * + * @param f0 + * @param f1 + * @return int + */ + public static int compareGetdownLauncherJarVersions(File f0, File f1) + { + if (!f0.exists() && !f1.exists()) + { + return 0; + } + if (!f0.exists()) + { + return 1; + } + if (!f1.exists()) + { + return -1; + } + String v0 = getJarImplementationVersion(f0); + String v1 = getJarImplementationVersion(f1); + syserr(true, false, + "Got launcher versions '" + v0 + "' and '" + v1 + "'"); + if (v0 == null && v1 == null) + { + return 0; + } + if (v0 == null) + { + return 1; + } + if (v1 == null) + { + return -1; + } + // now for the fun + if (v0.endsWith("JVL")) + { + v0 = v0.substring(0, v0.lastIndexOf('_')); + } + if (v1.endsWith("JVL")) + { + v1 = v1.substring(0, v1.lastIndexOf('_')); + } + + String[] v0parts = v0.split("-"); + String[] v1parts = v1.split("-"); + + int compare = 0; + for (int j = 0; j < Math.min(v0parts.length, v1parts.length); j++) + { + compare = 0; + try + { + compare = compareVersions(v0parts[j], v1parts[j]); + } catch (NumberFormatException e) + { + syserr(true, false, + "Problem parsing one of the getdown launcher version numbers: '" + + v0 + "', '" + v1 + "'"); + } + + if (compare != 0 + || (v0parts.length == j + 1 && v1parts.length == j + 1)) + { + return compare; + } + } + + return v1parts.length - v0parts.length; + } + + // just comparing 1.2.3.4...n + public static int compareVersions(String v0, String v1) + throws NumberFormatException + { + if (v0 == null && v1 == null) + { + return 0; + } + if (v0 == null) + { + return 1; + } + if (v1 == null) + { + return -1; + } + String[] v0dots = v0.split("\\."); + String[] v1dots = v1.split("\\."); + for (int i = 0; i < Math.min(v0dots.length, v1dots.length); i++) + { + if (!v0dots[i].equals(v1dots[i])) + { + return Integer.parseInt(v1dots[i]) - Integer.parseInt(v0dots[i]); + } + } + // all numbers match up to min length. If one has more dots, assume it's + // bigger. + return v1dots.length - v0dots.length; + } + + public static String getJarImplementationVersion(File jarFile) + { + String implementationVersion = null; + try + { + JarInputStream j0 = new JarInputStream(new FileInputStream(jarFile)); + Manifest m0 = j0.getManifest(); + if (m0 == null) + { + System.err.println("No manifest in " + jarFile.getAbsolutePath()); + } + else + { + implementationVersion = m0.getMainAttributes() + .getValue(Attributes.Name.IMPLEMENTATION_VERSION); + } + } catch (IOException e) + { + System.err.println("Exception opening " + jarFile.getAbsolutePath() + + " to check version: " + e.getMessage()); + } + return implementationVersion; + } + public static void syserr(boolean debug, boolean quiet, String message) { if (debug && !quiet)