2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
23 import java.awt.Color;
24 import java.io.BufferedReader;
26 import java.io.FileOutputStream;
27 import java.io.IOException;
28 import java.io.InputStreamReader;
29 import java.io.OutputStream;
30 import java.io.OutputStreamWriter;
31 import java.io.PrintStream;
32 import java.io.PrintWriter;
33 import java.net.MalformedURLException;
35 import java.net.URISyntaxException;
37 import java.security.AllPermission;
38 import java.security.CodeSource;
39 import java.security.PermissionCollection;
40 import java.security.Permissions;
41 import java.security.Policy;
42 import java.util.ArrayList;
43 import java.util.HashMap;
44 import java.util.List;
45 import java.util.Locale;
47 import java.util.Properties;
48 import java.util.Vector;
49 import java.util.logging.ConsoleHandler;
50 import java.util.logging.Level;
51 import java.util.logging.Logger;
52 import java.util.stream.Collectors;
54 import javax.swing.JDialog;
55 import javax.swing.JFrame;
56 import javax.swing.JInternalFrame;
57 import javax.swing.JOptionPane;
58 import javax.swing.SwingUtilities;
59 import javax.swing.UIManager;
60 import javax.swing.UIManager.LookAndFeelInfo;
61 import javax.swing.UnsupportedLookAndFeelException;
63 import com.formdev.flatlaf.FlatLightLaf;
64 import com.formdev.flatlaf.themes.FlatMacLightLaf;
65 import com.formdev.flatlaf.util.SystemInfo;
66 import com.threerings.getdown.util.LaunchUtil;
68 //import edu.stanford.ejalbert.launching.IBrowserLaunching;
69 import groovy.lang.Binding;
70 import groovy.util.GroovyScriptEngine;
71 import jalview.bin.argparser.Arg;
72 import jalview.bin.argparser.Arg.Opt;
73 import jalview.bin.argparser.Arg.Type;
74 import jalview.bin.argparser.ArgParser;
75 import jalview.bin.argparser.BootstrapArgs;
76 import jalview.ext.so.SequenceOntology;
77 import jalview.gui.AlignFrame;
78 import jalview.gui.Desktop;
79 import jalview.gui.PromptUserConfig;
80 import jalview.gui.QuitHandler;
81 import jalview.gui.QuitHandler.QResponse;
82 import jalview.gui.StructureViewerBase;
83 import jalview.io.AppletFormatAdapter;
84 import jalview.io.BioJsHTMLOutput;
85 import jalview.io.DataSourceType;
86 import jalview.io.FileFormat;
87 import jalview.io.FileFormatException;
88 import jalview.io.FileFormatI;
89 import jalview.io.FileFormats;
90 import jalview.io.FileLoader;
91 import jalview.io.HtmlSvgOutput;
92 import jalview.io.IdentifyFile;
93 import jalview.io.NewickFile;
94 import jalview.io.gff.SequenceOntologyFactory;
95 import jalview.schemes.ColourSchemeI;
96 import jalview.schemes.ColourSchemeProperty;
97 import jalview.util.ChannelProperties;
98 import jalview.util.HttpUtils;
99 import jalview.util.LaunchUtils;
100 import jalview.util.MessageManager;
101 import jalview.util.Platform;
102 import jalview.ws.jws2.Jws2Discoverer;
105 * Main class for Jalview Application <br>
107 * start with: java -classpath "$PATH_TO_LIB$/*:$PATH_TO_CLASSES$" \
108 * jalview.bin.Jalview
110 * or on Windows: java -classpath "$PATH_TO_LIB$/*;$PATH_TO_CLASSES$" \
111 * jalview.bin.Jalview jalview.bin.Jalview
113 * (ensure -classpath arg is quoted to avoid shell expansion of '*' and do not
114 * embellish '*' to e.g. '*.jar')
117 * @version $Revision$
123 Platform.getURLCommandArguments();
124 Platform.addJ2SDirectDatabaseCall("https://www.jalview.org");
125 Platform.addJ2SDirectDatabaseCall("http://www.jalview.org");
126 Platform.addJ2SDirectDatabaseCall("http://www.compbio.dundee.ac.uk");
127 Platform.addJ2SDirectDatabaseCall("https://www.compbio.dundee.ac.uk");
131 * singleton instance of this class
133 private static Jalview instance;
135 private Desktop desktop;
137 protected Commands cmds;
139 public static AlignFrame currentAlignFrame;
141 public ArgParser argparser = null;
143 public BootstrapArgs bootstrapArgs = null;
145 private boolean QUIET = false;
147 public static boolean quiet()
149 return Jalview.getInstance() != null && Jalview.getInstance().QUIET;
154 if (!Platform.isJS())
161 // grab all the rights we can for the JVM
162 Policy.setPolicy(new Policy()
165 public PermissionCollection getPermissions(CodeSource codesource)
167 Permissions perms = new Permissions();
168 perms.add(new AllPermission());
173 public void refresh()
181 * keep track of feature fetching tasks.
189 * TODO: generalise to track all jalview events to orchestrate batch processing
193 private int queued = 0;
195 private int running = 0;
197 public FeatureFetcher()
202 public void addFetcher(final AlignFrame af,
203 final Vector<String> dasSources)
205 final long id = System.currentTimeMillis();
207 final FeatureFetcher us = this;
208 new Thread(new Runnable()
220 af.setProgressBar(MessageManager
221 .getString("status.das_features_being_retrived"), id);
222 af.featureSettings_actionPerformed(null);
223 af.setProgressBar(null, id);
232 public synchronized boolean allFinished()
234 return queued == 0 && running == 0;
239 public static Jalview getInstance()
245 * main class for Jalview application
248 * open <em>filename</em>
250 public static void main(String[] args)
252 // setLogging(); // BH - for event debugging in JavaScript
253 instance = new Jalview();
254 instance.doMain(args);
257 private static void logClass(String name)
259 // BH - for event debugging in JavaScript
260 ConsoleHandler consoleHandler = new ConsoleHandler();
261 consoleHandler.setLevel(Level.ALL);
262 Logger logger = Logger.getLogger(name);
263 logger.setLevel(Level.ALL);
264 logger.addHandler(consoleHandler);
267 @SuppressWarnings("unused")
268 private static void setLogging()
276 System.out.println("not in js");
279 // BH - for event debugging in JavaScript (Java mode only)
280 if (!Platform.isJS())
287 Logger.getLogger("").setLevel(Level.ALL);
288 logClass("java.awt.EventDispatchThread");
289 logClass("java.awt.EventQueue");
290 logClass("java.awt.Component");
291 logClass("java.awt.focus.Component");
292 logClass("java.awt.focus.DefaultKeyboardFocusManager");
300 void doMain(String[] args)
302 if (!Platform.isJS())
304 System.setSecurityManager(null);
307 if (args == null || args.length == 0 || (args.length == 1
308 && (args[0] == null || args[0].length() == 0)))
310 args = new String[] {};
313 // get args needed before proper ArgParser
314 bootstrapArgs = BootstrapArgs.getBootstrapArgs(args);
316 if (!Platform.isJS())
318 // are we being --quiet ?
319 if (bootstrapArgs.contains(Arg.QUIET))
322 OutputStream devNull = new OutputStream()
326 public void write(int b)
331 System.setOut(new PrintStream(devNull));
332 // redirecting stderr not working
333 if (bootstrapArgs.getList(Arg.QUIET).size() > 1)
335 System.setErr(new PrintStream(devNull));
339 if (bootstrapArgs.contains(Arg.HELP)
340 || bootstrapArgs.contains(Arg.VERSION))
346 // Move any new getdown-launcher-new.jar into place over old
347 // getdown-launcher.jar
348 String appdirString = System.getProperty("getdownappdir");
349 if (appdirString != null && appdirString.length() > 0)
351 final File appdir = new File(appdirString);
358 LaunchUtil.upgradeGetdown(
359 new File(appdir, "getdown-launcher-old.jar"),
360 new File(appdir, "getdown-launcher.jar"),
361 new File(appdir, "getdown-launcher-new.jar"));
366 if (!quiet() || bootstrapArgs.contains(Arg.VERSION))
369 "Java version: " + System.getProperty("java.version"));
370 System.out.println("Java home: " + System.getProperty("java.home"));
371 System.out.println("Java arch: " + System.getProperty("os.arch") + " "
372 + System.getProperty("os.name") + " "
373 + System.getProperty("os.version"));
375 String val = System.getProperty("sys.install4jVersion");
378 System.out.println("Install4j version: " + val);
380 val = System.getProperty("installer_template_version");
383 System.out.println("Install4j template version: " + val);
385 val = System.getProperty("launcher_version");
388 System.out.println("Launcher version: " + val);
392 if (Platform.isLinux() && LaunchUtils.getJavaVersion() < 11)
394 System.setProperty("flatlaf.uiScale", "1");
397 // get bootstrap properties (mainly for the logger level)
398 Properties bootstrapProperties = Cache
399 .bootstrapProperties(bootstrapArgs.get(Arg.PROPS));
401 // report Jalview version
402 Cache.loadBuildProperties(
403 !quiet() || bootstrapArgs.contains(Arg.VERSION));
405 // stop now if only after --version
406 if (bootstrapArgs.contains(Arg.VERSION))
408 Jalview.exit(null, 0);
412 ArgsParser aparser = new ArgsParser(args);
415 boolean headless = false;
417 boolean headlessArg = false;
421 String logLevel = null;
422 if (bootstrapArgs.contains(Arg.TRACE))
426 else if (bootstrapArgs.contains(Arg.DEBUG))
430 if (logLevel == null && !(bootstrapProperties == null))
432 logLevel = bootstrapProperties.getProperty(Cache.JALVIEWLOGLEVEL);
434 Console.initLogger(logLevel);
435 } catch (NoClassDefFoundError error)
437 error.printStackTrace();
438 String message = "\nEssential logging libraries not found."
439 + "\nUse: java -classpath \"$PATH_TO_LIB$/*:$PATH_TO_CLASSES$\" jalview.bin.Jalview";
440 Jalview.exit(message, 0);
443 // register SIGTERM listener
444 Runtime.getRuntime().addShutdownHook(new Thread()
448 Console.debug("Running shutdown hook");
449 QuitHandler.startForceQuit();
450 boolean closeExternal = Cache
451 .getDefault("DEFAULT_CLOSE_EXTERNAL_VIEWERS", false)
452 || Cache.getDefault("ALWAYS_CLOSE_EXTERNAL_VIEWERS", false);
453 StructureViewerBase.setQuitClose(closeExternal);
454 for (JInternalFrame frame : Desktop.desktop.getAllFrames())
456 if (frame instanceof StructureViewerBase)
458 ((StructureViewerBase) frame).closeViewer(closeExternal);
462 if (QuitHandler.gotQuitResponse() == QResponse.CANCEL_QUIT)
464 // Got to here by a SIGTERM signal.
465 // Note we will not actually cancel the quit from here -- it's too
466 // late -- but we can wait for saving files and close external viewers
468 // Close viewers/Leave viewers open
469 Console.debug("Checking for saving files");
470 QuitHandler.getQuitResponse(false);
474 Console.debug("Nothing more to do");
476 Console.debug("Exiting, bye!");
477 // shutdownHook cannot be cancelled, JVM will now halt
481 String usrPropsFile = bootstrapArgs.contains(Arg.PROPS)
482 ? bootstrapArgs.get(Arg.PROPS)
483 : aparser.getValue("props");
484 // if usrPropsFile == null, loadProperties will use the Channel
486 Cache.loadProperties(usrPropsFile);
487 if (usrPropsFile != null)
490 "CMD [-props " + usrPropsFile + "] executed successfully!");
491 testoutput(bootstrapArgs, Arg.PROPS,
492 "test/jalview/bin/testProps.jvprops", usrPropsFile);
495 // --argfile=... -- OVERRIDES ALL NON-BOOTSTRAP ARGS
496 if (bootstrapArgs.contains(Arg.ARGFILE))
498 argparser = ArgParser.parseArgFiles(
499 bootstrapArgs.getValueList(Arg.ARGFILE),
500 bootstrapArgs.getBoolean(Arg.INITSUBSTITUTIONS),
505 argparser = new ArgParser(args,
506 bootstrapArgs.getBoolean(Arg.INITSUBSTITUTIONS),
510 if (!Platform.isJS())
517 if (bootstrapArgs.contains(Arg.HELP))
519 List<Map.Entry<Type, String>> helpArgs = bootstrapArgs
521 System.out.println(Arg.usage(helpArgs.stream().map(e -> e.getKey())
522 .collect(Collectors.toList())));
523 Jalview.exit(null, 0);
525 if (aparser.contains("help") || aparser.contains("h"))
528 * Now using new usage statement.
531 System.out.println(Arg.usage());
532 Jalview.exit(null, 0);
536 headlessArg = isHeadless(bootstrapArgs);
539 System.setProperty("java.awt.headless", "true");
542 if (aparser.contains("nodisplay") || aparser.contains("nogui")
543 || aparser.contains("headless"))
545 System.setProperty("java.awt.headless", "true");
550 // allow https handshakes to download intermediate certs if necessary
551 System.setProperty("com.sun.security.enableAIAcaIssuers", "true");
553 String jabawsUrl = bootstrapArgs.get(Arg.JABAWS);
554 if (jabawsUrl == null)
555 jabawsUrl = aparser.getValue("jabaws");
556 if (jabawsUrl != null)
560 Jws2Discoverer.getDiscoverer().setPreferredUrl(jabawsUrl);
562 "CMD [-jabaws " + jabawsUrl + "] executed successfully!");
563 testoutput(bootstrapArgs, Arg.JABAWS,
564 "http://www.compbio.dundee.ac.uk/jabaws", jabawsUrl);
565 } catch (MalformedURLException e)
568 "Invalid jabaws parameter: " + jabawsUrl + " ignored");
573 List<String> setprops = new ArrayList<>();
574 if (bootstrapArgs.contains(Arg.SETPROP))
576 setprops = bootstrapArgs.getValueList(Arg.SETPROP);
580 String sp = aparser.getValue("setprop");
584 sp = aparser.getValue("setprop");
587 for (String setprop : setprops)
589 int p = setprop.indexOf('=');
593 .println("Ignoring invalid setprop argument : " + setprop);
597 System.out.println("Executing setprop argument: " + setprop);
600 Cache.setProperty(setprop.substring(0, p),
601 setprop.substring(p + 1));
603 // DISABLED FOR SECURITY REASONS
604 // TODO: add a property to allow properties to be overriden by cli args
605 // Cache.setProperty(setprop.substring(0,p), setprop.substring(p+1));
608 if (System.getProperty("java.awt.headless") != null
609 && System.getProperty("java.awt.headless").equals("true"))
613 System.setProperty("http.agent",
614 "Jalview Desktop/" + Cache.getDefault("VERSION", "Unknown"));
618 Console.initLogger();
621 NoClassDefFoundError error)
623 error.printStackTrace();
624 String message = "\nEssential logging libraries not found."
625 + "\nUse: java -classpath \"$PATH_TO_LIB$/*:$PATH_TO_CLASSES$\" jalview.bin.Jalview";
626 Jalview.exit(message, 0);
630 if (!(headless || headlessArg))
634 * configure 'full' SO model if preferences say to, else use the default (full SO)
635 * - as JS currently doesn't have OBO parsing, it must use 'Lite' version
637 boolean soDefault = !Platform.isJS();
638 if (Cache.getDefault("USE_FULL_SO", soDefault))
640 SequenceOntologyFactory.setInstance(new SequenceOntology());
643 if (!(headless || headlessArg))
645 Desktop.nosplash = "false".equals(bootstrapArgs.get(Arg.SPLASH))
646 || aparser.contains("nosplash")
647 || Cache.getDefault("SPLASH", "true").equals("false");
648 desktop = new Desktop();
649 desktop.setInBatchMode(true); // indicate we are starting up
653 JalviewTaskbar.setTaskbar(this);
654 } catch (Exception e)
656 Console.info("Cannot set Taskbar");
657 Console.error(e.getMessage());
658 // e.printStackTrace();
659 } catch (Throwable t)
661 Console.info("Cannot set Taskbar");
662 Console.error(t.getMessage());
663 // t.printStackTrace();
666 // set Proxy settings before all the internet calls
667 Cache.setProxyPropertiesFromPreferences();
669 desktop.setVisible(true);
671 if (!Platform.isJS())
680 * Check to see that the JVM version being run is suitable for the Java
681 * version this Jalview was compiled for. Popup a warning if not.
683 if (!LaunchUtils.checkJavaVersion())
685 Console.warn("The Java version being used (Java "
686 + LaunchUtils.getJavaVersion()
687 + ") may lead to problems. This installation of Jalview should be used with Java "
688 + LaunchUtils.getJavaCompileVersion() + ".");
691 .getBooleanUserPreference("IGNORE_JVM_WARNING_POPUP"))
694 MessageManager.getString("label.continue") };
695 JOptionPane.showOptionDialog(null,
696 MessageManager.formatMessage(
697 "warning.wrong_jvm_version_message",
698 LaunchUtils.getJavaVersion(),
699 LaunchUtils.getJavaCompileVersion()),
701 .getString("warning.wrong_jvm_version_title"),
702 JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE,
703 null, options, options[0]);
707 boolean webservicediscovery = bootstrapArgs
708 .getBoolean(Arg.WEBSERVICEDISCOVERY);
709 if (aparser.contains("nowebservicediscovery"))
710 webservicediscovery = false;
711 if (webservicediscovery)
713 desktop.startServiceDiscovery();
717 testoutput(argparser, Arg.WEBSERVICEDISCOVERY);
720 boolean usagestats = bootstrapArgs.getBoolean(Arg.USAGESTATS);
721 if (aparser.contains("nousagestats"))
725 startUsageStats(desktop);
726 testoutput(argparser, Arg.USAGESTATS);
730 System.out.println("CMD [-nousagestats] executed successfully!");
731 testoutput(argparser, Arg.USAGESTATS);
734 boolean questionnaire = bootstrapArgs.getBoolean(Arg.QUESTIONNAIRE);
735 if (aparser.contains("noquestionnaire"))
736 questionnaire = false;
739 String url = aparser.getValue("questionnaire");
742 // Start the desktop questionnaire prompter with the specified
744 Console.debug("Starting questionnaire url at " + url);
745 desktop.checkForQuestionnaire(url);
746 System.out.println("CMD questionnaire[-" + url
747 + "] executed successfully!");
751 if (Cache.getProperty("NOQUESTIONNAIRES") == null)
753 // Start the desktop questionnaire prompter with the specified
756 // "http://anaplog.compbio.dundee.ac.uk/cgi-bin/questionnaire.pl";
758 String defurl = "https://www.jalview.org/cgi-bin/questionnaire.pl";
760 "Starting questionnaire with default url: " + defurl);
761 desktop.checkForQuestionnaire(defurl);
768 .println("CMD [-noquestionnaire] executed successfully!");
769 testoutput(argparser, Arg.QUESTIONNAIRE);
772 if ((!aparser.contains("nonews")
773 && Cache.getProperty("NONEWS") == null
774 && !"false".equals(bootstrapArgs.get(Arg.NEWS)))
775 || "true".equals(bootstrapArgs.get(Arg.NEWS)))
777 desktop.checkForNews();
780 if (!aparser.contains("nohtmltemplates")
781 && Cache.getProperty("NOHTMLTEMPLATES") == null)
783 BioJsHTMLOutput.updateBioJS();
787 // Run Commands from cli
788 cmds = new Commands(argparser, headlessArg);
789 boolean commandsSuccess = cmds.argsWereParsed();
794 if (argparser.getBoolean(Arg.NOQUIT))
797 "Completed " + Arg.HEADLESS.getName() + " commands, but "
798 + Arg.NOQUIT + " is set so not quitting!");
802 Jalview.exit("Successfully completed commands in headless mode",
806 Console.info("Successfully completed commands");
812 Jalview.exit("Error when running Commands in headless mode", 1);
814 Console.warn("Error when running commands");
817 // Check if JVM and compile version might cause problems and log if it
819 if (headless && !Platform.isJS() && !LaunchUtils.checkJavaVersion())
821 Console.warn("The Java version being used (Java "
822 + LaunchUtils.getJavaVersion()
823 + ") may lead to problems. This installation of Jalview should be used with Java "
824 + LaunchUtils.getJavaCompileVersion() + ".");
827 String file = null, data = null;
829 FileFormatI format = null;
831 DataSourceType protocol = null;
833 FileLoader fileLoader = new FileLoader(!headless);
835 String groovyscript = null; // script to execute after all loading is
836 // completed one way or another
837 // extract groovy argument and execute if necessary
838 groovyscript = aparser.getValue("groovy", true);
839 file = aparser.getValue("open", true);
841 if (file == null && desktop == null && !commandsSuccess)
843 Jalview.exit("No files to open!", 1);
847 // Finally, deal with the remaining input data.
852 desktop.setProgressBar(
854 .getString("status.processing_commandline_args"),
855 progress = System.currentTimeMillis());
857 System.out.println("CMD [-open " + file + "] executed successfully!");
859 if (!Platform.isJS())
861 * ignore in JavaScript -- can't just file existence - could load it?
866 if (!HttpUtils.startsWithHttpOrHttps(file))
868 if (!(new File(file)).exists())
873 "Can't find file '" + file + "' in headless mode", 1);
875 Console.warn("Can't find file'" + file + "'");
880 protocol = AppletFormatAdapter.checkProtocol(file);
884 format = new IdentifyFile().identify(file, protocol);
885 } catch (FileFormatException e1)
890 AlignFrame af = fileLoader.LoadFileWaitTillLoaded(file, protocol,
894 System.out.println("error");
898 setCurrentAlignFrame(af);
899 data = aparser.getValue("colour", true);
902 data.replaceAll("%20", " ");
904 ColourSchemeI cs = ColourSchemeProperty.getColourScheme(
905 af.getViewport(), af.getViewport().getAlignment(), data);
910 "CMD [-colour " + data + "] executed successfully!");
915 // Must maintain ability to use the groups flag
916 data = aparser.getValue("groups", true);
919 af.parseFeaturesFile(data,
920 AppletFormatAdapter.checkProtocol(data));
921 // System.out.println("Added " + data);
923 "CMD groups[-" + data + "] executed successfully!");
925 data = aparser.getValue("features", true);
928 af.parseFeaturesFile(data,
929 AppletFormatAdapter.checkProtocol(data));
930 // System.out.println("Added " + data);
932 "CMD [-features " + data + "] executed successfully!");
935 data = aparser.getValue("annotations", true);
938 af.loadJalviewDataFile(data, null, null, null);
939 // System.out.println("Added " + data);
941 "CMD [-annotations " + data + "] executed successfully!");
943 // set or clear the sortbytree flag.
944 if (aparser.contains("sortbytree"))
946 af.getViewport().setSortByTree(true);
947 if (af.getViewport().getSortByTree())
949 System.out.println("CMD [-sortbytree] executed successfully!");
952 if (aparser.contains("no-annotation"))
954 af.getViewport().setShowAnnotation(false);
955 if (!af.getViewport().isShowAnnotation())
957 System.out.println("CMD no-annotation executed successfully!");
960 if (aparser.contains("nosortbytree"))
962 af.getViewport().setSortByTree(false);
963 if (!af.getViewport().getSortByTree())
966 .println("CMD [-nosortbytree] executed successfully!");
969 data = aparser.getValue("tree", true);
975 "CMD [-tree " + data + "] executed successfully!");
976 NewickFile nf = new NewickFile(data,
977 AppletFormatAdapter.checkProtocol(data));
979 .setCurrentTree(af.showNewickTree(nf, data).getTree());
980 } catch (IOException ex)
982 System.err.println("Couldn't add tree " + data);
983 ex.printStackTrace(System.err);
986 // TODO - load PDB structure(s) to alignment JAL-629
987 // (associate with identical sequence in alignment, or a specified
989 if (groovyscript != null)
991 // Execute the groovy script after we've done all the rendering stuff
992 // and before any images or figures are generated.
993 System.out.println("Executing script " + groovyscript);
994 executeGroovyScript(groovyscript, af);
995 System.out.println("CMD groovy[" + groovyscript
996 + "] executed successfully!");
999 String imageName = "unnamed.png";
1000 while (aparser.getSize() > 1)
1002 String outputFormat = aparser.nextValue();
1003 file = aparser.nextValue();
1005 if (outputFormat.equalsIgnoreCase("png"))
1007 af.createPNG(new File(file));
1008 imageName = (new File(file)).getName();
1009 System.out.println("Creating PNG image: " + file);
1012 else if (outputFormat.equalsIgnoreCase("svg"))
1014 File imageFile = new File(file);
1015 imageName = imageFile.getName();
1016 af.createSVG(imageFile);
1017 System.out.println("Creating SVG image: " + file);
1020 else if (outputFormat.equalsIgnoreCase("html"))
1022 File imageFile = new File(file);
1023 imageName = imageFile.getName();
1024 HtmlSvgOutput htmlSVG = new HtmlSvgOutput(af.alignPanel);
1025 htmlSVG.exportHTML(file);
1027 System.out.println("Creating HTML image: " + file);
1030 else if (outputFormat.equalsIgnoreCase("biojsmsa"))
1034 System.err.println("The output html file must not be null");
1039 BioJsHTMLOutput.refreshVersionInfo(
1040 BioJsHTMLOutput.BJS_TEMPLATES_LOCAL_DIRECTORY);
1041 } catch (URISyntaxException e)
1043 e.printStackTrace();
1045 BioJsHTMLOutput bjs = new BioJsHTMLOutput(af.alignPanel);
1046 bjs.exportHTML(file);
1048 .println("Creating BioJS MSA Viwer HTML file: " + file);
1051 else if (outputFormat.equalsIgnoreCase("imgMap"))
1053 af.createImageMap(new File(file), imageName);
1054 System.out.println("Creating image map: " + file);
1057 else if (outputFormat.equalsIgnoreCase("eps"))
1059 File outputFile = new File(file);
1061 "Creating EPS file: " + outputFile.getAbsolutePath());
1062 af.createEPS(outputFile);
1065 FileFormatI outFormat = null;
1068 outFormat = FileFormats.getInstance().forName(outputFormat);
1069 } catch (Exception formatP)
1071 System.out.println("Couldn't parse " + outFormat
1072 + " as a valid Jalview format string.");
1074 if (outFormat != null)
1076 if (!outFormat.isWritable())
1079 "This version of Jalview does not support alignment export as "
1084 af.saveAlignment(file, outFormat);
1085 if (af.isSaveAlignmentSuccessful())
1087 System.out.println("Written alignment in "
1088 + outFormat.getName() + " format to " + file);
1092 System.out.println("Error writing file " + file + " in "
1093 + outFormat.getName() + " format!!");
1100 while (aparser.getSize() > 0)
1102 System.out.println("Unknown arg: " + aparser.nextValue());
1107 AlignFrame startUpAlframe = null;
1108 // We'll only open the default file if the desktop is visible.
1110 // ////////////////////
1112 if (!Platform.isJS() && !headless && file == null
1113 && Cache.getDefault("SHOW_STARTUP_FILE", true)
1114 && !cmds.commandArgsProvided())
1115 // don't open the startup file if command line args have been processed
1116 // (&& !Commands.commandArgsProvided())
1123 file = Cache.getDefault("STARTUP_FILE",
1124 Cache.getDefault("www.jalview.org", "https://www.jalview.org")
1125 + "/examples/exampleFile_2_7.jvp");
1126 if (file.equals("http://www.jalview.org/examples/exampleFile_2_3.jar")
1128 "http://www.jalview.org/examples/exampleFile_2_7.jar"))
1130 file.replace("http:", "https:");
1131 // hardwire upgrade of the startup file
1132 file.replace("_2_3", "_2_7");
1133 file.replace("2_7.jar", "2_7.jvp");
1134 // and remove the stale setting
1135 Cache.removeProperty("STARTUP_FILE");
1138 protocol = AppletFormatAdapter.checkProtocol(file);
1140 if (file.endsWith(".jar"))
1142 format = FileFormat.Jalview;
1148 format = new IdentifyFile().identify(file, protocol);
1149 } catch (FileFormatException e)
1155 startUpAlframe = fileLoader.LoadFileWaitTillLoaded(file, protocol,
1157 // don't ask to save when quitting if only the startup file has been
1159 Console.debug("Resetting up-to-date flag for startup file");
1160 startUpAlframe.getViewport().setSavedUpToDate(true);
1161 // extract groovy arguments before anything else.
1164 // Once all other stuff is done, execute any groovy scripts (in order)
1165 if (groovyscript != null)
1167 if (Cache.groovyJarsPresent())
1169 System.out.println("Executing script " + groovyscript);
1170 executeGroovyScript(groovyscript, startUpAlframe);
1175 "Sorry. Groovy Support is not available, so ignoring the provided groovy script "
1179 // and finally, turn off batch mode indicator - if the desktop still exists
1180 if (desktop != null)
1184 desktop.setProgressBar(null, progress);
1186 desktop.setInBatchMode(false);
1190 private static void setLookAndFeel()
1192 // property laf = "crossplatform", "system", "gtk", "metal", "nimbus",
1194 // If not set (or chosen laf fails), use the normal SystemLaF and if on Mac,
1195 // try Quaqua/Vaqua.
1196 String lafProp = System.getProperty("laf");
1197 String lafSetting = Cache.getDefault("PREFERRED_LAF", null);
1198 String laf = "none";
1199 if (lafProp != null)
1203 else if (lafSetting != null)
1207 boolean lafSet = false;
1210 case "crossplatform":
1211 lafSet = setCrossPlatformLookAndFeel();
1214 Console.error("Could not set requested laf=" + laf);
1218 lafSet = setSystemLookAndFeel();
1221 Console.error("Could not set requested laf=" + laf);
1225 lafSet = setGtkLookAndFeel();
1228 Console.error("Could not set requested laf=" + laf);
1232 lafSet = setMetalLookAndFeel();
1235 Console.error("Could not set requested laf=" + laf);
1239 lafSet = setNimbusLookAndFeel();
1242 Console.error("Could not set requested laf=" + laf);
1246 lafSet = setFlatLookAndFeel();
1249 Console.error("Could not set requested laf=" + laf);
1253 lafSet = setMacLookAndFeel();
1256 Console.error("Could not set requested laf=" + laf);
1262 Console.error("Requested laf=" + laf + " not implemented");
1266 // Flatlaf default for everyone!
1267 lafSet = setFlatLookAndFeel();
1270 setSystemLookAndFeel();
1272 if (Platform.isLinux())
1274 setLinuxLookAndFeel();
1276 if (Platform.isMac())
1278 setMacLookAndFeel();
1283 private static boolean setCrossPlatformLookAndFeel()
1285 boolean set = false;
1288 UIManager.setLookAndFeel(
1289 UIManager.getCrossPlatformLookAndFeelClassName());
1291 } catch (Exception ex)
1293 Console.error("Unexpected Look and Feel Exception");
1294 Console.error(ex.getMessage());
1295 Console.debug(Cache.getStackTraceString(ex));
1300 private static boolean setSystemLookAndFeel()
1302 boolean set = false;
1305 UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
1307 } catch (Exception ex)
1309 Console.error("Unexpected Look and Feel Exception");
1310 Console.error(ex.getMessage());
1311 Console.debug(Cache.getStackTraceString(ex));
1316 private static boolean setSpecificLookAndFeel(String name,
1317 String className, boolean nameStartsWith)
1319 boolean set = false;
1322 for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels())
1324 if (info.getName() != null && nameStartsWith
1325 ? info.getName().toLowerCase(Locale.ROOT)
1326 .startsWith(name.toLowerCase(Locale.ROOT))
1327 : info.getName().toLowerCase(Locale.ROOT)
1328 .equals(name.toLowerCase(Locale.ROOT)))
1330 className = info.getClassName();
1334 UIManager.setLookAndFeel(className);
1336 } catch (Exception ex)
1338 Console.error("Unexpected Look and Feel Exception");
1339 Console.error(ex.getMessage());
1340 Console.debug(Cache.getStackTraceString(ex));
1345 private static boolean setGtkLookAndFeel()
1347 return setSpecificLookAndFeel("gtk",
1348 "com.sun.java.swing.plaf.gtk.GTKLookAndFeel", true);
1351 private static boolean setMetalLookAndFeel()
1353 return setSpecificLookAndFeel("metal",
1354 "javax.swing.plaf.metal.MetalLookAndFeel", false);
1357 private static boolean setNimbusLookAndFeel()
1359 return setSpecificLookAndFeel("nimbus",
1360 "javax.swing.plaf.nimbus.NimbusLookAndFeel", false);
1363 private static boolean setFlatLookAndFeel()
1365 boolean set = false;
1366 if (SystemInfo.isMacOS)
1370 UIManager.setLookAndFeel(
1371 "com.formdev.flatlaf.themes.FlatMacLightLaf");
1373 Console.debug("Using FlatMacLightLaf");
1374 } catch (ClassNotFoundException | InstantiationException
1375 | IllegalAccessException | UnsupportedLookAndFeelException e)
1377 Console.debug("Exception loading FlatLightLaf", e);
1379 System.setProperty("apple.laf.useScreenMenuBar", "true");
1380 System.setProperty("apple.awt.application.name",
1381 ChannelProperties.getProperty("app_name"));
1382 System.setProperty("apple.awt.application.appearance", "system");
1383 if (SystemInfo.isMacFullWindowContentSupported
1384 && Desktop.desktop != null)
1386 Console.debug("Setting transparent title bar");
1387 Desktop.desktop.getRootPane()
1388 .putClientProperty("apple.awt.fullWindowContent", true);
1389 Desktop.desktop.getRootPane()
1390 .putClientProperty("apple.awt.transparentTitleBar", true);
1391 Desktop.desktop.getRootPane()
1392 .putClientProperty("apple.awt.fullscreenable", true);
1394 SwingUtilities.invokeLater(() -> {
1395 FlatMacLightLaf.setup();
1397 Console.debug("Using FlatMacLightLaf");
1404 UIManager.setLookAndFeel("com.formdev.flatlaf.FlatLightLaf");
1406 Console.debug("Using FlatLightLaf");
1407 } catch (ClassNotFoundException | InstantiationException
1408 | IllegalAccessException | UnsupportedLookAndFeelException e)
1410 Console.debug("Exception loading FlatLightLaf", e);
1412 // Windows specific properties here
1413 SwingUtilities.invokeLater(() -> {
1414 FlatLightLaf.setup();
1416 Console.debug("Using FlatLightLaf");
1419 else if (SystemInfo.isLinux)
1423 UIManager.setLookAndFeel("com.formdev.flatlaf.FlatLightLaf");
1425 Console.debug("Using FlatLightLaf");
1426 } catch (ClassNotFoundException | InstantiationException
1427 | IllegalAccessException | UnsupportedLookAndFeelException e)
1429 Console.debug("Exception loading FlatLightLaf", e);
1431 // enable custom window decorations
1432 JFrame.setDefaultLookAndFeelDecorated(true);
1433 JDialog.setDefaultLookAndFeelDecorated(true);
1434 SwingUtilities.invokeLater(() -> {
1435 FlatLightLaf.setup();
1437 Console.debug("Using FlatLightLaf");
1445 UIManager.setLookAndFeel("com.formdev.flatlaf.FlatLightLaf");
1447 Console.debug("Using FlatLightLaf");
1448 } catch (ClassNotFoundException | InstantiationException
1449 | IllegalAccessException | UnsupportedLookAndFeelException e)
1451 Console.debug("Exception loading FlatLightLaf", e);
1457 UIManager.put("TabbedPane.tabType", "card");
1458 UIManager.put("TabbedPane.showTabSeparators", true);
1459 UIManager.put("TabbedPane.showContentSeparator", true);
1460 UIManager.put("TabbedPane.tabSeparatorsFullHeight", true);
1461 UIManager.put("TabbedPane.tabsOverlapBorder", true);
1462 UIManager.put("TabbedPane.hasFullBorder", true);
1463 UIManager.put("TabbedPane.tabLayoutPolicy", "scroll");
1464 UIManager.put("TabbedPane.scrollButtonsPolicy", "asNeeded");
1465 UIManager.put("TabbedPane.smoothScrolling", true);
1466 UIManager.put("TabbedPane.tabWidthMode", "compact");
1467 UIManager.put("TabbedPane.selectedBackground", Color.white);
1468 UIManager.put("TabbedPane.background", new Color(236, 236, 236));
1469 UIManager.put("TabbedPane.hoverColor", Color.lightGray);
1472 Desktop.setLiveDragMode(Cache.getDefault("FLAT_LIVE_DRAG_MODE", true));
1476 private static boolean setMacLookAndFeel()
1478 boolean set = false;
1479 System.setProperty("com.apple.mrj.application.apple.menu.about.name",
1480 ChannelProperties.getProperty("app_name"));
1481 System.setProperty("apple.laf.useScreenMenuBar", "true");
1483 * broken native LAFs on (ARM?) macbooks
1484 set = setQuaquaLookAndFeel();
1485 if ((!set) || !UIManager.getLookAndFeel().getClass().toString()
1486 .toLowerCase(Locale.ROOT).contains("quaqua"))
1488 set = setVaquaLookAndFeel();
1491 set = setFlatLookAndFeel();
1495 private static boolean setLinuxLookAndFeel()
1497 boolean set = false;
1498 set = setFlatLookAndFeel();
1500 set = setMetalLookAndFeel();
1501 // avoid GtkLookAndFeel -- not good results especially on HiDPI
1503 set = setNimbusLookAndFeel();
1508 private static void showUsage()
1511 "Usage: jalview -open [FILE] [OUTPUT_FORMAT] [OUTPUT_FILE]\n\n"
1512 + "-nodisplay\tRun Jalview without User Interface.\n"
1513 + "-props FILE\tUse the given Jalview properties file instead of users default.\n"
1514 + "-colour COLOURSCHEME\tThe colourscheme to be applied to the alignment\n"
1515 + "-annotations FILE\tAdd precalculated annotations to the alignment.\n"
1516 + "-tree FILE\tLoad the given newick format tree file onto the alignment\n"
1517 + "-features FILE\tUse the given file to mark features on the alignment.\n"
1518 + "-fasta FILE\tCreate alignment file FILE in Fasta format.\n"
1519 + "-clustal FILE\tCreate alignment file FILE in Clustal format.\n"
1520 + "-pfam FILE\tCreate alignment file FILE in PFAM format.\n"
1521 + "-msf FILE\tCreate alignment file FILE in MSF format.\n"
1522 + "-pileup FILE\tCreate alignment file FILE in Pileup format\n"
1523 + "-pir FILE\tCreate alignment file FILE in PIR format.\n"
1524 + "-blc FILE\tCreate alignment file FILE in BLC format.\n"
1525 + "-json FILE\tCreate alignment file FILE in JSON format.\n"
1526 + "-jalview FILE\tCreate alignment file FILE in Jalview format.\n"
1527 + "-png FILE\tCreate PNG image FILE from alignment.\n"
1528 + "-svg FILE\tCreate SVG image FILE from alignment.\n"
1529 + "-html FILE\tCreate HTML file from alignment.\n"
1530 + "-biojsMSA FILE\tCreate BioJS MSA Viewer HTML file from alignment.\n"
1531 + "-imgMap FILE\tCreate HTML file FILE with image map of PNG image.\n"
1532 + "-eps FILE\tCreate EPS file FILE from alignment.\n"
1533 + "-questionnaire URL\tQueries the given URL for information about any Jalview user questionnaires.\n"
1534 + "-noquestionnaire\tTurn off questionnaire check.\n"
1535 + "-nonews\tTurn off check for Jalview news.\n"
1536 + "-nousagestats\tTurn off google analytics tracking for this session.\n"
1537 + "-sortbytree OR -nosortbytree\tEnable or disable sorting of the given alignment by the given tree\n"
1539 // "-setprop PROPERTY=VALUE\tSet the given Jalview property,
1540 // after all other properties files have been read\n\t
1541 // (quote the 'PROPERTY=VALUE' pair to ensure spaces are
1542 // passed in correctly)"
1543 + "-jabaws URL\tSpecify URL for Jabaws services (e.g. for a local installation).\n"
1544 + "-fetchfrom nickname\tQuery nickname for features for the alignments and display them.\n"
1545 + "-groovy FILE\tExecute groovy script in FILE, after all other arguments have been processed (if FILE is the text 'STDIN' then the file will be read from STDIN)\n"
1546 + "-jvmmempc=PERCENT\tOnly available with standalone executable jar or jalview.bin.Launcher. Limit maximum heap size (memory) to PERCENT% of total physical memory detected. This defaults to 90 if total physical memory can be detected. See https://www.jalview.org/help/html/memory.html for more details.\n"
1547 + "-jvmmemmax=MAXMEMORY\tOnly available with standalone executable jar or jalview.bin.Launcher. Limit maximum heap size (memory) to MAXMEMORY. MAXMEMORY can be specified in bytes, kilobytes(k), megabytes(m), gigabytes(g) or if you're lucky enough, terabytes(t). This defaults to 32g if total physical memory can be detected, or to 8g if total physical memory cannot be detected. See https://www.jalview.org/help/html/memory.html for more details.\n"
1548 + "\n~Read documentation in Application or visit https://www.jalview.org for description of Features and Annotations file~\n\n");
1552 private static void startUsageStats(final Desktop desktop)
1555 * start a User Config prompt asking if we can log usage statistics.
1557 PromptUserConfig prompter = new PromptUserConfig(Desktop.desktop,
1558 "USAGESTATS", "Jalview Usage Statistics",
1559 "Do you want to help make Jalview better by enabling "
1560 + "the collection of usage statistics with Google Analytics ?"
1561 + "\n\n(you can enable or disable usage tracking in the preferences)",
1568 "Initialising googletracker for usage stats.");
1569 Cache.initGoogleTracker();
1570 Console.debug("Tracking enabled.");
1577 Console.debug("Not enabling Google Tracking.");
1580 desktop.addDialogThread(prompter);
1584 * Locate the given string as a file and pass it to the groovy interpreter.
1586 * @param groovyscript
1587 * the script to execute
1588 * @param jalviewContext
1589 * the Jalview Desktop object passed in to the groovy binding as the
1592 protected void executeGroovyScript(String groovyscript, AlignFrame af)
1595 * for scripts contained in files
1602 if (groovyscript.trim().equals("STDIN"))
1604 // read from stdin into a tempfile and execute it
1607 tfile = File.createTempFile("jalview", "groovy");
1608 PrintWriter outfile = new PrintWriter(
1609 new OutputStreamWriter(new FileOutputStream(tfile)));
1610 BufferedReader br = new BufferedReader(
1611 new InputStreamReader(System.in));
1613 while ((line = br.readLine()) != null)
1615 outfile.write(line + "\n");
1621 } catch (Exception ex)
1623 System.err.println("Failed to read from STDIN into tempfile "
1624 + ((tfile == null) ? "(tempfile wasn't created)"
1625 : tfile.toString()));
1626 ex.printStackTrace();
1631 sfile = tfile.toURI().toURL();
1632 } catch (Exception x)
1635 "Unexpected Malformed URL Exception for temporary file created from STDIN: "
1637 x.printStackTrace();
1645 sfile = new URI(groovyscript).toURL();
1646 } catch (Exception x)
1648 tfile = new File(groovyscript);
1649 if (!tfile.exists())
1651 System.err.println("File '" + groovyscript + "' does not exist.");
1654 if (!tfile.canRead())
1656 System.err.println("File '" + groovyscript + "' cannot be read.");
1659 if (tfile.length() < 1)
1661 System.err.println("File '" + groovyscript + "' is empty.");
1666 sfile = tfile.getAbsoluteFile().toURI().toURL();
1667 } catch (Exception ex)
1669 System.err.println("Failed to create a file URL for "
1670 + tfile.getAbsoluteFile());
1677 Map<String, java.lang.Object> vbinding = new HashMap<>();
1678 vbinding.put("Jalview", this);
1681 vbinding.put("currentAlFrame", af);
1683 Binding gbinding = new Binding(vbinding);
1684 GroovyScriptEngine gse = new GroovyScriptEngine(new URL[] { sfile });
1685 gse.run(sfile.toString(), gbinding);
1686 if ("STDIN".equals(groovyscript))
1688 // delete temp file that we made -
1689 // only if it was successfully executed
1692 } catch (Exception e)
1694 System.err.println("Exception Whilst trying to execute file " + sfile
1695 + " as a groovy script.");
1696 e.printStackTrace(System.err);
1701 public static boolean isHeadlessMode()
1703 String isheadless = System.getProperty("java.awt.headless");
1704 if (isheadless != null && isheadless.equalsIgnoreCase("true"))
1711 public AlignFrame[] getAlignFrames()
1713 return desktop == null ? new AlignFrame[] { getCurrentAlignFrame() }
1714 : Desktop.getAlignFrames();
1719 * jalview.bin.Jalview.quit() will just run the non-GUI shutdownHook and exit
1723 // System.exit will run the shutdownHook first
1724 Jalview.exit("Quitting now. Bye!", 0);
1727 public static AlignFrame getCurrentAlignFrame()
1729 return Jalview.currentAlignFrame;
1732 public static void setCurrentAlignFrame(AlignFrame currentAlignFrame)
1734 Jalview.currentAlignFrame = currentAlignFrame;
1737 protected Commands getCommands()
1742 public static void exit(String message, int exitcode)
1744 if (Console.log == null)
1746 // Don't start the logger just to exit!
1747 if (message != null)
1751 System.out.println(message);
1755 System.err.println(message);
1761 Console.debug("Using Jalview.exit");
1762 if (message != null)
1766 Console.info(message);
1770 Console.error(message);
1776 System.exit(exitcode);
1781 * testoutput for string values
1783 protected static void testoutput(ArgParser ap, Arg a, String s1,
1786 BootstrapArgs bsa = ap.getBootstrapArgs();
1787 if (!bsa.getBoolean(Arg.TESTOUTPUT))
1789 if (!((s1 == null && s2 == null) || (s1 != null && s1.equals(s2))))
1791 Console.debug("testoutput with unmatching values '" + s1 + "' and '"
1792 + s2 + "' for arg " + a.argString());
1795 boolean isset = a.hasOption(Opt.BOOTSTRAP) ? bsa.contains(a)
1799 Console.warn("Arg '" + a.getName() + "' not set at all");
1802 testoutput(true, a, s1, s2);
1805 protected static void testoutput(BootstrapArgs bsa, Arg a, String s1,
1808 if (!bsa.getBoolean(Arg.TESTOUTPUT))
1810 if (!((s1 == null && s2 == null) || (s1 != null && s1.equals(s2))))
1812 Console.debug("testoutput with unmatching values '" + s1 + "' and '"
1813 + s2 + "' for arg " + a.argString());
1816 if (!a.hasOption(Opt.BOOTSTRAP))
1818 Console.error("Non-bootstrap Arg '" + a.getName()
1819 + "' given to testoutput(BootstrapArgs bsa, Arg a, String s1, String s2) with only BootstrapArgs");
1821 if (!bsa.contains(a))
1823 Console.warn("Arg '" + a.getName() + "' not set at all");
1826 testoutput(true, a, s1, s2);
1829 private static void testoutput(boolean yes, Arg a, String s1, String s2)
1831 if (yes && ((s1 == null && s2 == null)
1832 || (s1 != null && s1.equals(s2))))
1834 System.out.println("[TESTOUTPUT] arg " + a.argString() + "='" + s1
1840 * testoutput for boolean values
1842 protected static void testoutput(ArgParser ap, Arg a)
1846 BootstrapArgs bsa = ap.getBootstrapArgs();
1849 if (!bsa.getBoolean(Arg.TESTOUTPUT))
1851 boolean val = a.hasOption(Opt.BOOTSTRAP) ? bsa.getBoolean(a)
1853 boolean isset = a.hasOption(Opt.BOOTSTRAP) ? bsa.contains(a)
1857 Console.warn("Arg '" + a.getName() + "' not set at all");
1863 protected static void testoutput(BootstrapArgs bsa, Arg a)
1865 if (!bsa.getBoolean(Arg.TESTOUTPUT))
1867 if (!a.hasOption(Opt.BOOTSTRAP))
1869 Console.warn("Non-bootstrap Arg '" + a.getName()
1870 + "' given to testoutput(BootstrapArgs bsa, Arg a) with only BootstrapArgs");
1873 if (!bsa.contains(a))
1875 Console.warn("Arg '" + a.getName() + "' not set at all");
1878 testoutput(bsa.getBoolean(a), a);
1881 private static void testoutput(boolean yes, Arg a)
1883 System.out.println("[TESTOUTPUT] arg "
1884 + (yes ? a.argString() : a.negateArgString()) + " was set");
1887 private static boolean isHeadless(BootstrapArgs bootstrapArgs)
1889 if (bootstrapArgs == null)
1893 boolean isHeadless = false;
1894 if (bootstrapArgs.contains(Arg.GUI))
1896 isHeadless = !bootstrapArgs.getBoolean(Arg.GUI);
1898 else if (bootstrapArgs.contains(Arg.HEADLESS))
1900 isHeadless = bootstrapArgs.getBoolean(Arg.HEADLESS);
1902 else if (bootstrapArgs.argsHaveOption(Opt.OUTPUTFILE))