import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.Proxy;
+import java.net.URI;
+import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLConnection;
+import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream;
-import com.sun.management.OperatingSystemMXBean;
-import java.lang.management.ManagementFactory;
+import jalview.bin.HiDPISetting;
import jalview.bin.MemorySetting;
+//import com.install4j.api.launcher.Variables;
import com.threerings.getdown.util.*;
// avoid ambiguity with java.util.Base64 which we can't use as it's 1.8+
{
/** The name of our configuration file. */
public static final String CONFIG_FILE = "getdown.txt";
+
+ /** Dir where a backup config file might reside */
+ public static final String BACKUP_CONFIG_DIR = "install";
/** The name of our target version file. */
public static final String VERSION_FILE = "version.txt";
*/
public enum Step
{
- UPDATE_JAVA(10),
+ //UPDATE_JAVA(10),
+ UPDATE_JAVA(20),
//VERIFY_METADATA(15, 65, 95),
VERIFY_METADATA(15, 45, 90),
- DOWNLOAD(50),
+ DOWNLOAD(60),
PATCH(60),
//VERIFY_RESOURCES(70, 97),
- VERIFY_RESOURCES(30, 60),
+ VERIFY_RESOURCES(40, 90),
//REDOWNLOAD_RESOURCES(90),
- REDOWNLOAD_RESOURCES(70),
+ REDOWNLOAD_RESOURCES(80),
//UNPACK(98),
- UNPACK(90),
+ UNPACK(95),
//LAUNCH(99);
LAUNCH(100);
/** Whether progress text should be hidden or not. */
public final boolean hideProgressText;
- /** Whether the splash screen should retain focus. */
+ /** Whether the splash screen should update non-asynchronously before being shown. */
public final boolean progressSync;
+ /** Whether the splash screen should update non-asynchronously after being shown. */
+ public final boolean progressSyncAfterShown;
+
/** Whether the splash screen should retain focus. */
public final boolean keepOnTop;
", pb=" + progressBar + ", srect=" + status + ", st=" + statusText +
", shadow=" + textShadow + ", err=" + installError + ", nrect=" + patchNotes +
", notes=" + patchNotesUrl + ", stepPercentages=" + stepPercentages +
- ", hideProgressText=" + hideProgressText + ", keepOnTop=" + keepOnTop + ", progressSync=" + progressSync + ", minShow=" + minShowSeconds +
+ ", hideProgressText=" + hideProgressText + ", keepOnTop=" + keepOnTop + ", progressSync=" + progressSync +
+ ", progressSyncAfterShown=" + progressSyncAfterShown + ", minShow=" + minShowSeconds +
", displayAppbase=" + displayAppbase + ", displayVersion=" + displayVersion + "]";
}
this.name = config.getString("ui.name");
this.progress = config.getRect("ui.progress", new Rectangle(5, 5, 300, 15));
this.progressText = config.getColor("ui.progress_text", Color.BLACK);
- this.hideProgressText = config.getBoolean("ui.hide_progress_text");
- this.progressSync = config.getBoolean("ui.progress_sync");
+ this.hideProgressText = config.getBoolean("ui.hide_progress_text");
+ this.progressSync = config.getBoolean("ui.progress_sync_before_shown");
+ this.progressSyncAfterShown = config.getBoolean("ui.progress_sync_after_shown");
this.keepOnTop = config.getBoolean("ui.keep_on_top");
this.displayAppbase = config.getBoolean("ui.display_appbase");
this.displayVersion = config.getBoolean("ui.display_version");
*
*/
public Application (EnvConfig envc) {
- _envc = envc;
- _config = getLocalPath(envc.appDir, CONFIG_FILE);
+ _envc = envc;
+ _config = getLocalPath(envc.appDir, CONFIG_FILE);
+ _backupConfig = getLocalPath(envc.appDir, BACKUP_CONFIG_DIR+File.separator+CONFIG_FILE);
}
/**
* Returns the configured application directory.
*/
public File getAppDir () {
- return _envc.appDir;
+ return _envc.appDir;
}
/**
*/
public boolean useCodeCache ()
{
- return _useCodeCache;
+ return _useCodeCache;
}
/**
*/
public int getCodeCacheRetentionDays ()
{
- return _codeCacheRetentionDays;
+ return _codeCacheRetentionDays;
}
/**
* app files from its hosting server.
*/
public int maxConcurrentDownloads () {
- return _maxConcDownloads;
+ return _maxConcDownloads;
}
/**
*/
public Resource getConfigResource ()
{
- try {
- return createResource(CONFIG_FILE, Resource.NORMAL);
- } catch (Exception e) {
- throw new RuntimeException("Invalid appbase '" + _vappbase + "'.", e);
- }
+ try {
+ return createResource(CONFIG_FILE, Resource.NORMAL);
+ } catch (Exception e) {
+ throw new RuntimeException("Invalid appbase '" + _vappbase + "'.", e);
+ }
}
/**
*/
public List<Resource> getCodeResources ()
{
- return _codes;
+ return _codes;
}
/**
public Config init (boolean checkPlatform)
throws IOException
{
+ if (_initialised && _initialisedConfig != null)
+ {
+ return _initialisedConfig;
+ }
+
+ try {
+ Application.i4jVersion = com.install4j.api.launcher.Variables.getCompilerVariable("sys.install4jVersion");
+ } catch (IOException e)
+ {
+ System.err.println("install4j version not available");
+ } catch (NoClassDefFoundError e)
+ {
+ log.warning("Starting without install4j classes");
+ } catch (Throwable t)
+ {
+ System.err.println("install4j not available");
+ t.printStackTrace();
+ }
+
Config config = null;
File cfgfile = _config;
Config.ParseOpts opts = Config.createOpts(checkPlatform);
} catch (Exception e) {
log.warning("Failure reading config file", "file", _config, e);
}
+ if (config == null || config.getString("appbase") == null || config.getString("appbase").isEmpty()) {
+ try {
+ Config backupConfig = Config.parseConfig(_backupConfig, opts);
+ config = backupConfig;
+ log.warning("Using backup config file", "appdir", getAppDir(), "backupConfig", _backupConfig.getAbsoluteFile());
+ } catch (Exception e) {
+ log.warning("Failure reading backup config file", "file", _backupConfig, e);
+ }
+ }
// see if there's an override config from locator file
Config locatorConfig = createLocatorConfig(opts);
addAll(jvmargs, _jvmargs);
}
- // see if a percentage of physical memory option exists
- int jvmmempc = config.getInt("jvmmempc", -1);
+ // see if a percentage of physical memory, or max heap size options exist
+ jvmmempc = config.getString("jvmmempc", null);
+ jvmmemmax = config.getString("jvmmemmax", null);
// app_id prefixed setting overrides
if (appPrefix.length() > 0) {
- jvmmempc = config.getInt(appPrefix + "jvmmempc", jvmmempc);
- }
- if (0 <= jvmmempc && jvmmempc <= 100) {
-
- long maxMemLong = -1;
-
- try
- {
- maxMemLong = MemorySetting.memPercent(jvmmempc);
- } catch (Exception e)
- {
- e.printStackTrace();
- } catch (Throwable t)
- {
- t.printStackTrace();
- }
-
- if (maxMemLong > 0)
- {
-
- String[] maxMemHeapArg = new String[]{"-Xmx"+Long.toString(maxMemLong)};
- // remove other max heap size arg
- ARG: for (int i = 0; i < _jvmargs.size(); i++) {
- if (_jvmargs.get(i) instanceof java.lang.String && _jvmargs.get(i).startsWith("-Xmx")) {
- _jvmargs.remove(i);
- }
- }
- addAll(maxMemHeapArg, _jvmargs);
-
- }
-
- } else if (jvmmempc != -1) {
- System.out.println("'jvmmempc' value must be in range 0 to 100 (read as '"+Integer.toString(jvmmempc)+"')");
+ jvmmempc = config.getString(appPrefix + "jvmmempc", jvmmempc);
+ jvmmemmax = config.getString(appPrefix + "jvmmemmax", jvmmemmax);
}
// get the set of optimum JVM arguments
_dockName = config.getString("ui.name");
_dockIconPath = config.getString("ui.mac_dock_icon", "../desktop.icns");
+ _initialised = true;
+ _initialisedConfig = config;
return config;
}
// add the marker indicating the app is running in getdown
args.add("-D" + Properties.GETDOWN + "=true");
+ args.add("-Dsys.install4jVersion=" + Application.i4jVersion);
+ 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();
+ if (scalePropertyArg != null)
+ {
+ args.add(scalePropertyArg);
+ }
// set the native library path if we have native resources
// @TODO optional getdown.txt parameter to set addCurrentLibraryPath to true or false?
}
}
+ // test for jalview/s URL. Insert startupNotification URI into start of _appargs
+ if (! StringUtil.isBlank(_jalviewUri)) {
+ _appargs.add(0, _jalviewUri);
+ }
+ if (_appargs.size() > 0) {
+ String uri = _appargs.get(0);
+ try {
+ log.info("TRYING TO PARSE URL '"+uri+"'");
+ URI jalviewUri = new URI(uri);
+ if (jalviewUri != null) {
+ String scheme = jalviewUri.getScheme();
+ if (scheme != null && (scheme.equals("jalview") || scheme.equals("jalviews"))) {
+ boolean https = jalviewUri.getScheme().equals("jalviews");
+ String host = jalviewUri.getHost();
+ int port = jalviewUri.getPort();
+ String file = jalviewUri.getPath();
+ String ref = jalviewUri.getFragment();
+ String query = jalviewUri.getQuery();
+
+ _appargs.clear();
+ _appargs.add("-open");
+ if (host != null && host.length() > 0) {
+ URL newUrl = new URL(
+ (https?"https":"http")
+ + "://"
+ + host
+ + (port > -1? String.valueOf(port) : "")
+ + jalviewUri.getRawPath()
+ + (query != null && query.length() > 0 ? "?" + jalviewUri.getRawQuery() : "")
+ );
+ _appargs.add(newUrl.toString());
+ } else {
+ _appargs.add(file);
+ }
+
+ if (ref != null && ref.length() > 0) {
+ String[] refArgs = ref.split("&");
+ for (String refArg : refArgs) {
+ if (refArg.startsWith("jvmmempc=")) {
+ jvmmempc = refArg.substring(9);
+ continue;
+ }
+ if (refArg.startsWith("jvmmemmax=")) {
+ jvmmemmax = refArg.substring(10);
+ continue;
+ }
+ _appargs.add(URLDecoder.decode(refArg, "UTF-8"));
+ }
+ }
+
+ }
+ }
+ } catch (URISyntaxException e) {
+ log.error("Malformed jalview URI", uri);
+ }
+ }
+
+ for (String argString: _appargs) {
+ if (argString.startsWith("-jvmmempc=")) {
+ jvmmempc = argString.substring(10);
+ continue;
+ }
+ if (argString.startsWith("-jvmmemmax=")) {
+ jvmmemmax = argString.substring(11);
+ continue;
+ }
+ }
+
+ // add the memory setting from jvmmempc and jvmmemmax
+ long maxMemLong = -1;
+ maxMemLong = MemorySetting.getMemorySetting(jvmmemmax, jvmmempc);
+ if (maxMemLong > 0)
+ {
+ String[] maxMemHeapArg = new String[]{"-Xmx"+Long.toString(maxMemLong)};
+ // remove other max heap size arg
+ ARG: for (int i = 0; i < _jvmargs.size(); i++) {
+ if (_jvmargs.get(i) instanceof java.lang.String && _jvmargs.get(i).startsWith("-Xmx")) {
+ _jvmargs.remove(i);
+ break ARG;
+ }
+ }
+ addAll(maxMemHeapArg, _jvmargs);
+ }
+
// add the JVM arguments
for (String string : _jvmargs) {
args.add(processArg(string));
if (j > -1) {
ext = filename.substring(j+1);
}
- if (LOCATOR_FILE_EXTENSION.equals(ext.toLowerCase())) {
+ if (ext != null && LOCATOR_FILE_EXTENSION.equals(ext.toLowerCase())) {
// this file extension should have been dealt with in Getdown class
} else {
_appargs.add(0, "-open");
for (String string : _appargs) {
args.add(processArg(string));
}
-
+
String[] envp = createEnvironment();
String[] sargs = args.toArray(new String[args.size()]);
log.info("Running " + StringUtil.join(sargs, "\n "));
clearValidationMarkers();
// if the new copy validates, reinitialize ourselves; otherwise report baffling hoseage
if (_digest.validateResource(crsrc, null)) {
+ // unset _initialisedConfig so new file is initialised
+ _initialisedConfig = null;
init(true);
} else {
log.warning(CONFIG_FILE + " failed to validate even after redownloading. " +
for (int i = 0; i < filenames.length; i++) {
String filename = filenames[i];
// skip any other locator files in a multiple file list
- if (! filename.toLowerCase().endsWith("."+Application.LOCATOR_FILE_EXTENSION)) {
+ if (filename.startsWith("jalview://") || filename.startsWith("jalviews://")) {
+ setJalviewUri(filename);
+ } else if (! filename.toLowerCase().endsWith("."+Application.LOCATOR_FILE_EXTENSION)) {
addStartupFile(filename);
}
}
_startupFiles.add(new File(filename));
}
+ public static void setJalviewUri(String uri) {
+ _jalviewUri = uri;
+ }
+
private Config createLocatorConfig(Config.ParseOpts opts) {
if (_locatorFile == null) {
return null;
log.warning("Failure reading locator file", "file", _locatorFile, e);
}
- log.info("Returning locatorConfig", locatorConfig);
-
return locatorConfig;
}
protected final EnvConfig _envc;
protected File _config;
+ protected File _backupConfig;
protected Digest _digest;
protected long _version = -1;
protected static File _locatorFile;
protected static List<File> _startupFiles = new ArrayList<>();
+ protected static String _jalviewUri;
public static final String LOCATOR_FILE_EXTENSION = "jvl";
+
+ private boolean _initialised = false;
+ private Config _initialisedConfig = null;
+
+ public static String i4jVersion = null;
+ private String jvmmempc = null;
+ private String jvmmemmax = null;
}