Merge branch 'develop' into Jalview-JS/develop
[jalview.git] / src / jalview / bin / Cache.java
index 1f031b2..788cb02 100755 (executable)
@@ -28,6 +28,7 @@ import jalview.schemes.UserColourScheme;
 import jalview.structure.StructureImportSettings;
 import jalview.urls.IdOrgSettings;
 import jalview.util.ColorUtils;
+import jalview.util.Platform;
 import jalview.ws.sifts.SiftsSettings;
 
 import java.awt.Color;
@@ -37,6 +38,7 @@ import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.InputStream;
 import java.io.InputStreamReader;
+import java.net.URL;
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.util.Collections;
@@ -114,7 +116,6 @@ import org.apache.log4j.SimpleLayout;
  * service</li>
  * <li>USAGESTATS (false - user prompted) Enable google analytics tracker for
  * collecting usage statistics</li>
- * <li>DAS_LOCAL_SOURCE list of local das sources</li>
  * <li>SHOW_OVERVIEW boolean for overview window display</li>
  * <li>ANTI_ALIAS boolean for smooth fonts</li>
  * <li>RIGHT_ALIGN_IDS boolean</li>
@@ -134,9 +135,7 @@ import org.apache.log4j.SimpleLayout;
  * sequence id (must be in SEQUENCE_LINKS or STORED_LINKS)
  * <li>GROUP_LINKS list of name|URL[|&lt;separator&gt;] tuples - see
  * jalview.utils.GroupURLLink for more info</li>
- * <li>DAS_REGISTRY_URL the registry to query</li>
  * <li>DEFAULT_BROWSER for unix</li>
- * <li>DAS_ACTIVE_SOURCE list of active sources</li>
  * <li>SHOW_MEMUSAGE boolean show memory usage and warning indicator on desktop
  * (false)</li>
  * <li>VERSION_CHECK (true) check for the latest release version from
@@ -226,12 +225,6 @@ public class Cache
    */
   public static final String JALVIEWLOGLEVEL = "logs.Jalview.level";
 
-  public static final String DAS_LOCAL_SOURCE = "DAS_LOCAL_SOURCE";
-
-  public static final String DAS_REGISTRY_URL = "DAS_REGISTRY_URL";
-
-  public static final String DAS_ACTIVE_SOURCE = "DAS_ACTIVE_SOURCE";
-
   /**
    * Sifts settings
    */
@@ -286,8 +279,9 @@ public class Cache
   /** Default file is ~/.jalview_properties */
   static String propertiesFile;
 
-  private static boolean propsAreReadOnly = /** @j2sNative true || */
-          false;
+  private static boolean propsAreReadOnly = Platform.isJS();
+
+  private final static String JS_PROPERTY_PREFIX = "jalview_";
 
   public static void initLogger()
   {
@@ -340,7 +334,7 @@ public class Cache
   public static void loadProperties(String propsFile)
   {
     propertiesFile = propsFile;
-    if (propsFile == null)
+    if (propsFile == null && !propsAreReadOnly)
     {
       propertiesFile = System.getProperty("user.home") + File.separatorChar
               + ".jalview_properties";
@@ -351,38 +345,45 @@ public class Cache
       propsAreReadOnly = true;
     }
 
-    try
+    if (propertiesFile == null)
+    { // BH 2019
+      Platform.readInfoProperties(JS_PROPERTY_PREFIX,
+              applicationProperties);
+    }
+    else
     {
-      InputStream fis;
       try
       {
-        fis = new java.net.URL(propertiesFile).openStream();
-        System.out.println(
-                "Loading jalview properties from : " + propertiesFile);
-        System.out.println(
-                "Disabling Jalview writing to user's local properties file.");
-        propsAreReadOnly = true;
+        InputStream fis;
+        try
+        {
+          fis = new java.net.URL(propertiesFile).openStream();
+          System.out.println(
+                  "Loading jalview properties from : " + propertiesFile);
+          System.out.println(
+                  "Disabling Jalview writing to user's local properties file.");
+          propsAreReadOnly = true;
+
+        } catch (Exception ex)
+        {
+          fis = null;
+        }
+        if (fis == null)
+        {
+          fis = new FileInputStream(propertiesFile);
+        }
+        applicationProperties.clear();
+        applicationProperties.load(fis);
 
+        // remove any old build properties
+
+        deleteBuildProperties();
+        fis.close();
       } catch (Exception ex)
       {
-        fis = null;
-      }
-      if (fis == null)
-      {
-        fis = new FileInputStream(propertiesFile);
+        System.out.println("Error reading properties file: " + ex);
       }
-      applicationProperties.clear();
-      applicationProperties.load(fis);
-
-      // remove any old build properties
-
-      deleteBuildProperties();
-      fis.close();
-    } catch (Exception ex)
-    {
-      System.out.println("Error reading properties file: " + ex);
     }
-
     if (getDefault("USE_PROXY", false))
     {
       String proxyServer = getDefault("PROXY_SERVER", ""),
@@ -396,62 +397,30 @@ public class Cache
     }
 
     // LOAD THE AUTHORS FROM THE authors.props file
+    String authorDetails = resolveResourceURLFor("/authors.props");
+
     try
     {
-      String authorDetails = /** @j2sNative "xxx" || */
-              "jar:"
-              .concat(Cache.class.getProtectionDomain().getCodeSource()
-                      .getLocation().toString().concat("!/authors.props"));
-
-      java.net.URL localJarFileURL = new java.net.URL(authorDetails);
-
-      InputStream in = localJarFileURL.openStream();
-      applicationProperties.load(in);
-      in.close();
+      if (authorDetails != null)
+      {
+        URL localJarFileURL = new URL(authorDetails);
+        InputStream in = localJarFileURL.openStream();
+        applicationProperties.load(in);
+        in.close();
+      }
     } catch (Exception ex)
     {
       System.out.println("Error reading author details: " + ex);
-      applicationProperties.remove("AUTHORS");
-      applicationProperties.remove("AUTHORFNAMES");
-      applicationProperties.remove("YEAR");
+      authorDetails = null;
     }
-
-    // FIND THE VERSION NUMBER AND BUILD DATE FROM jalview.jar
-    // MUST FOLLOW READING OF LOCAL PROPERTIES FILE AS THE
-    // VERSION MAY HAVE CHANGED SINCE LAST USING JALVIEW
-    try
+    if (authorDetails == null)
     {
-      String buildDetails = /** @j2sNative "xxx" || */
-              "jar:".concat(Cache.class.getProtectionDomain()
-              .getCodeSource().getLocation().toString()
-              .concat("!/.build_properties"));
-
-      java.net.URL localJarFileURL = new java.net.URL(buildDetails);
-
-      InputStream in = localJarFileURL.openStream();
-      applicationProperties.load(in);
-      in.close();
-    } catch (Exception ex)
-    {
-      System.out.println("Error reading build details: " + ex);
-      applicationProperties.remove("VERSION");
+        applicationProperties.remove("AUTHORS");
+        applicationProperties.remove("AUTHORFNAMES");
+        applicationProperties.remove("YEAR");
     }
 
-    String jnlpVersion = System.getProperty("jalview.version");
-    String codeVersion = getProperty("VERSION");
-    String codeInstallation = getProperty("INSTALLATION");
-    if (codeVersion == null)
-    {
-      // THIS SHOULD ONLY BE THE CASE WHEN TESTING!!
-      codeVersion = "Test";
-      jnlpVersion = "Test";
-      codeInstallation = "";
-    }
-    else
-    {
-      codeInstallation = " (" + codeInstallation + ")";
-    }
-    new BuildDetails(codeVersion, null, codeInstallation);
+    loadBuildProperties(false);
 
     SiftsSettings
             .setMapWithSifts(Cache.getDefault("MAP_WITH_SIFTS", false));
@@ -471,9 +440,6 @@ public class Cache
             "http://www.jalview.org/services/identifiers"));
     IdOrgSettings.setDownloadLocation(ID_ORG_FILE);
 
-    System.out
-            .println("Jalview Version: " + codeVersion + codeInstallation);
-
     StructureImportSettings.setDefaultStructureFileFormat(jalview.bin.Cache
             .getDefault("PDB_DOWNLOAD_FORMAT", PDB_DOWNLOAD_FORMAT));
     StructureImportSettings
@@ -481,14 +447,18 @@ public class Cache
     // StructureImportSettings
     // .setDefaultPDBFileParser(jalview.bin.Cache.getDefault(
     // "DEFAULT_PDB_FILE_PARSER", DEFAULT_PDB_FILE_PARSER));
-    // jnlpVersion will be null if we're using InstallAnywhere
+
+    String jnlpVersion = System.getProperty("jalview.version");
+
+    // jnlpVersion will be null if a latest version check for the channel needs to
+    // be done
     // Dont do this check if running in headless mode
+
     if (jnlpVersion == null && getDefault("VERSION_CHECK", true)
             && (System.getProperty("java.awt.headless") == null || System
                     .getProperty("java.awt.headless").equals("false")))
     {
-
-      class VersionChecker extends Thread
+      new Thread()
       {
         @Override
         public void run()
@@ -536,10 +506,7 @@ public class Cache
 
           setProperty("LATEST_VERSION", remoteVersion);
         }
-      }
-
-      VersionChecker vc = new VersionChecker();
-      vc.start();
+      }.start();
     }
     else
     {
@@ -553,15 +520,84 @@ public class Cache
       }
     }
 
-    setProperty("VERSION", codeVersion);
-
     // LOAD USERDEFINED COLOURS
-    jalview.bin.Cache
-            .initUserColourSchemes(getProperty("USER_DEFINED_COLOURS"));
+    Cache.initUserColourSchemes(getProperty("USER_DEFINED_COLOURS"));
     jalview.io.PIRFile.useModellerOutput = Cache.getDefault("PIR_MODELLER",
             false);
   }
 
+  /**
+   * construct a resource URL for the given absolute resource pathname
+   * 
+   * @param resourcePath
+   * @return
+   */
+  private static String resolveResourceURLFor(String resourcePath)
+  {
+    String url = null;
+    if (Platform.isJS() || !Cache.class.getProtectionDomain()
+            .getCodeSource().getLocation().toString().endsWith(".jar"))
+    {
+      try
+      {
+        url = Cache.class.getResource(resourcePath).toString();
+      } catch (Exception ex)
+      {
+        System.err.println("Failed to resolve resource " + resourcePath + ": "
+                + ex.getMessage());
+      }
+    }
+    else
+    {
+      url = "jar:".concat(Cache.class.getProtectionDomain().getCodeSource()
+              .getLocation().toString().concat("!" + resourcePath));
+    }
+    return url;
+  }
+
+  public static void loadBuildProperties(boolean reportVersion)
+  {
+    String codeInstallation = getProperty("INSTALLATION");
+    boolean printVersion = codeInstallation == null;
+
+    /*
+     * read build properties - from the Jalview jar for a Java distribution,
+     * or from codebase file in test or JalviewJS context
+     */
+    try
+    {
+      String buildDetails = resolveResourceURLFor("/.build_properties");
+      URL localJarFileURL = new URL(buildDetails);
+      InputStream in = localJarFileURL.openStream();
+      applicationProperties.load(in);
+      in.close();
+    } catch (Exception ex)
+    {
+      System.out.println("Error reading build details: " + ex);
+      applicationProperties.remove("VERSION");
+    }
+    String codeVersion = getProperty("VERSION");
+    codeInstallation = getProperty("INSTALLATION");
+
+    if (codeVersion == null)
+    {
+      // THIS SHOULD ONLY BE THE CASE WHEN TESTING!!
+      codeVersion = "Test";
+      codeInstallation = "";
+    }
+    else
+    {
+      codeInstallation = " (" + codeInstallation + ")";
+    }
+    setProperty("VERSION", codeVersion);
+    new BuildDetails(codeVersion, null, codeInstallation);
+    if (printVersion && reportVersion)
+    {
+      System.out
+            .println("Jalview Version: " + codeVersion + codeInstallation);
+    }
+  }
+
   private static void deleteBuildProperties()
   {
     applicationProperties.remove("LATEST_VERSION");
@@ -584,7 +620,13 @@ public class Cache
    */
   public static String getProperty(String key)
   {
-    return applicationProperties.getProperty(key);
+    String prop = applicationProperties.getProperty(key);
+    if (prop == null && Platform.isJS())
+    {
+      prop = applicationProperties.getProperty(Platform.getUniqueAppletID()
+              + "_" + JS_PROPERTY_PREFIX + key);
+    }
+    return prop;
   }
 
   /**
@@ -603,22 +645,35 @@ public class Cache
     return def;
   }
 
-  /**
-   * These methods are used when checking if the saved preference is different
-   * to the default setting
-   */
-  public static String getDefault(String property, String def)
+  public static int getDefault(String property, int def)
   {
     String string = getProperty(property);
     if (string != null)
     {
-      return string;
+      try
+      {
+        def = Integer.parseInt(string);
+      } catch (NumberFormatException e)
+      {
+        System.out.println("Error parsing int property '" + property
+                + "' with value '" + string + "'");
+      }
     }
 
     return def;
   }
 
   /**
+   * Answers the value of the given property, or the supplied default value if
+   * the property is not set
+   */
+  public static String getDefault(String property, String def)
+  {
+    String value = getProperty(property);
+    return value == null ? def : value;
+  }
+
+  /**
    * Stores property in the file "HOME_DIR/.jalview_properties"
    * 
    * @param key
@@ -634,7 +689,7 @@ public class Cache
     try
     {
       oldValue = applicationProperties.setProperty(key, obj);
-      if (!propsAreReadOnly)
+      if (propertiesFile != null && !propsAreReadOnly)
       {
         FileOutputStream out = new FileOutputStream(propertiesFile);
         applicationProperties.store(out, "---JalviewX Properties File---");
@@ -1057,4 +1112,66 @@ public class Cache
       }
     }
   }
+
+  /**
+   * Initial logging information helper for various versions output
+   * 
+   * @param prefix
+   * @param value
+   * @param defaultValue
+   */
+  private static void appendIfNotNull(StringBuilder sb, String prefix,
+          String value, String suffix, String defaultValue)
+  {
+    if (value == null && defaultValue == null)
+    {
+      return;
+    }
+    String line = prefix + (value != null ? value : defaultValue) + suffix;
+    sb.append(line);
+  }
+
+  /**
+   * 
+   * @return Jalview version, build details and JVM platform version for console
+   */
+  public static String getVersionDetailsForConsole()
+  {
+    StringBuilder sb = new StringBuilder();
+    sb.append("Jalview Version: " + jalview.bin.Cache.getDefault("VERSION", "TEST"));
+    sb.append("\n");
+    sb.append("Jalview Installation: "
+            + jalview.bin.Cache.getDefault("INSTALLATION", "unknown"));
+    sb.append("\n");
+    sb.append("Build Date: " + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
+    sb.append("\n");
+    sb.append("Java version: " + System.getProperty("java.version"));
+    sb.append("\n");
+    sb.append(System.getProperty("os.arch") + " " + System.getProperty("os.name") + " " + System.getProperty("os.version"));
+    sb.append("\n");
+    appendIfNotNull(sb, "Install4j version: ",
+            System.getProperty("sys.install4jVersion"), "\n", null);
+    appendIfNotNull(sb, "Install4j template version: ",
+            System.getProperty("installer_template_version"), "\n", null);
+    appendIfNotNull(sb, "Launcher version: ",
+            System.getProperty("launcher_version"), "\n", null);
+    if (jalview.bin.Cache.getDefault("VERSION", "TEST").equals("DEVELOPMENT")) {
+      appendIfNotNull(sb, "Getdown appdir: ",
+              System.getProperty("getdownappdir"), "\n", null);
+      appendIfNotNull(sb, "Java home: ", System.getProperty("java.home"),
+              "\n", "unknown");
+    }
+    return sb.toString();
+  }
+
+  /**
+   * 
+   * @return build details as reported in splashscreen
+   */
+  public static String getBuildDetailsForSplash()
+  {
+    // consider returning more human friendly info
+    // eg 'built from Source' or update channel
+    return jalview.bin.Cache.getDefault("INSTALLATION", "unknown");
+  }
 }