import java.util.Locale;
import java.util.concurrent.TimeUnit;
+import jalview.bin.argparser.Arg;
import jalview.util.ChannelProperties;
import jalview.util.LaunchUtils;
* A Launcher class for Jalview. This class is used to launch Jalview from the
* shadowJar when Getdown is not used or available. It attempts to take all the
* command line arguments to pass on to the jalview.bin.Jalview class, but to
- * insert a -Xmx memory setting to a sensible default, using the -jvmmempc and
+ * insert a -Xmx memory setting to a sensible default, using the --jvmmempc and
* -jvmmemmax application arguments if specified. If not specified then system
* properties will be looked for by jalview.bin.MemorySetting. If the user has
- * provided the JVM with a -Xmx setting directly and not set -jvmmempc or
- * -jvmmemmax then this setting will be used and system properties ignored. If
- * -Xmx is set as well as -jvmmempc or -jvmmemmax as argument(s) then the -Xmx
+ * provided the JVM with a -Xmx setting directly and not set --jvmmempc or
+ * --jvmmemmax then this setting will be used and system properties ignored. If
+ * -Xmx is set as well as --jvmmempc or --jvmmemmax as argument(s) then the -Xmx
* argument will NOT be passed on to the main application launch.
*
* @author bsoares
{
private final static String startClass = "jalview.bin.Jalview";
- private static boolean checkJVMSymlink(String testBin)
- {
- File testBinFile = new File(testBin);
- if (!testBinFile.exists())
- {
- return false;
- }
- File targetFile = null;
- try
- {
- targetFile = testBinFile.getCanonicalFile();
- } catch (IOException e)
- {
- return false;
- }
- if (targetFile != null && ("java".equals(targetFile.getName())
- || "java.exe".equals(targetFile.getName())))
- {
- return true;
- }
- return false;
- }
+ // not setting this yet due to problem with Jmol
+ private final static String headlessProperty = "java.awt.headless";
+
+ // used for headless macOS
+ private final static String macosHeadlessProperty = "apple.awt.UIElement";
+
+ // arguments that assume headless mode
+ private final static String[] assumeHeadlessArgs = { "headless", "output",
+ "image", "structureimage" };
/**
* main method for jalview.bin.Launcher. This restarts the same JRE's JVM with
- * the same arguments but with memory adjusted based on extracted -jvmmempc
- * and -jvmmemmax application arguments. If on a Mac then extra dock:icon and
+ * the same arguments but with memory adjusted based on extracted --jvmmempc
+ * and --jvmmemmax application arguments. If on a Mac then extra dock:icon and
* dock:name arguments are also set.
*
* @param args
{
if (!LaunchUtils.checkJavaVersion())
{
- System.err.println("WARNING - The Java version being used (Java "
- + LaunchUtils.getJavaVersion()
- + ") may lead to problems. This installation of Jalview should be used with Java "
- + LaunchUtils.getJavaCompileVersion() + ".");
- }
- final String appName = ChannelProperties.getProperty("app_name");
- final String javaBinDir = System.getProperty("java.home")
- + File.separator + "bin" + File.separator;
- String javaBin = null;
- if (javaBin == null && checkJVMSymlink(javaBinDir + appName))
- {
- javaBin = javaBinDir + appName;
- }
- if (javaBin == null && checkJVMSymlink(javaBinDir + "Jalview"))
- {
- javaBin = javaBinDir + "Jalview";
- }
- if (javaBin == null && checkJVMSymlink(javaBinDir + "java"))
- {
- javaBin = javaBinDir + "java";
- }
- if (javaBin == null)
- {
- javaBin = "java";
+ jalview.bin.Console
+ .errPrintln("WARNING - The Java version being used (Java "
+ + LaunchUtils.getJavaVersion()
+ + ") may lead to problems. This installation of Jalview should be used with Java "
+ + LaunchUtils.getJavaCompileVersion() + ".");
}
- List<String> command = new ArrayList<>();
- command.add(javaBin);
-
- String memSetting = null;
-
- boolean isAMac = System.getProperty("os.name").indexOf("Mac") > -1;
-
- for (String jvmArg : ManagementFactory.getRuntimeMXBean()
- .getInputArguments())
- {
- command.add(jvmArg);
- }
- command.add("-cp");
- command.add(ManagementFactory.getRuntimeMXBean().getClassPath());
-
String jvmmempc = null;
String jvmmemmax = null;
boolean debug = false;
boolean wait = true;
boolean quiet = false;
+ boolean headless = false;
+ boolean assumeheadless = false;
+ boolean gui = false;
+ boolean help = false;
+ boolean stdout = false;
// must set --debug before --launcher...
boolean launcherstop = false;
boolean launcherprint = false;
boolean launcherwait = false;
ArrayList<String> arguments = new ArrayList<>();
+ String previousArg = null;
+ // set debug first
for (String arg : args)
{
if (arg.equals("--debug"))
{
debug = true;
}
+ }
+ for (String arg : args)
+ {
if (arg.equals("--quiet"))
{
quiet = true;
}
- if (debug && arg.equals("--launcherprint"))
+ else if (arg.equals("--gui"))
{
- launcherprint = true;
+ gui = true;
}
- if (debug && arg.equals("--launcherstop"))
+ else if (arg.equals("--help"))
{
- launcherstop = true;
+ help = true;
+ }
+ else if (arg.equals("--version"))
+ {
+ help = true;
+ }
+
+ if (!assumeheadless)
+ {
+ for (String a : assumeHeadlessArgs)
+ {
+ if (arg.equals("--" + a) || arg.startsWith("--" + a + "="))
+ {
+ assumeheadless = true;
+ }
+ }
}
- if (debug && arg.equals("--launcherwait"))
+
+ if (arg.equals("--output=-")
+ || (arg.equals("-") && "--output".equals(previousArg)))
{
- launcherwait = true;
+ stdout = true;
}
- // this ends the launcher immediately
- if (debug && arg.equals("--launchernowait"))
+
+ if (debug)
{
- wait = false;
+ if (arg.equals("--launcherprint"))
+ {
+ launcherprint = true;
+ }
+ else if (arg.equals("--launcherstop"))
+ {
+ launcherstop = true;
+ }
+ else if (arg.equals("--launcherwait"))
+ {
+ launcherwait = true;
+ }
+ else
+ // this ends the launcher immediately
+ if (arg.equals("--launchernowait"))
+ {
+ wait = false;
+ }
}
+ previousArg = arg;
// Don't add the --launcher... args to Jalview launch
if (arg.startsWith("--launcher"))
{
}
// jvmmempc and jvmmemmax args used to set memory and are not passed on to
// startClass
- if (arg.startsWith(
- "-" + MemorySetting.MAX_HEAPSIZE_PERCENT_PROPERTY_NAME + "="))
+ final String jvmmempcArg = Arg.JVMMEMPC.getName();
+ final String jvmmemmaxArg = Arg.JVMMEMMAX.getName();
+ if (arg.startsWith("-" + jvmmempcArg + "="))
{
- jvmmempc = arg.substring(
- MemorySetting.MAX_HEAPSIZE_PERCENT_PROPERTY_NAME.length()
- + 2);
+ jvmmempc = arg.substring(jvmmempcArg.length() + 2);
}
- else if (arg.startsWith(
- "-" + MemorySetting.MAX_HEAPSIZE_PROPERTY_NAME + "="))
+ else if (arg.startsWith("-" + jvmmemmaxArg + "="))
{
- jvmmemmax = arg.substring(
- MemorySetting.MAX_HEAPSIZE_PROPERTY_NAME.length() + 2);
+ jvmmemmax = arg.substring(jvmmemmaxArg.length() + 2);
}
// --doubledash versions
- else if (arg.startsWith("--"
- + MemorySetting.MAX_HEAPSIZE_PERCENT_PROPERTY_NAME + "="))
+ else if (arg.startsWith("--" + jvmmempcArg + "="))
{
- jvmmempc = arg.substring(
- MemorySetting.MAX_HEAPSIZE_PERCENT_PROPERTY_NAME.length()
- + 3);
+ jvmmempc = arg.substring(jvmmempcArg.length() + 3);
}
- else if (arg.startsWith(
- "--" + MemorySetting.MAX_HEAPSIZE_PROPERTY_NAME + "="))
+ else if (arg.startsWith("--" + jvmmemmaxArg + "="))
{
- jvmmemmax = arg.substring(
- MemorySetting.MAX_HEAPSIZE_PROPERTY_NAME.length() + 3);
+ jvmmemmax = arg.substring(jvmmemmaxArg.length() + 3);
}
// retain arg
else
arguments.add(arg);
}
}
+ if (help)
+ {
+ // --help takes precedence over --gui
+ headless = true;
+ }
+ else if (gui)
+ {
+ // --gui takes precedence over --headless
+ headless = false;
+ }
+ else
+ {
+ // --output arguments assume headless mode
+ headless = assumeheadless;
+ }
+
+ final String appName = ChannelProperties.getProperty("app_name");
+
+ // if we're using jalview.bin.Launcher we always assume a console is in use
+ final String javaBin = LaunchUtils.findJavaBin(true);
+
+ List<String> command = new ArrayList<>();
+ command.add(javaBin);
+
+ String memSetting = null;
+
+ for (String jvmArg : ManagementFactory.getRuntimeMXBean()
+ .getInputArguments())
+ {
+ command.add(jvmArg);
+ }
+ command.add("-cp");
+ command.add(ManagementFactory.getRuntimeMXBean().getClassPath());
// use saved preferences if no cmdline args
boolean useCustomisedSettings = LaunchUtils
boolean memSet = false;
boolean dockIcon = false;
boolean dockName = false;
+ boolean headlessProp = false;
+ boolean macosHeadlessProp = false;
for (int i = 0; i < command.size(); i++)
{
String arg = command.get(i);
{
dockName = true;
}
+ else if (arg.startsWith("-D" + headlessProperty + "="))
+ {
+ headlessProp = true;
+ }
+ else if (arg.startsWith("-D" + macosHeadlessProperty + "="))
+ {
+ macosHeadlessProp = true;
+ }
}
if (!memSet)
}
}
- if (isAMac)
+ if (LaunchUtils.isMac)
{
if (!dockIcon)
{
// -Xdock:name=... doesn't actually work :(
// Leaving it in in case it gets fixed
command.add("-Xdock:name=" + appName);
- // this launches WITHOUT an icon in the macOS dock. Could be useful for
- // getdown?
- // command.add("-Dapple.awt.UIElement=false");
// This also does not work for the dock
command.add("-Dcom.apple.mrj.application.apple.menu.about.name="
+ appName);
}
}
+ if (headless && !headlessProp)
+ {
+ System.setProperty(headlessProperty, "true");
+ /* not setting this in java invocation of running jalview due to problem with Jmol */
+ if (help)
+ {
+ command.add("-D" + headlessProperty + "=true");
+ }
+ }
+ if (headless && LaunchUtils.isMac && !macosHeadlessProp)
+ {
+ System.setProperty(macosHeadlessProperty, "true");
+ command.add("-D" + macosHeadlessProperty + "=true");
+ }
String scalePropertyArg = HiDPISetting.getScalePropertyArg();
if (scalePropertyArg != null)
{
- sysout(debug, quiet, "Running " + startClass + " with scale setting "
+ syserr(debug, quiet, "Running " + startClass + " with scale setting "
+ scalePropertyArg);
command.add(scalePropertyArg);
}
if ((Boolean.parseBoolean(System.getProperty("launcherprint", "false"))
|| launcherprint))
{
- sysout(debug, quiet,
+ syserr(debug, quiet,
"LAUNCHER COMMAND: " + String.join(" ", builder.command()));
}
- sysout(debug, quiet,
+ syserr(debug, quiet,
"Running " + startClass + " with "
+ (memSetting == null ? "no memory setting"
: ("memory setting " + memSetting)));
if (Boolean.parseBoolean(System.getProperty("launcherstop", "false"))
|| (debug && launcherstop))
{
- sysout(debug, quiet,
+ syserr(debug, quiet,
"System property 'launcherstop' is set and not 'false'. Exiting.");
System.exit(0);
}
Process process = builder.start();
if (wait || launcherwait)
{
- sysout(debug, quiet, "Launching application process");
+ syserr(debug, quiet, "Launching application process");
process.waitFor();
}
else
{
int waitInt = 0;
- sysout(debug, quiet,
+ syserr(debug, quiet,
"Wait time for application process is " + waitInt + "ms");
process.waitFor(waitInt, TimeUnit.MILLISECONDS);
}
- sysout(debug, quiet, "Launcher process ending");
+ syserr(debug, quiet, "Launcher process ending");
} catch (IOException e)
{
if (e.getMessage().toLowerCase(Locale.ROOT).contains("memory"))
{
- System.err.println("Caught a memory exception: " + e.getMessage());
+ jalview.bin.Console
+ .errPrintln("Caught a memory exception: " + e.getMessage());
// Probably the "Cannot allocate memory" error, try without the memory
// setting
ArrayList<String> commandNoMem = new ArrayList<>();
}
final ProcessBuilder builderNoMem = new ProcessBuilder(
commandNoMem);
- System.err.println("Command without memory setting: "
+ jalview.bin.Console.errPrintln("Command without memory setting: "
+ String.join(" ", builderNoMem.command()));
try
{
}
}
- private static void sysout(boolean debug, boolean quiet, String message)
+ private static void syserr(boolean debug, boolean quiet, String message)
{
if (debug && !quiet)
{
- System.out.println("LAUNCHERDEBUG - " + message);
+ jalview.bin.Console.errPrintln("LAUNCHERDEBUG - " + message);
}
}