JAL-3631 Check Implementation-Version of getdown-launcher.jar in installation appdir...
authorBen Soares <b.soares@dundee.ac.uk>
Mon, 24 Jun 2024 23:23:00 +0000 (00:23 +0100)
committerBen Soares <b.soares@dundee.ac.uk>
Mon, 24 Jun 2024 23:23:00 +0000 (00:23 +0100)
16 files changed:
getdown/lib/FJVL_VERSION
getdown/lib/JVL_VERSION
getdown/lib/getdown-core.jar
getdown/lib/getdown-launcher-local.jar
getdown/lib/getdown-launcher.jar
getdown/src/getdown/ant/pom.xml
getdown/src/getdown/core/pom.xml
getdown/src/getdown/core/src/main/java/com/threerings/getdown/data/Application.java
getdown/src/getdown/core/src/main/java/com/threerings/getdown/data/EnvConfig.java
getdown/src/getdown/core/src/main/java/jalview/util/LaunchUtils.java
getdown/src/getdown/launcher/pom.xml
getdown/src/getdown/mvn_cmd
getdown/src/getdown/pom.xml
j11lib/getdown-core.jar
j8lib/getdown-core.jar
src/jalview/util/LaunchUtils.java

index 21df89d..5658c0d 100644 (file)
@@ -1 +1 @@
-1.8.3-1.4.0_FJVL
+1.8.3-1.4.1_FJVL
index 2d02e7a..de777a1 100644 (file)
@@ -1 +1 @@
-1.8.3-1.4.0_JVL
+1.8.3-1.4.1_JVL
index 7be6374..7cb005e 100644 (file)
Binary files a/getdown/lib/getdown-core.jar and b/getdown/lib/getdown-core.jar differ
index dca82cd..cd0824c 100644 (file)
Binary files a/getdown/lib/getdown-launcher-local.jar and b/getdown/lib/getdown-launcher-local.jar differ
index f2f681d..d30f084 100644 (file)
Binary files a/getdown/lib/getdown-launcher.jar and b/getdown/lib/getdown-launcher.jar differ
index ce84058..75ec538 100644 (file)
@@ -4,7 +4,7 @@
   <parent>
     <groupId>com.threerings.getdown</groupId>
     <artifactId>getdown</artifactId>
-    <version>1.8.3-1.4.0_FJVL</version>
+    <version>1.8.3-1.4.1_FJVL</version>
   </parent>
 
   <artifactId>getdown-ant</artifactId>
index c926ab2..4670d8d 100644 (file)
@@ -4,7 +4,7 @@
   <parent>
     <groupId>com.threerings.getdown</groupId>
     <artifactId>getdown</artifactId>
-    <version>1.8.3-1.4.0_FJVL</version>
+    <version>1.8.3-1.4.1_FJVL</version>
   </parent>
 
   <artifactId>getdown-core</artifactId>
index 9429efc..74814c6 100644 (file)
@@ -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();
index 735ce8d..e644565 100644 (file)
@@ -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<String> removeClasspath = new ArrayList<>();
-                removeClasspath.add(installerGetdown.getAbsolutePath());
-                List<String> 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<String> removeArgs = new ArrayList<>();
-                removeArgs.add(argvAppDir);
-                removeArgs.add(argvAppId);
-                List<String> 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<String> removeClasspath = new ArrayList<>();
+              removeClasspath.add(installerGetdown.getAbsolutePath());
+              List<String> 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<String> removeArgs = new ArrayList<>();
+              removeArgs.add(argvAppDir);
+              removeArgs.add(argvAppId);
+              List<String> 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");
index 0b18c6c..dc8961f 100644 (file)
@@ -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)
index 876efd2..13303fa 100644 (file)
@@ -4,7 +4,7 @@
   <parent>
     <groupId>com.threerings.getdown</groupId>
     <artifactId>getdown</artifactId>
-    <version>1.8.3-1.4.0_FJVL</version>
+    <version>1.8.3-1.4.1_FJVL</version>
   </parent>
 
   <artifactId>getdown-launcher</artifactId>
index 52b4b40..50e69d6 100755 (executable)
@@ -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
index c3c6fc3..4d7b0ec 100644 (file)
@@ -10,7 +10,7 @@
   <groupId>com.threerings.getdown</groupId>
   <artifactId>getdown</artifactId>
   <packaging>pom</packaging>
-  <version>1.8.3-1.4.0_FJVL</version>
+  <version>1.8.3-1.4.1_FJVL</version>
 
   <name>getdown</name>
   <description>An application installer and updater.</description>
index 7be6374..7cb005e 100644 (file)
Binary files a/j11lib/getdown-core.jar and b/j11lib/getdown-core.jar differ
index 7be6374..7cb005e 100644 (file)
Binary files a/j8lib/getdown-core.jar and b/j8lib/getdown-core.jar differ
index 0b18c6c..dc8961f 100644 (file)
@@ -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)