X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fbin%2FCache.java;h=8051336f4a09100dd8872cc43bda158c9ddc87bd;hb=419898b96abeb2f9cdc77b22b34d71fff5451fd9;hp=35d6aa381ff2e2e2fb783e37f77f5fb3acb60af5;hpb=510131abf452a7389d0d40afa323d0bec8bb9f0d;p=jalview.git diff --git a/src/jalview/bin/Cache.java b/src/jalview/bin/Cache.java index 35d6aa3..8051336 100755 --- a/src/jalview/bin/Cache.java +++ b/src/jalview/bin/Cache.java @@ -20,16 +20,6 @@ */ package jalview.bin; -import jalview.datamodel.PDBEntry; -import jalview.gui.UserDefinedColours; -import jalview.schemes.ColourSchemeLoader; -import jalview.schemes.ColourSchemes; -import jalview.schemes.UserColourScheme; -import jalview.structure.StructureImportSettings; -import jalview.urls.IdOrgSettings; -import jalview.util.ColorUtils; -import jalview.ws.sifts.SiftsSettings; - import java.awt.Color; import java.io.BufferedReader; import java.io.File; @@ -37,6 +27,11 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.net.Authenticator; +import java.net.PasswordAuthentication; +import java.net.URL; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Collections; @@ -46,12 +41,30 @@ import java.util.Locale; import java.util.Properties; import java.util.StringTokenizer; import java.util.TreeSet; +import java.util.regex.Pattern; + +import javax.swing.LookAndFeel; +import javax.swing.UIManager; import org.apache.log4j.ConsoleAppender; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.apache.log4j.SimpleLayout; +import jalview.datamodel.PDBEntry; +import jalview.gui.Preferences; +import jalview.gui.UserDefinedColours; +import jalview.jbgui.GPreferences; +import jalview.schemes.ColourSchemeLoader; +import jalview.schemes.ColourSchemes; +import jalview.schemes.UserColourScheme; +import jalview.structure.StructureImportSettings; +import jalview.urls.IdOrgSettings; +import jalview.util.ColorUtils; +import jalview.util.MessageManager; +import jalview.util.Platform; +import jalview.ws.sifts.SiftsSettings; + /** * Stores and retrieves Jalview Application Properties Lists and fields within * list entries are separated by '|' symbols unless otherwise stated (|) clauses @@ -263,6 +276,28 @@ public class Cache */ public static Logger log; + // save the proxy properties set at startup + public final static String[] startupProxyProperties = { + System.getProperty("http.proxyHost"), + System.getProperty("http.proxyPort"), + System.getProperty("https.proxyHost"), + System.getProperty("https.proxyPort"), + System.getProperty("http.proxyUser"), + System.getProperty("http.proxyPassword"), + System.getProperty("https.proxyUser"), + System.getProperty("https.proxyPassword"), + System.getProperty("http.nonProxyHosts") }; + + public final static String PROXYTYPE_NONE = "none"; + + // "false" and "true" for backward compatibility + public final static String PROXYTYPE_SYSTEM = "false"; + + public final static String PROXYTYPE_CUSTOM = "true"; + + // in-memory only storage of proxy password, safer to use char array + public static char[] proxyAuthPassword = null; + /** Jalview Properties */ public static Properties applicationProperties = new Properties() { @@ -277,7 +312,9 @@ public class Cache /** Default file is ~/.jalview_properties */ static String propertiesFile; - private static boolean propsAreReadOnly = false; + private static boolean propsAreReadOnly = Platform.isJS(); + + private final static String JS_PROPERTY_PREFIX = "jalview_"; public static void initLogger() { @@ -309,6 +346,10 @@ public class Cache // lcastor = Logger.getLogger("org.exolab.castor.xml.Marshaller"); // lcastor.setLevel(Level.toLevel(Cache.getDefault("logs.Castor.Level", // Level.INFO.toString()))); + // we shouldn't need to do this + org.apache.log4j.Logger.getRootLogger() + .setLevel(org.apache.log4j.Level.INFO); + jalview.bin.Cache.log.setLevel(Level.toLevel(Cache .getDefault("logs.Jalview.level", Level.INFO.toString()))); // laxis.addAppender(ap); @@ -330,7 +371,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"; @@ -341,65 +382,103 @@ 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 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); } + /* TO BE REPLACED WITH PROXY_TYPE SETTINGS if (getDefault("USE_PROXY", false)) { String proxyServer = getDefault("PROXY_SERVER", ""), proxyPort = getDefault("PROXY_PORT", "8080"); + } + */ - System.out.println("Using proxyServer: " + proxyServer - + " proxyPort: " + proxyPort); - - System.setProperty("http.proxyHost", proxyServer); - System.setProperty("http.proxyPort", proxyPort); + // PROXY TYPE settings (now three options "none", "false", "true", but using + // backward compatible strings) + String proxyType = getDefault("USE_PROXY", PROXYTYPE_SYSTEM); + // default to upgrading old settings + switch (proxyType) + { + case PROXYTYPE_NONE: + clearProxyProperties(); + break; + case PROXYTYPE_SYSTEM: // use system settings + resetProxyProperties(); + break; + case PROXYTYPE_CUSTOM: // use specified proxy settings + String httpHost = getDefault("PROXY_SERVER", ""); + String httpPort = getDefault("PROXY_PORT", "8080"); + String httpsHost = getDefault("PROXY_SERVER_HTTPS", httpHost); + String httpsPort = getDefault("PROXY_PORT_HTTPS", httpPort); + String httpUser = getDefault("PROXY_AUTH_USER", null); + // https.proxyUser and https.proxyPassword are not able to be + // independently set in Preferences yet (or http.nonProxyHosts) + String httpsUser = getDefault("PROXY_AUTH_USER_HTTPS", httpUser); + setProxyProperties(httpHost, httpPort, httpsHost, httpsPort, httpUser, + proxyAuthPassword, httpsUser, proxyAuthPassword, "localhost"); + break; + default: + String message = "Incorrect PROXY_TYPE - should be 'none' (clear proxy properties), 'false' (system settings), 'true' (custom settings): " + + proxyType; + Cache.warn(message); } // LOAD THE AUTHORS FROM THE authors.props file + String authorDetails = resolveResourceURLFor("/authors.props"); + try { - String authorDetails = "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); + authorDetails = null; + } + if (authorDetails == null) + { applicationProperties.remove("AUTHORS"); applicationProperties.remove("AUTHORFNAMES"); applicationProperties.remove("YEAR"); @@ -435,8 +514,8 @@ public class Cache String jnlpVersion = System.getProperty("jalview.version"); - // jnlpVersion will be null if a latest version check for the channel needs to - // be done + // 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) @@ -510,26 +589,53 @@ public class Cache } // 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 printV = codeInstallation == null; + boolean printVersion = codeInstallation == null; - // FIND THE VERSION NUMBER AND BUILD DATE FROM jalview.jar + /* + * read build properties - from the Jalview jar for a Java distribution, + * or from codebase file in test or JalviewJS context + */ try { - String buildDetails = "jar:".concat(Cache.class.getProtectionDomain() - .getCodeSource().getLocation().toString() - .concat("!/.build_properties")); - - java.net.URL localJarFileURL = new java.net.URL(buildDetails); - + String buildDetails = resolveResourceURLFor("/.build_properties"); + URL localJarFileURL = new URL(buildDetails); InputStream in = localJarFileURL.openStream(); applicationProperties.load(in); in.close(); @@ -553,10 +659,10 @@ public class Cache } setProperty("VERSION", codeVersion); new BuildDetails(codeVersion, null, codeInstallation); - if (printV && reportVersion) + if (printVersion && reportVersion) { - System.out - .println("Jalview Version: " + codeVersion + codeInstallation); + System.out.println( + "Jalview Version: " + codeVersion + codeInstallation); } } @@ -582,7 +688,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; } /** @@ -620,18 +732,13 @@ public class Cache } /** - * These methods are used when checking if the saved preference is different - * to the default setting + * 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 string = getProperty(property); - if (string != null) - { - return string; - } - - return def; + String value = getProperty(property); + return value == null ? def : value; } /** @@ -1099,16 +1206,23 @@ public class Cache public static String getVersionDetailsForConsole() { StringBuilder sb = new StringBuilder(); - sb.append("Jalview Version: " + jalview.bin.Cache.getDefault("VERSION", "TEST")); + sb.append("Jalview Version: "); + sb.append(jalview.bin.Cache.getDefault("VERSION", "TEST")); sb.append("\n"); - sb.append("Jalview Installation: " - + jalview.bin.Cache.getDefault("INSTALLATION", "unknown")); + sb.append("Jalview Installation: "); + sb.append(jalview.bin.Cache.getDefault("INSTALLATION", "unknown")); sb.append("\n"); - sb.append("Build Date: " + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")); + sb.append("Build Date: "); + sb.append(jalview.bin.Cache.getDefault("BUILD_DATE", "unknown")); sb.append("\n"); - sb.append("Java version: " + System.getProperty("java.version")); + sb.append("Java version: "); + sb.append(System.getProperty("java.version")); sb.append("\n"); - sb.append(System.getProperty("os.arch") + " " + System.getProperty("os.name") + " " + System.getProperty("os.version")); + sb.append(System.getProperty("os.arch")); + sb.append(" "); + sb.append(System.getProperty("os.name")); + sb.append(" "); + sb.append(System.getProperty("os.version")); sb.append("\n"); appendIfNotNull(sb, "Install4j version: ", System.getProperty("sys.install4jVersion"), "\n", null); @@ -1116,7 +1230,19 @@ public class Cache 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")) { + LookAndFeel laf = UIManager.getLookAndFeel(); + String lafName = laf == null ? "Not obtained" : laf.getName(); + String lafClass = laf == null ? "unknown" : laf.getClass().getName(); + sb.append("LookAndFeel: "); + sb.append(lafName); + sb.append(" ("); + sb.append(lafClass); + sb.append(")\n"); + // Not displayed in release version ( determined by possible version number + // regex 9[9.]*9[.-_a9]* ) + if (Pattern.matches("^\\d[\\d\\.]*\\d[\\.\\-\\w]*$", + jalview.bin.Cache.getDefault("VERSION", "TEST"))) + { appendIfNotNull(sb, "Getdown appdir: ", System.getProperty("getdownappdir"), "\n", null); appendIfNotNull(sb, "Java home: ", System.getProperty("java.home"), @@ -1135,4 +1261,231 @@ public class Cache // eg 'built from Source' or update channel return jalview.bin.Cache.getDefault("INSTALLATION", "unknown"); } + + public static String getStackTraceString(Throwable t) + { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + t.printStackTrace(pw); + return sw.toString(); + } + + // proxy properties methods + public static void clearProxyProperties() + { + setProxyProperties(null, null, null, null, null, null, null, null, + null); + } + + public static void resetProxyProperties() + { + setProxyProperties(startupProxyProperties[0], startupProxyProperties[1], + startupProxyProperties[2], startupProxyProperties[3], + startupProxyProperties[4], + startupProxyProperties[5] == null ? null + : startupProxyProperties[5].toCharArray(), + startupProxyProperties[6], + startupProxyProperties[7] == null ? null + : startupProxyProperties[7].toCharArray(), + startupProxyProperties[8]); + StringBuilder sb = new StringBuilder(); + sb.append("Setting proxy properties to: http.proxyHost=") + .append(startupProxyProperties[0]).append(", http.proxyPort=") + .append(startupProxyProperties[1]) + .append(startupProxyProperties[4] != null + && !startupProxyProperties[4].isEmpty() + ? " [" + startupProxyProperties[4] + "]" + : "") + .append(", https.proxyHost=").append(startupProxyProperties[2]) + .append(", https.proxyPort=").append(startupProxyProperties[3]) + .append(startupProxyProperties[6] != null + && !startupProxyProperties[6].isEmpty() + ? " [" + startupProxyProperties[6] + "]" + : ""); + + Cache.debug(sb.toString()); + } + + public static void setProxyProperties(String httpHost, String httpPort, + String httpsHost, String httpsPort, String httpUser, + char[] httpPassword, String httpsUser, char[] httpsPassword, + String nonProxyHosts) + { + setOrClearSystemProperty("http.proxyHost", httpHost); + setOrClearSystemProperty("http.proxyPort", httpPort); + setOrClearSystemProperty("https.proxyHost", httpsHost); + setOrClearSystemProperty("https.proxyPort", httpsPort); + setOrClearSystemProperty("http.proxyUser", httpUser); + setOrClearSystemProperty("http.proxyPassword", httpPassword); + setOrClearSystemProperty("https.proxyUser", httpsUser); + setOrClearSystemProperty("https.proxyPassword", httpsPassword); + // are we using a custom proxy (password prompt might be required)? + boolean customProxySet = getDefault("USE_PROXY", PROXYTYPE_SYSTEM) + .equals(PROXYTYPE_CUSTOM); + if (httpUser != null || httpsUser != null) + { + try + { + Authenticator.setDefault(new Authenticator() + { + @Override + protected PasswordAuthentication getPasswordAuthentication() + { + if (getRequestorType() == RequestorType.PROXY) + { + String scheme = getRequestingScheme(); + boolean needProxyPasswordSet = false; + if (customProxySet && + // we have a username but no password for the scheme being + // requested + (scheme.equalsIgnoreCase("http") + && (httpUser != null && httpUser.length() > 0 + && (httpPassword == null + || httpPassword.length == 0))) + || (scheme.equalsIgnoreCase("https") + && (httpsUser != null + && httpsUser.length() > 0 + && (httpsPassword == null + || httpsPassword.length == 0)))) + { + // open Preferences -> Connections + String message = MessageManager + .getString("label.proxy_password_required"); + openPreferencesConnectionsForProxyPassword(message); + } + else + { + try + { + if (scheme.equalsIgnoreCase("http") + && getRequestingHost().equalsIgnoreCase(httpHost) + && getRequestingPort() == Integer + .valueOf(httpPort)) + { + return new PasswordAuthentication(httpUser, + httpPassword); + } + if (scheme.equalsIgnoreCase("https") + && getRequestingHost().equalsIgnoreCase(httpsHost) + && getRequestingPort() == Integer + .valueOf(httpsPort)) + { + return new PasswordAuthentication(httpsUser, + httpsPassword); + } + } catch (NumberFormatException e) + { + Cache.error("Problem with proxy port values [http:" + + httpPort + ", https:" + httpsPort + "]"); + } + } + } + // non proxy request + return null; + } + }); + // required to re-enable basic authentication (should be okay for a + // local proxy) + System.setProperty("jdk.http.auth.tunneling.disabledSchemes", ""); + } catch (SecurityException e) + { + Cache.error("Could not set default Authenticator"); + Cache.debug(getStackTraceString(e)); + } + } + else + { + // reset the Authenticator to protect http.proxyUser and + // http.proxyPassword Just In Case + Authenticator.setDefault(null); + } + + // nonProxyHosts not currently configurable in Preferences + setOrClearSystemProperty("http.nonProxyHosts", nonProxyHosts); + } + + private static void openPreferencesConnectionsForProxyPassword( + String message) + { + // + Cache.info("Opening Preferences for proxy password"); + // Desktop.instance.preferences_actionPerformed(null); + Preferences p = new Preferences(GPreferences.CONNECTIONS_TAB); + p.grabFocus(); + } + + public static void setOrClearSystemProperty(String key, char[] value) + { + setOrClearSystemProperty(key, + (value == null) ? null : value.toString()); + } + + public static void setOrClearSystemProperty(String key, String value) + { + if (key == null) + { + return; + } + if (value == null) + { + System.clearProperty(key); + } + else + { + System.setProperty(key, value); + } + } + + public final static int DEBUG = 10; + + public final static int INFO = 20; + + public final static int WARN = 30; + + public final static int ERROR = 40; + + public static boolean println(int level, String message) + { + if (Cache.log == null) + { + if (level >= ERROR) + System.err.println(message); + else + System.out.println(message); + return false; + } + if (level >= WARN) + { + Cache.log.warn(message); + } + else if (level >= INFO) + { + Cache.log.info(message); + } + else + { + Cache.log.debug(message); + } + return true; + } + + public static void debug(String message) + { + println(DEBUG, message); + } + + public static void info(String message) + { + println(INFO, message); + } + + public static void warn(String message) + { + println(WARN, message); + } + + public static void error(String message) + { + println(ERROR, message); + } }