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.Arrays;
44 import java.util.HashMap;
45 import java.util.List;
46 import java.util.Locale;
48 import java.util.Properties;
49 import java.util.Vector;
50 import java.util.logging.ConsoleHandler;
51 import java.util.logging.Level;
52 import java.util.logging.Logger;
53 import java.util.stream.Collectors;
55 import javax.swing.JDialog;
56 import javax.swing.JFrame;
57 import javax.swing.JInternalFrame;
58 import javax.swing.JOptionPane;
59 import javax.swing.SwingUtilities;
60 import javax.swing.UIManager;
61 import javax.swing.UIManager.LookAndFeelInfo;
62 import javax.swing.UnsupportedLookAndFeelException;
64 import com.formdev.flatlaf.FlatLightLaf;
65 import com.formdev.flatlaf.themes.FlatMacLightLaf;
66 import com.formdev.flatlaf.util.SystemInfo;
67 import com.threerings.getdown.util.LaunchUtil;
69 //import edu.stanford.ejalbert.launching.IBrowserLaunching;
70 import groovy.lang.Binding;
71 import groovy.util.GroovyScriptEngine;
72 import jalview.bin.argparser.Arg;
73 import jalview.bin.argparser.Arg.Opt;
74 import jalview.bin.argparser.Arg.Type;
75 import jalview.bin.argparser.ArgParser;
76 import jalview.bin.argparser.BootstrapArgs;
77 import jalview.bin.groovy.JalviewObject;
78 import jalview.bin.groovy.JalviewObjectI;
79 import jalview.ext.so.SequenceOntology;
80 import jalview.gui.AlignFrame;
81 import jalview.gui.Desktop;
82 import jalview.gui.JvOptionPane;
83 import jalview.gui.PromptUserConfig;
84 import jalview.gui.QuitHandler;
85 import jalview.gui.QuitHandler.QResponse;
86 import jalview.gui.StructureViewerBase;
87 import jalview.io.AppletFormatAdapter;
88 import jalview.io.BioJsHTMLOutput;
89 import jalview.io.DataSourceType;
90 import jalview.io.FileFormat;
91 import jalview.io.FileFormatException;
92 import jalview.io.FileFormatI;
93 import jalview.io.FileFormats;
94 import jalview.io.FileLoader;
95 import jalview.io.HtmlSvgOutput;
96 import jalview.io.IdentifyFile;
97 import jalview.io.NewickFile;
98 import jalview.io.exceptions.ImageOutputException;
99 import jalview.io.gff.SequenceOntologyFactory;
100 import jalview.schemes.ColourSchemeI;
101 import jalview.schemes.ColourSchemeProperty;
102 import jalview.util.ChannelProperties;
103 import jalview.util.HttpUtils;
104 import jalview.util.IdUtils;
105 import jalview.util.IdUtils.IdType;
106 import jalview.util.LaunchUtils;
107 import jalview.util.MessageManager;
108 import jalview.util.Platform;
109 import jalview.ws.jws2.Jws2Discoverer;
112 * Main class for Jalview Application <br>
114 * start with: java -classpath "$PATH_TO_LIB$/*:$PATH_TO_CLASSES$" \
115 * jalview.bin.Jalview
117 * or on Windows: java -classpath "$PATH_TO_LIB$/*;$PATH_TO_CLASSES$" \
118 * jalview.bin.Jalview jalview.bin.Jalview
120 * (ensure -classpath arg is quoted to avoid shell expansion of '*' and do not
121 * embellish '*' to e.g. '*.jar')
124 * @version $Revision$
126 public class Jalview implements JalviewObjectI
130 Platform.getURLCommandArguments();
131 Platform.addJ2SDirectDatabaseCall("https://www.jalview.org");
132 Platform.addJ2SDirectDatabaseCall("http://www.jalview.org");
133 Platform.addJ2SDirectDatabaseCall("http://www.compbio.dundee.ac.uk");
134 Platform.addJ2SDirectDatabaseCall("https://www.compbio.dundee.ac.uk");
138 * singleton instance of this class
140 private static Jalview instance;
142 private Desktop desktop;
144 protected Commands cmds;
146 public AlignFrame currentAlignFrame = null;
148 private ArgParser argparser = null;
150 private BootstrapArgs bootstrapArgs = null;
152 private boolean QUIET = false;
154 public static boolean quiet()
156 return Jalview.getInstance() != null && Jalview.getInstance().QUIET;
161 if (!Platform.isJS())
168 // grab all the rights we can for the JVM
169 Policy.setPolicy(new Policy()
172 public PermissionCollection getPermissions(CodeSource codesource)
174 Permissions perms = new Permissions();
175 perms.add(new AllPermission());
180 public void refresh()
188 * keep track of feature fetching tasks.
196 * TODO: generalise to track all jalview events to orchestrate batch processing
200 private int queued = 0;
202 private int running = 0;
204 public FeatureFetcher()
209 public void addFetcher(final AlignFrame af,
210 final Vector<String> dasSources)
212 final long id = IdUtils.newId(IdType.PROGRESS);
214 final FeatureFetcher us = this;
215 new Thread(new Runnable()
227 af.setProgressBar(MessageManager
228 .getString("status.das_features_being_retrived"), id);
229 af.featureSettings_actionPerformed(null);
230 af.setProgressBar(null, id);
239 public synchronized boolean allFinished()
241 return queued == 0 && running == 0;
246 public static Jalview getInstance()
252 * main class for Jalview application
255 * open <em>filename</em>
257 public static void main(String[] args)
259 // setLogging(); // BH - for event debugging in JavaScript
260 instance = new Jalview();
261 instance.doMain(args);
264 private static void logClass(String name)
266 // BH - for event debugging in JavaScript
267 ConsoleHandler consoleHandler = new ConsoleHandler();
268 consoleHandler.setLevel(Level.ALL);
269 Logger logger = Logger.getLogger(name);
270 logger.setLevel(Level.ALL);
271 logger.addHandler(consoleHandler);
274 @SuppressWarnings("unused")
275 private static void setLogging()
283 Console.outPrintln("not in js");
286 // BH - for event debugging in JavaScript (Java mode only)
287 if (!Platform.isJS())
294 Logger.getLogger("").setLevel(Level.ALL);
295 logClass("java.awt.EventDispatchThread");
296 logClass("java.awt.EventQueue");
297 logClass("java.awt.Component");
298 logClass("java.awt.focus.Component");
299 logClass("java.awt.focus.DefaultKeyboardFocusManager");
307 void doMain(String[] args)
309 if (!Platform.isJS())
311 System.setSecurityManager(null);
318 if (args == null || args.length == 0 || (args.length == 1
319 && (args[0] == null || args[0].length() == 0)))
321 args = new String[] {};
324 // get args needed before proper ArgParser
325 bootstrapArgs = BootstrapArgs.getBootstrapArgs(args);
327 if (!Platform.isJS())
329 // are we being --quiet ?
330 if (bootstrapArgs.contains(Arg.QUIET))
333 OutputStream devNull = new OutputStream()
337 public void write(int b)
342 System.setOut(new PrintStream(devNull));
343 // redirecting stderr not working
344 if (bootstrapArgs.getList(Arg.QUIET).size() > 1)
346 System.setErr(new PrintStream(devNull));
350 if (bootstrapArgs.contains(Arg.HELP)
351 || bootstrapArgs.contains(Arg.VERSION))
357 // set individual session preferences
358 if (bootstrapArgs.contains(Arg.P))
360 for (String kev : bootstrapArgs.getValueList(Arg.P))
366 int equalsIndex = kev.indexOf(ArgParser.EQUALS);
367 if (equalsIndex > -1)
369 String key = kev.substring(0, equalsIndex);
370 String val = kev.substring(equalsIndex + 1);
371 Cache.setSessionProperty(key, val);
376 // Move any new getdown-launcher-new.jar into place over old
377 // getdown-launcher.jar
378 String appdirString = System.getProperty("getdownappdir");
379 if (appdirString != null && appdirString.length() > 0)
381 final File appdir = new File(appdirString);
388 LaunchUtil.upgradeGetdown(
389 new File(appdir, "getdown-launcher-old.jar"),
390 new File(appdir, "getdown-launcher.jar"),
391 new File(appdir, "getdown-launcher-new.jar"));
396 if (!quiet() || !bootstrapArgs.outputToStdout()
397 || bootstrapArgs.contains(Arg.VERSION))
400 "Java version: " + System.getProperty("java.version"));
401 Console.outPrintln("Java home: " + System.getProperty("java.home"));
402 Console.outPrintln("Java arch: " + System.getProperty("os.arch") + " "
403 + System.getProperty("os.name") + " "
404 + System.getProperty("os.version"));
406 String val = System.getProperty("sys.install4jVersion");
409 Console.outPrintln("Install4j version: " + val);
411 val = System.getProperty("installer_template_version");
414 Console.outPrintln("Install4j template version: " + val);
416 val = System.getProperty("launcher_version");
419 Console.outPrintln("Launcher version: " + val);
423 if (Platform.isLinux() && LaunchUtils.getJavaVersion() < 11)
425 System.setProperty("flatlaf.uiScale", "1");
428 // get bootstrap properties (mainly for the logger level)
429 Properties bootstrapProperties = Cache
430 .bootstrapProperties(bootstrapArgs.getValue(Arg.PROPS));
432 // report Jalview version
433 Cache.loadBuildProperties(
434 !quiet() || bootstrapArgs.contains(Arg.VERSION));
436 // stop now if only after --version
437 if (bootstrapArgs.contains(Arg.VERSION))
439 Jalview.exit(null, ExitCode.OK);
443 ArgsParser aparser = new ArgsParser(args);
446 boolean headless = false;
448 boolean headlessArg = false;
452 String logLevel = null;
453 if (bootstrapArgs.contains(Arg.TRACE))
457 else if (bootstrapArgs.contains(Arg.DEBUG))
459 logLevel = bootstrapArgs.getBoolean(Arg.DEBUG) ? "DEBUG" : "INFO";
461 if (logLevel == null && !(bootstrapProperties == null))
463 logLevel = bootstrapProperties.getProperty(Cache.JALVIEWLOGLEVEL);
465 Console.initLogger(logLevel);
466 } catch (NoClassDefFoundError error)
468 error.printStackTrace();
469 String message = "\nEssential logging libraries not found."
470 + "\nUse: java -classpath \"$PATH_TO_LIB$/*:$PATH_TO_CLASSES$\" jalview.bin.Jalview";
471 Jalview.exit(message, ExitCode.OK);
474 // register SIGTERM listener
475 Runtime.getRuntime().addShutdownHook(new Thread()
480 Console.debug("Running shutdown hook");
481 QuitHandler.startForceQuit();
482 boolean closeExternal = Cache
483 .getDefault("DEFAULT_CLOSE_EXTERNAL_VIEWERS", false)
484 || Cache.getDefault("ALWAYS_CLOSE_EXTERNAL_VIEWERS", false);
485 StructureViewerBase.setQuitClose(closeExternal);
488 for (JInternalFrame frame : Desktop.desktop.getAllFrames())
490 if (frame instanceof StructureViewerBase)
492 ((StructureViewerBase) frame).closeViewer(closeExternal);
497 if (QuitHandler.gotQuitResponse() == QResponse.CANCEL_QUIT)
499 // Got to here by a SIGTERM signal.
500 // Note we will not actually cancel the quit from here -- it's too
501 // late -- but we can wait for saving files and close external viewers
503 // Close viewers/Leave viewers open
504 Console.debug("Checking for saving files");
505 QuitHandler.getQuitResponse(false);
509 Console.debug("Nothing more to do");
511 Console.debug("Exiting, bye!");
512 // shutdownHook cannot be cancelled, JVM will now halt
516 String usrPropsFile = bootstrapArgs.contains(Arg.PROPS)
517 ? bootstrapArgs.getValue(Arg.PROPS)
518 : aparser.getValue("props");
519 // if usrPropsFile == null, loadProperties will use the Channel
521 Cache.loadProperties(usrPropsFile);
522 if (usrPropsFile != null)
525 "CMD [-props " + usrPropsFile + "] executed successfully!");
526 testoutput(bootstrapArgs, Arg.PROPS,
527 "test/jalview/bin/testProps.jvprops", usrPropsFile);
530 // --argfile=... -- OVERRIDES ALL NON-BOOTSTRAP ARGS
531 if (bootstrapArgs.contains(Arg.ARGFILE))
533 argparser = ArgParser.parseArgFiles(
534 bootstrapArgs.getValueList(Arg.ARGFILE),
535 bootstrapArgs.getBoolean(Arg.INITSUBSTITUTIONS),
540 argparser = new ArgParser(args,
541 bootstrapArgs.getBoolean(Arg.INITSUBSTITUTIONS),
545 if (!Platform.isJS())
552 if (bootstrapArgs.contains(Arg.HELP))
554 List<Map.Entry<Type, String>> helpArgs = bootstrapArgs
556 Console.outPrintln(Arg.usage(helpArgs.stream().map(e -> e.getKey())
557 .collect(Collectors.toList())));
558 Jalview.exit(null, ExitCode.OK);
560 if (aparser.contains("help") || aparser.contains("h"))
563 * Now using new usage statement. showUsage();
565 Console.outPrintln(Arg.usage());
566 Jalview.exit(null, ExitCode.OK);
570 headlessArg = bootstrapArgs.isHeadless();
573 System.setProperty("java.awt.headless", "true");
576 if (aparser.contains("nodisplay") || aparser.contains("nogui")
577 || aparser.contains("headless"))
579 System.setProperty("java.awt.headless", "true");
584 // allow https handshakes to download intermediate certs if necessary
585 System.setProperty("com.sun.security.enableAIAcaIssuers", "true");
587 String jabawsUrl = bootstrapArgs.getValue(Arg.JABAWS);
588 if (jabawsUrl == null)
589 jabawsUrl = aparser.getValue("jabaws");
590 if (jabawsUrl != null)
594 Jws2Discoverer.getDiscoverer().setPreferredUrl(jabawsUrl);
596 "CMD [-jabaws " + jabawsUrl + "] executed successfully!");
597 testoutput(bootstrapArgs, Arg.JABAWS,
598 "http://www.compbio.dundee.ac.uk/jabaws", jabawsUrl);
599 } catch (MalformedURLException e)
601 jalview.bin.Console.errPrintln(
602 "Invalid jabaws parameter: " + jabawsUrl + " ignored");
607 List<String> setprops = new ArrayList<>();
608 if (bootstrapArgs.contains(Arg.SETPROP))
610 setprops = bootstrapArgs.getValueList(Arg.SETPROP);
614 String sp = aparser.getValue("setprop");
618 sp = aparser.getValue("setprop");
621 for (String setprop : setprops)
623 int p = setprop.indexOf('=');
627 .println("Ignoring invalid setprop argument : " + setprop);
632 .errPrintln("Executing setprop argument: " + setprop);
635 Cache.setProperty(setprop.substring(0, p),
636 setprop.substring(p + 1));
638 // DISABLED FOR SECURITY REASONS
639 // TODO: add a property to allow properties to be overriden by cli args
640 // Cache.setProperty(setprop.substring(0,p), setprop.substring(p+1));
643 if (System.getProperty("java.awt.headless") != null
644 && System.getProperty("java.awt.headless").equals("true"))
648 System.setProperty("http.agent", HttpUtils.getUserAgent());
652 Console.initLogger();
653 } catch (NoClassDefFoundError error)
655 error.printStackTrace();
656 String message = "\nEssential logging libraries not found."
657 + "\nUse: java -classpath \"$PATH_TO_LIB$/*:$PATH_TO_CLASSES$\" jalview.bin.Jalview";
658 Jalview.exit(message, ExitCode.NO_LOGGING);
662 if (!(headless || headlessArg))
666 * configure 'full' SO model if preferences say to, else use the default (full
667 * SO) - as JS currently doesn't have OBO parsing, it must use 'Lite' version
669 boolean soDefault = !Platform.isJS();
670 if (Cache.getDefault("USE_FULL_SO", soDefault))
672 SequenceOntologyFactory.setInstance(new SequenceOntology());
675 if (!(headless || headlessArg))
677 Desktop.nosplash = "false".equals(bootstrapArgs.getValue(Arg.SPLASH))
678 || aparser.contains("nosplash")
679 || Cache.getDefault("SPLASH", "true").equals("false");
680 desktop = new Desktop();
681 desktop.setInBatchMode(true); // indicate we are starting up
687 JalviewTaskbar.setTaskbar(this);
688 } catch (Exception e)
690 Console.info("Cannot set Taskbar");
691 Console.error(e.getMessage());
692 // e.printStackTrace();
693 } catch (Throwable t)
695 Console.info("Cannot set Taskbar");
696 Console.error(t.getMessage());
697 // t.printStackTrace();
700 // set Proxy settings before all the internet calls
701 Cache.setProxyPropertiesFromPreferences();
703 desktop.setVisible(true);
705 if (!Platform.isJS())
714 * Check to see that the JVM version being run is suitable for the Java
715 * version this Jalview was compiled for. Popup a warning if not.
717 if (!LaunchUtils.checkJavaVersion())
719 Console.warn("The Java version being used (Java "
720 + LaunchUtils.getJavaVersion()
721 + ") may lead to problems. This installation of Jalview should be used with Java "
722 + LaunchUtils.getJavaCompileVersion() + ".");
725 .getBooleanUserPreference("IGNORE_JVM_WARNING_POPUP"))
728 MessageManager.getString("label.continue") };
729 JOptionPane.showOptionDialog(null,
730 MessageManager.formatMessage(
731 "warning.wrong_jvm_version_message",
732 LaunchUtils.getJavaVersion(),
733 LaunchUtils.getJavaCompileVersion()),
735 .getString("warning.wrong_jvm_version_title"),
736 JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE,
737 null, options, options[0]);
741 boolean webservicediscovery = bootstrapArgs
742 .getBoolean(Arg.WEBSERVICEDISCOVERY);
743 if (aparser.contains("nowebservicediscovery"))
744 webservicediscovery = false;
745 if (webservicediscovery)
747 desktop.startServiceDiscovery();
751 testoutput(argparser, Arg.WEBSERVICEDISCOVERY);
754 boolean usagestats = !bootstrapArgs.getBoolean(Arg.NOUSAGESTATS);
755 if (aparser.contains("nousagestats"))
759 startUsageStats(desktop);
760 testoutput(argparser, Arg.NOUSAGESTATS);
764 Console.outPrintln("CMD [-nousagestats] executed successfully!");
765 testoutput(argparser, Arg.NOUSAGESTATS);
768 boolean questionnaire = bootstrapArgs.getBoolean(Arg.QUESTIONNAIRE);
769 if (aparser.contains("noquestionnaire"))
770 questionnaire = false;
773 String url = aparser.getValue("questionnaire");
776 // Start the desktop questionnaire prompter with the specified
778 Console.debug("Starting questionnaire url at " + url);
779 desktop.checkForQuestionnaire(url);
780 Console.outPrintln("CMD questionnaire[-" + url
781 + "] executed successfully!");
785 if (Cache.getProperty("NOQUESTIONNAIRES") == null)
787 // Start the desktop questionnaire prompter with the specified
790 // "http://anaplog.compbio.dundee.ac.uk/cgi-bin/questionnaire.pl";
792 String defurl = "https://www.jalview.org/cgi-bin/questionnaire.pl";
794 "Starting questionnaire with default url: " + defurl);
795 desktop.checkForQuestionnaire(defurl);
802 "CMD [-noquestionnaire] executed successfully!");
803 testoutput(argparser, Arg.QUESTIONNAIRE);
806 if ((!aparser.contains("nonews")
807 && Cache.getProperty("NONEWS") == null
808 && !"false".equals(bootstrapArgs.getValue(Arg.NEWS)))
809 || "true".equals(bootstrapArgs.getValue(Arg.NEWS)))
811 desktop.checkForNews();
814 if (!aparser.contains("nohtmltemplates")
815 && Cache.getProperty("NOHTMLTEMPLATES") == null)
817 BioJsHTMLOutput.updateBioJS();
824 if (getArgParser().isMixedStyle())
826 String warning = MessageManager.formatMessage(
827 "warning.using_mixed_command_line_arguments",
828 getArgParser().getMixedExamples());
829 Console.warn(warning);
831 "Exiting due to mixed old and new command line arguments",
832 ExitCode.INVALID_ARGUMENT);
834 if (getArgParser().isOldStyle())
836 String warning = MessageManager
837 .getString("warning.using_old_command_line_arguments")
839 + "https://www.jalview.org/help/html/features/commandline.html";
840 Console.warn(warning);
845 // Run Commands from cli
846 boolean commandsSuccess = false;
847 if (!(argparser.isMixedStyle() || argparser.isOldStyle()))
849 cmds = new Commands(argparser, headlessArg);
851 commandsSuccess = cmds.argsWereParsed();
857 if (argparser.getBoolean(Arg.NOQUIT))
859 Console.warn("Completed " + Arg.HEADLESS.getName()
860 + " commands, but " + Arg.NOQUIT
861 + " is set so not quitting!");
865 Jalview.exit("Successfully completed commands in headless mode",
869 Console.info("Successfully completed commands");
875 Jalview.exit("Error when running Commands in headless mode",
876 ExitCode.ERROR_RUNNING_COMMANDS);
878 Console.warn("Error when running commands");
882 // Check if JVM and compile version might cause problems and log if it
884 if (headless && !Platform.isJS() && !LaunchUtils.checkJavaVersion())
886 Console.warn("The Java version being used (Java "
887 + LaunchUtils.getJavaVersion()
888 + ") may lead to problems. This installation of Jalview should be used with Java "
889 + LaunchUtils.getJavaCompileVersion() + ".");
892 String file = null, data = null;
894 FileFormatI format = null;
896 DataSourceType protocol = null;
898 FileLoader fileLoader = new FileLoader(!headless);
900 String groovyscript = null; // script to execute after all loading is
901 // completed one way or another
902 // extract groovy argument and execute if necessary
903 groovyscript = aparser.getValue("groovy", true);
904 file = aparser.getValue("open", true);
906 if (file == null && desktop == null && !commandsSuccess)
908 Jalview.exit("No files to open!", ExitCode.NO_FILES);
912 // Finally, deal with the remaining input data.
917 desktop.setProgressBar(
919 .getString("status.processing_commandline_args"),
920 progress = IdUtils.newId(IdType.PROGRESS));
922 Console.outPrintln("CMD [-open " + file + "] executed successfully!");
924 if (!Platform.isJS())
926 * ignore in JavaScript -- can't just file existence - could load it?
931 if (!HttpUtils.startsWithHttpOrHttps(file))
933 if (!(new File(file)).exists())
938 "Can't find file '" + file + "' in headless mode",
939 ExitCode.FILE_NOT_FOUND);
941 Console.warn("Can't find file'" + file + "'");
946 protocol = AppletFormatAdapter.checkProtocol(file);
950 format = new IdentifyFile().identify(file, protocol);
951 } catch (FileFormatException e1)
956 AlignFrame af = fileLoader.LoadFileWaitTillLoaded(file, protocol,
960 Console.outPrintln("error");
964 setCurrentAlignFrame(af);
965 data = aparser.getValue("colour", true);
968 data.replaceAll("%20", " ");
970 ColourSchemeI cs = ColourSchemeProperty.getColourScheme(
971 af.getViewport(), af.getViewport().getAlignment(), data);
976 "CMD [-colour " + data + "] executed successfully!");
981 // Must maintain ability to use the groups flag
982 data = aparser.getValue("groups", true);
985 af.parseFeaturesFile(data,
986 AppletFormatAdapter.checkProtocol(data));
987 // Console.outPrintln("Added " + data);
989 "CMD groups[-" + data + "] executed successfully!");
991 data = aparser.getValue("features", true);
994 af.parseFeaturesFile(data,
995 AppletFormatAdapter.checkProtocol(data));
996 // Console.outPrintln("Added " + data);
998 "CMD [-features " + data + "] executed successfully!");
1001 data = aparser.getValue("annotations", true);
1004 af.loadJalviewDataFile(data, null, null, null);
1005 // Console.outPrintln("Added " + data);
1007 "CMD [-annotations " + data + "] executed successfully!");
1009 // set or clear the sortbytree flag.
1010 if (aparser.contains("sortbytree"))
1012 af.getViewport().setSortByTree(true);
1013 if (af.getViewport().getSortByTree())
1015 Console.outPrintln("CMD [-sortbytree] executed successfully!");
1018 if (aparser.contains("no-annotation"))
1020 af.getViewport().setShowAnnotation(false);
1021 if (!af.getViewport().isShowAnnotation())
1023 Console.outPrintln("CMD no-annotation executed successfully!");
1026 if (aparser.contains("nosortbytree"))
1028 af.getViewport().setSortByTree(false);
1029 if (!af.getViewport().getSortByTree())
1032 "CMD [-nosortbytree] executed successfully!");
1035 data = aparser.getValue("tree", true);
1041 "CMD [-tree " + data + "] executed successfully!");
1042 NewickFile nf = new NewickFile(data,
1043 AppletFormatAdapter.checkProtocol(data));
1045 .setCurrentTree(af.showNewickTree(nf, data).getTree());
1046 } catch (IOException ex)
1048 jalview.bin.Console.errPrintln("Couldn't add tree " + data);
1049 ex.printStackTrace(System.err);
1053 if (groovyscript != null)
1055 // Execute the groovy script after we've done all the rendering stuff
1056 // and before any images or figures are generated.
1057 Console.outPrintln("Executing script " + groovyscript);
1058 executeGroovyScript(groovyscript, af);
1059 Console.outPrintln("CMD groovy[" + groovyscript
1060 + "] executed successfully!");
1061 groovyscript = null;
1063 String imageName = "unnamed.png";
1064 while (aparser.getSize() > 1)
1068 String outputFormat = aparser.nextValue();
1069 file = aparser.nextValue();
1071 if (outputFormat.equalsIgnoreCase("png"))
1073 Console.outPrintln("Creating PNG image: " + file);
1074 af.createPNG(new File(file));
1075 imageName = (new File(file)).getName();
1078 else if (outputFormat.equalsIgnoreCase("svg"))
1080 Console.outPrintln("Creating SVG image: " + file);
1081 File imageFile = new File(file);
1082 imageName = imageFile.getName();
1083 af.createSVG(imageFile);
1086 else if (outputFormat.equalsIgnoreCase("html"))
1088 File imageFile = new File(file);
1089 imageName = imageFile.getName();
1090 HtmlSvgOutput htmlSVG = new HtmlSvgOutput(af.alignPanel);
1092 Console.outPrintln("Creating HTML image: " + file);
1093 htmlSVG.exportHTML(file);
1096 else if (outputFormat.equalsIgnoreCase("biojsmsa"))
1100 jalview.bin.Console.errPrintln(
1101 "The output html file must not be null");
1106 BioJsHTMLOutput.refreshVersionInfo(
1107 BioJsHTMLOutput.BJS_TEMPLATES_LOCAL_DIRECTORY);
1108 } catch (URISyntaxException e)
1110 e.printStackTrace();
1112 BioJsHTMLOutput bjs = new BioJsHTMLOutput(af.alignPanel);
1114 "Creating BioJS MSA Viwer HTML file: " + file);
1115 bjs.exportHTML(file);
1118 else if (outputFormat.equalsIgnoreCase("imgMap"))
1120 Console.outPrintln("Creating image map: " + file);
1121 af.createImageMap(new File(file), imageName);
1124 else if (outputFormat.equalsIgnoreCase("eps"))
1126 File outputFile = new File(file);
1128 "Creating EPS file: " + outputFile.getAbsolutePath());
1129 af.createEPS(outputFile);
1133 FileFormatI outFormat = null;
1136 outFormat = FileFormats.getInstance().forName(outputFormat);
1137 } catch (Exception formatP)
1139 Console.outPrintln("Couldn't parse " + outFormat
1140 + " as a valid Jalview format string.");
1142 if (outFormat != null)
1144 if (!outFormat.isWritable())
1147 "This version of Jalview does not support alignment export as "
1152 af.saveAlignment(file, outFormat);
1153 if (af.isSaveAlignmentSuccessful())
1155 Console.outPrintln("Written alignment in "
1156 + outFormat.getName() + " format to " + file);
1160 Console.outPrintln("Error writing file " + file + " in "
1161 + outFormat.getName() + " format!!");
1165 } catch (ImageOutputException ioexc)
1168 "Unexpected error whilst exporting image to " + file);
1169 ioexc.printStackTrace();
1174 while (aparser.getSize() > 0)
1176 Console.outPrintln("Unknown arg: " + aparser.nextValue());
1181 AlignFrame startUpAlframe = null;
1182 // We'll only open the default file if the desktop is visible.
1184 // ////////////////////
1186 if (!Platform.isJS() && !headless && file == null
1187 && Cache.getDefault("SHOW_STARTUP_FILE", true)
1188 && !cmds.commandArgsProvided()
1189 && !bootstrapArgs.getBoolean(Arg.NOSTARTUPFILE))
1190 // don't open the startup file if command line args have been processed
1191 // (&& !Commands.commandArgsProvided())
1198 file = Cache.getDefault("STARTUP_FILE",
1199 Cache.getDefault("www.jalview.org", "https://www.jalview.org")
1200 + "/examples/exampleFile_2_7.jvp");
1201 if (file.equals("http://www.jalview.org/examples/exampleFile_2_3.jar")
1203 "http://www.jalview.org/examples/exampleFile_2_7.jar"))
1205 file.replace("http:", "https:");
1206 // hardwire upgrade of the startup file
1207 file.replace("_2_3", "_2_7");
1208 file.replace("2_7.jar", "2_7.jvp");
1209 // and remove the stale setting
1210 Cache.removeProperty("STARTUP_FILE");
1213 protocol = AppletFormatAdapter.checkProtocol(file);
1215 if (file.endsWith(".jar"))
1217 format = FileFormat.Jalview;
1223 format = new IdentifyFile().identify(file, protocol);
1224 } catch (FileFormatException e)
1230 startUpAlframe = fileLoader.LoadFileWaitTillLoaded(file, protocol,
1232 // don't ask to save when quitting if only the startup file has been
1234 Console.debug("Resetting up-to-date flag for startup file");
1235 startUpAlframe.getViewport().setSavedUpToDate(true);
1236 // extract groovy arguments before anything else.
1239 // Once all other stuff is done, execute any groovy scripts (in order)
1240 if (groovyscript != null)
1242 if (Cache.groovyJarsPresent())
1244 Console.outPrintln("Executing script " + groovyscript);
1245 executeGroovyScript(groovyscript, startUpAlframe);
1249 jalview.bin.Console.errPrintln(
1250 "Sorry. Groovy Support is not available, so ignoring the provided groovy script "
1254 // and finally, turn off batch mode indicator - if the desktop still exists
1255 if (desktop != null)
1259 desktop.setProgressBar(null, progress);
1261 desktop.setInBatchMode(false);
1267 private static void setLookAndFeel()
1269 if (!Platform.isJS())
1276 // property laf = "crossplatform", "system", "gtk", "metal", "nimbus",
1278 // If not set (or chosen laf fails), use the normal SystemLaF and if on
1280 // try Quaqua/Vaqua.
1281 String lafProp = System.getProperty("laf");
1282 String lafSetting = Cache.getDefault("PREFERRED_LAF", null);
1283 String laf = "none";
1284 if (lafProp != null)
1288 else if (lafSetting != null)
1292 boolean lafSet = false;
1295 case "crossplatform":
1296 lafSet = setCrossPlatformLookAndFeel();
1299 Console.error("Could not set requested laf=" + laf);
1303 lafSet = setSystemLookAndFeel();
1306 Console.error("Could not set requested laf=" + laf);
1310 lafSet = setGtkLookAndFeel();
1313 Console.error("Could not set requested laf=" + laf);
1317 lafSet = setMetalLookAndFeel();
1320 Console.error("Could not set requested laf=" + laf);
1324 lafSet = setNimbusLookAndFeel();
1327 Console.error("Could not set requested laf=" + laf);
1331 lafSet = setFlatLookAndFeel();
1334 Console.error("Could not set requested laf=" + laf);
1338 lafSet = setMacLookAndFeel();
1341 Console.error("Could not set requested laf=" + laf);
1347 Console.error("Requested laf=" + laf + " not implemented");
1351 // Flatlaf default for everyone!
1352 lafSet = setFlatLookAndFeel();
1355 setSystemLookAndFeel();
1357 if (Platform.isLinux())
1359 setLinuxLookAndFeel();
1361 if (Platform.isMac())
1363 setMacLookAndFeel();
1369 private static boolean setCrossPlatformLookAndFeel()
1371 boolean set = false;
1374 UIManager.setLookAndFeel(
1375 UIManager.getCrossPlatformLookAndFeelClassName());
1377 } catch (Exception ex)
1379 Console.error("Unexpected Look and Feel Exception");
1380 Console.error(ex.getMessage());
1381 Console.debug(Cache.getStackTraceString(ex));
1386 private static boolean setSystemLookAndFeel()
1388 boolean set = false;
1391 UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
1393 } catch (Exception ex)
1395 Console.error("Unexpected Look and Feel Exception");
1396 Console.error(ex.getMessage());
1397 Console.debug(Cache.getStackTraceString(ex));
1402 private static boolean setSpecificLookAndFeel(String name,
1403 String className, boolean nameStartsWith)
1405 boolean set = false;
1408 for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels())
1410 if (info.getName() != null && nameStartsWith
1411 ? info.getName().toLowerCase(Locale.ROOT)
1412 .startsWith(name.toLowerCase(Locale.ROOT))
1413 : info.getName().toLowerCase(Locale.ROOT)
1414 .equals(name.toLowerCase(Locale.ROOT)))
1416 className = info.getClassName();
1420 UIManager.setLookAndFeel(className);
1422 } catch (Exception ex)
1424 Console.error("Unexpected Look and Feel Exception");
1425 Console.error(ex.getMessage());
1426 Console.debug(Cache.getStackTraceString(ex));
1431 private static boolean setGtkLookAndFeel()
1433 return setSpecificLookAndFeel("gtk",
1434 "com.sun.java.swing.plaf.gtk.GTKLookAndFeel", true);
1437 private static boolean setMetalLookAndFeel()
1439 return setSpecificLookAndFeel("metal",
1440 "javax.swing.plaf.metal.MetalLookAndFeel", false);
1443 private static boolean setNimbusLookAndFeel()
1445 return setSpecificLookAndFeel("nimbus",
1446 "javax.swing.plaf.nimbus.NimbusLookAndFeel", false);
1449 private static boolean setFlatLookAndFeel()
1451 boolean set = false;
1452 if (SystemInfo.isMacOS)
1456 UIManager.setLookAndFeel(
1457 "com.formdev.flatlaf.themes.FlatMacLightLaf");
1459 Console.debug("Using FlatMacLightLaf");
1460 } catch (ClassNotFoundException | InstantiationException
1461 | IllegalAccessException | UnsupportedLookAndFeelException e)
1463 Console.debug("Exception loading FlatLightLaf", e);
1465 System.setProperty("apple.laf.useScreenMenuBar", "true");
1466 System.setProperty("apple.awt.application.name",
1467 ChannelProperties.getProperty("app_name"));
1468 System.setProperty("apple.awt.application.appearance", "system");
1469 if (SystemInfo.isMacFullWindowContentSupported
1470 && Desktop.desktop != null)
1472 Console.debug("Setting transparent title bar");
1473 Desktop.desktop.getRootPane()
1474 .putClientProperty("apple.awt.fullWindowContent", true);
1475 Desktop.desktop.getRootPane()
1476 .putClientProperty("apple.awt.transparentTitleBar", true);
1477 Desktop.desktop.getRootPane()
1478 .putClientProperty("apple.awt.fullscreenable", true);
1480 SwingUtilities.invokeLater(() -> {
1481 FlatMacLightLaf.setup();
1483 Console.debug("Using FlatMacLightLaf");
1490 UIManager.setLookAndFeel("com.formdev.flatlaf.FlatLightLaf");
1492 Console.debug("Using FlatLightLaf");
1493 } catch (ClassNotFoundException | InstantiationException
1494 | IllegalAccessException | UnsupportedLookAndFeelException e)
1496 Console.debug("Exception loading FlatLightLaf", e);
1498 // Windows specific properties here
1499 SwingUtilities.invokeLater(() -> {
1500 FlatLightLaf.setup();
1502 Console.debug("Using FlatLightLaf");
1505 else if (SystemInfo.isLinux)
1509 UIManager.setLookAndFeel("com.formdev.flatlaf.FlatLightLaf");
1511 Console.debug("Using FlatLightLaf");
1512 } catch (ClassNotFoundException | InstantiationException
1513 | IllegalAccessException | UnsupportedLookAndFeelException e)
1515 Console.debug("Exception loading FlatLightLaf", e);
1517 // enable custom window decorations
1518 JFrame.setDefaultLookAndFeelDecorated(true);
1519 JDialog.setDefaultLookAndFeelDecorated(true);
1520 SwingUtilities.invokeLater(() -> {
1521 FlatLightLaf.setup();
1523 Console.debug("Using FlatLightLaf");
1531 UIManager.setLookAndFeel("com.formdev.flatlaf.FlatLightLaf");
1533 Console.debug("Using FlatLightLaf");
1534 } catch (ClassNotFoundException | InstantiationException
1535 | IllegalAccessException | UnsupportedLookAndFeelException e)
1537 Console.debug("Exception loading FlatLightLaf", e);
1543 UIManager.put("TabbedPane.tabType", "card");
1544 UIManager.put("TabbedPane.showTabSeparators", true);
1545 UIManager.put("TabbedPane.showContentSeparator", true);
1546 // UIManager.put("TabbedPane.tabSeparatorsFullHeight", true);
1547 UIManager.put("TabbedPane.tabsOverlapBorder", true);
1548 UIManager.put("TabbedPane.hasFullBorder", true);
1549 UIManager.put("TabbedPane.tabLayoutPolicy", "scroll");
1550 UIManager.put("TabbedPane.scrollButtonsPolicy", "asNeeded");
1551 UIManager.put("TabbedPane.smoothScrolling", true);
1552 UIManager.put("TabbedPane.tabWidthMode", "compact");
1553 UIManager.put("TabbedPane.selectedBackground", Color.white);
1554 UIManager.put("TabbedPane.background", new Color(236, 236, 236));
1555 UIManager.put("TabbedPane.hoverColor", Color.lightGray);
1558 Desktop.setLiveDragMode(Cache.getDefault("FLAT_LIVE_DRAG_MODE", true));
1562 private static boolean setMacLookAndFeel()
1564 boolean set = false;
1565 System.setProperty("com.apple.mrj.application.apple.menu.about.name",
1566 ChannelProperties.getProperty("app_name"));
1567 System.setProperty("apple.laf.useScreenMenuBar", "true");
1569 * broken native LAFs on (ARM?) macbooks set = setQuaquaLookAndFeel(); if
1570 * ((!set) || !UIManager.getLookAndFeel().getClass().toString()
1571 * .toLowerCase(Locale.ROOT).contains("quaqua")) { set = setVaquaLookAndFeel();
1574 set = setFlatLookAndFeel();
1578 private static boolean setLinuxLookAndFeel()
1580 boolean set = false;
1581 set = setFlatLookAndFeel();
1583 set = setMetalLookAndFeel();
1584 // avoid GtkLookAndFeel -- not good results especially on HiDPI
1586 set = setNimbusLookAndFeel();
1591 * private static void showUsage() { jalview.bin.Console.outPrintln(
1592 * "Usage: jalview -open [FILE] [OUTPUT_FORMAT] [OUTPUT_FILE]\n\n" +
1593 * "-nodisplay\tRun Jalview without User Interface.\n" +
1594 * "-props FILE\tUse the given Jalview properties file instead of users default.\n"
1595 * + "-colour COLOURSCHEME\tThe colourscheme to be applied to the alignment\n" +
1596 * "-annotations FILE\tAdd precalculated annotations to the alignment.\n" +
1597 * "-tree FILE\tLoad the given newick format tree file onto the alignment\n" +
1598 * "-features FILE\tUse the given file to mark features on the alignment.\n" +
1599 * "-fasta FILE\tCreate alignment file FILE in Fasta format.\n" +
1600 * "-clustal FILE\tCreate alignment file FILE in Clustal format.\n" +
1601 * "-pfam FILE\tCreate alignment file FILE in PFAM format.\n" +
1602 * "-msf FILE\tCreate alignment file FILE in MSF format.\n" +
1603 * "-pileup FILE\tCreate alignment file FILE in Pileup format\n" +
1604 * "-pir FILE\tCreate alignment file FILE in PIR format.\n" +
1605 * "-blc FILE\tCreate alignment file FILE in BLC format.\n" +
1606 * "-json FILE\tCreate alignment file FILE in JSON format.\n" +
1607 * "-jalview FILE\tCreate alignment file FILE in Jalview format.\n" +
1608 * "-png FILE\tCreate PNG image FILE from alignment.\n" +
1609 * "-svg FILE\tCreate SVG image FILE from alignment.\n" +
1610 * "-html FILE\tCreate HTML file from alignment.\n" +
1611 * "-biojsMSA FILE\tCreate BioJS MSA Viewer HTML file from alignment.\n" +
1612 * "-imgMap FILE\tCreate HTML file FILE with image map of PNG image.\n" +
1613 * "-eps FILE\tCreate EPS file FILE from alignment.\n" +
1614 * "-questionnaire URL\tQueries the given URL for information about any Jalview user questionnaires.\n"
1615 * + "-noquestionnaire\tTurn off questionnaire check.\n" +
1616 * "-nonews\tTurn off check for Jalview news.\n" +
1617 * "-nousagestats\tTurn off analytics tracking for this session.\n" +
1618 * "-sortbytree OR -nosortbytree\tEnable or disable sorting of the given alignment by the given tree\n"
1619 * // + // "-setprop PROPERTY=VALUE\tSet the given Jalview property, // after
1620 * all other properties files have been read\n\t // (quote the 'PROPERTY=VALUE'
1621 * pair to ensure spaces are // passed in correctly)" +
1622 * "-jabaws URL\tSpecify URL for Jabaws services (e.g. for a local installation).\n"
1624 * "-fetchfrom nickname\tQuery nickname for features for the alignments and display them.\n"
1626 * "-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"
1628 * "-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"
1630 * "-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"
1632 * "\n~Read documentation in Application or visit https://www.jalview.org for description of Features and Annotations file~\n\n"
1636 private static void startUsageStats(final Desktop desktop)
1639 * start a User Config prompt asking if we can log usage statistics.
1641 PromptUserConfig prompter = new PromptUserConfig(Desktop.desktop,
1643 MessageManager.getString("prompt.analytics_title"),
1644 MessageManager.getString("prompt.analytics"), new Runnable()
1649 Console.debug("Initialising analytics for usage stats.");
1650 Cache.initAnalytics();
1651 Console.debug("Tracking enabled.");
1658 Console.debug("Not enabling analytics.");
1661 desktop.addDialogThread(prompter);
1665 * Locate the given string as a file and pass it to the groovy interpreter.
1667 * @param groovyscript
1668 * the script to execute
1669 * @param jalviewContext
1670 * the Jalview Desktop object passed in to the groovy binding as the
1673 protected void executeGroovyScript(String groovyscript, AlignFrame af)
1676 * for scripts contained in files
1683 if (groovyscript.trim().equals("STDIN"))
1685 // read from stdin into a tempfile and execute it
1688 tfile = File.createTempFile("jalview", "groovy");
1689 PrintWriter outfile = new PrintWriter(
1690 new OutputStreamWriter(new FileOutputStream(tfile)));
1691 BufferedReader br = new BufferedReader(
1692 new InputStreamReader(System.in));
1694 while ((line = br.readLine()) != null)
1696 outfile.write(line + "\n");
1702 } catch (Exception ex)
1705 .errPrintln("Failed to read from STDIN into tempfile "
1706 + ((tfile == null) ? "(tempfile wasn't created)"
1707 : tfile.toString()));
1708 ex.printStackTrace();
1713 sfile = tfile.toURI().toURL();
1714 } catch (Exception x)
1716 jalview.bin.Console.errPrintln(
1717 "Unexpected Malformed URL Exception for temporary file created from STDIN: "
1719 x.printStackTrace();
1727 sfile = new URI(groovyscript).toURL();
1728 } catch (Exception x)
1730 tfile = new File(groovyscript);
1731 if (!tfile.exists())
1733 jalview.bin.Console.errPrintln(
1734 "File '" + groovyscript + "' does not exist.");
1737 if (!tfile.canRead())
1739 jalview.bin.Console.errPrintln(
1740 "File '" + groovyscript + "' cannot be read.");
1743 if (tfile.length() < 1)
1746 .errPrintln("File '" + groovyscript + "' is empty.");
1751 sfile = tfile.getAbsoluteFile().toURI().toURL();
1752 } catch (Exception ex)
1754 jalview.bin.Console.errPrintln("Failed to create a file URL for "
1755 + tfile.getAbsoluteFile());
1762 JalviewObjectI j = new JalviewObject(this);
1763 Map<String, java.lang.Object> vbinding = new HashMap<>();
1764 vbinding.put(JalviewObjectI.jalviewObjectName, j);
1765 vbinding.put(JalviewObjectI.currentAlFrameName,
1766 af != null ? af : getCurrentAlignFrame());
1767 Binding gbinding = new Binding(vbinding);
1768 GroovyScriptEngine gse = new GroovyScriptEngine(new URL[] { sfile });
1769 gse.run(sfile.toString(), gbinding);
1770 if ("STDIN".equals(groovyscript))
1772 // delete temp file that we made -
1773 // only if it was successfully executed
1776 } catch (Exception e)
1779 .errPrintln("Exception Whilst trying to execute file " + sfile
1780 + " as a groovy script.");
1781 e.printStackTrace(System.err);
1785 public static boolean isHeadlessMode()
1787 String isheadless = System.getProperty("java.awt.headless");
1788 if (isheadless != null && isheadless.equalsIgnoreCase("true"))
1796 public AlignFrame[] getAlignFrames()
1798 return desktop == null ? new AlignFrame[] { getCurrentAlignFrame() }
1799 : Desktop.getDesktopAlignFrames();
1803 * jalview.bin.Jalview.quit() will just run the non-GUI shutdownHook and exit
1808 // System.exit will run the shutdownHook first
1809 Jalview.exit("Quitting now. Bye!", ExitCode.OK);
1813 public AlignFrame getCurrentAlignFrame()
1815 return currentAlignFrame;
1818 public void setCurrentAlignFrame(AlignFrame af)
1820 this.currentAlignFrame = af;
1823 public Commands getCommands()
1828 public static void exit(String message, ExitCode ec)
1830 int exitcode = ec == ExitCode.OK ? 0 : ec.ordinal() + 1;
1831 if (Console.log == null)
1833 // Don't start the logger just to exit!
1834 if (message != null)
1838 Console.outPrintln(message);
1842 jalview.bin.Console.errPrintln(message);
1848 Console.debug("Using Jalview.exit");
1849 if (message != null)
1853 Console.info(message);
1857 Console.error(message);
1863 System.exit(exitcode);
1867 public enum ExitCode
1869 // only add new ones to the end of the list (to preserve ordinal values)
1870 OK, FILE_NOT_FOUND, FILE_NOT_READABLE, NO_FILES, INVALID_FORMAT,
1871 INVALID_ARGUMENT, INVALID_VALUE, MIXED_CLI_ARGUMENTS,
1872 ERROR_RUNNING_COMMANDS, NO_LOGGING, GROOVY_ERROR;
1875 /******************************
1877 * TEST OUTPUT METHODS
1879 * these operate only when Arg.TESTOUTPUT has been passed, and variously check
1880 * if an expected value / arg was set and report it to the test framework.
1882 ******************************/
1884 * report string values parsed/processed during tests When the Bootstrap
1885 * argument Arg.TESTOUTPUT is present - reports on debug if given s1 is not
1886 * null and not equals s2, warns if given argument is not set, and calls
1887 * testoutput(true,a,s1,s2) to report processing progress.
1890 * - ArgParser handling parsing
1892 * - Arg currently being processed
1897 protected static void testoutput(ArgParser ap, Arg a, String s1,
1900 BootstrapArgs bsa = ap.getBootstrapArgs();
1901 if (!bsa.getBoolean(Arg.TESTOUTPUT))
1903 if (!((s1 == null && s2 == null) || (s1 != null && s1.equals(s2))))
1905 Console.debug("testoutput with unmatching values '" + s1 + "' and '"
1906 + s2 + "' for arg " + a.argString());
1909 boolean isset = a.hasOption(Opt.BOOTSTRAP) ? bsa.contains(a)
1913 Console.warn("Arg '" + a.getName() + "' not set at all");
1916 testoutput(true, a, s1, s2);
1920 * report values passed via bootstrap arguments
1922 * TODO: significant code duplication with testouput(Argparser...) - move it
1925 protected static void testoutput(BootstrapArgs bsa, Arg a, String s1,
1928 if (!bsa.getBoolean(Arg.TESTOUTPUT))
1930 if (!((s1 == null && s2 == null) || (s1 != null && s1.equals(s2))))
1932 Console.debug("testoutput with unmatching values '" + s1 + "' and '"
1933 + s2 + "' for arg " + a.argString());
1936 if (!a.hasOption(Opt.BOOTSTRAP))
1938 Console.error("Non-bootstrap Arg '" + a.getName()
1939 + "' given to testoutput(BootstrapArgs bsa, Arg a, String s1, String s2) with only BootstrapArgs");
1941 if (!bsa.contains(a))
1943 Console.warn("Arg '" + a.getName() + "' not set at all");
1946 testoutput(true, a, s1, s2);
1950 * conditionally (on @param yes) report that expected value s1 was set during
1951 * CommandsTest tests
1953 private static void testoutput(boolean yes, Arg a, String s1, String s2)
1955 if (yes && ((s1 == null && s2 == null)
1956 || (s1 != null && s1.equals(s2))))
1958 Console.outPrintln("[TESTOUTPUT] arg " + a.argString() + "='" + s1
1964 * testoutput for boolean and unary values
1966 protected static void testoutput(ArgParser ap, Arg a)
1970 BootstrapArgs bsa = ap.getBootstrapArgs();
1973 if (!bsa.getBoolean(Arg.TESTOUTPUT))
1975 boolean val = a.hasOption(Opt.BOOTSTRAP) ? bsa.getBoolean(a)
1977 boolean isset = a.hasOption(Opt.BOOTSTRAP) ? bsa.contains(a)
1981 Console.warn("Arg '" + a.getName() + "' not set at all");
1987 protected static void testoutput(BootstrapArgs bsa, Arg a)
1989 if (!bsa.getBoolean(Arg.TESTOUTPUT))
1991 if (!a.hasOption(Opt.BOOTSTRAP))
1993 Console.warn("Non-bootstrap Arg '" + a.getName()
1994 + "' given to testoutput(BootstrapArgs bsa, Arg a) with only BootstrapArgs");
1997 if (!bsa.contains(a))
1999 Console.warn("Arg '" + a.getName() + "' not set at all");
2002 testoutput(bsa.getBoolean(a), a);
2005 private static void testoutput(boolean yes, Arg a)
2007 String message = null;
2008 if (a.hasOption(Opt.BOOLEAN))
2010 message = (yes ? a.argString() : a.negateArgString()) + " was set";
2012 else if (a.hasOption(Opt.UNARY))
2014 message = a.argString() + (yes ? " was set" : " was not set");
2016 Console.outPrintln("[TESTOUTPUT] arg " + message);
2019 public ArgParser getArgParser()
2024 public BootstrapArgs getBootstrapArgs()
2026 return bootstrapArgs;
2029 public static boolean isBatchMode()
2031 return getInstance() != null && (getInstance().desktop == null
2032 || getInstance().desktop.isInBatchMode());
2036 * Warning about old or mixed command line arguments
2038 private void mixedCliWarning()
2040 Jalview j = Jalview.getInstance();
2041 boolean mixedStyle = j.getArgParser() != null
2042 && j.getArgParser().isMixedStyle();
2043 String title = MessageManager.getString("label.command_line_arguments");
2046 String warning = MessageManager.formatMessage(
2047 "warning.using_mixed_command_line_arguments",
2048 j.getArgParser().getMixedExamples());
2049 String quit = MessageManager.getString("action.quit");
2051 Desktop.instance.nonBlockingDialog(title, warning, null, quit,
2052 JvOptionPane.WARNING_MESSAGE, false, false, true, 30000);
2055 "Exiting due to mixed old and new command line arguments.",
2056 ExitCode.MIXED_CLI_ARGUMENTS);
2060 private void cliWarning()
2062 Jalview j = Jalview.getInstance();
2063 Commands c = j.getCommands();
2064 boolean oldStyle = j.getArgParser() != null
2065 && j.getArgParser().isOldStyle();
2066 String title = MessageManager.getString("label.command_line_arguments");
2069 String warning = MessageManager
2070 .getString("warning.using_old_command_line_arguments");
2071 String url = "<a href=\"https://www.jalview.org/help/html/features/commandline.html\">https://www.jalview.org/help/html/features/commandline.html</a>";
2072 if (Desktop.instance != null)
2074 String cont = MessageManager.getString("label.continue");
2076 Desktop.instance.nonBlockingDialog(title, warning, url, cont,
2077 JvOptionPane.WARNING_MESSAGE, false, true, true, 30000);
2080 if (j.getCommands() != null && j.getCommands().getErrors().size() > 0)
2082 if (Desktop.instance != null)
2084 String message = MessageManager
2085 .getString("warning.the_following_errors");
2086 String ok = MessageManager.getString("action.ok");
2088 List<String> errors = j.getCommands().getErrors();
2089 for (int i = 0; i < errors.size(); i++)
2091 shortest = Math.min(shortest, errors.get(i).length());
2093 Desktop.instance.nonBlockingDialog(
2094 Math.max(message.length(), Math.min(60, shortest)),
2095 Math.min(errors.size(), 20), title, message,
2096 j.getCommands().errorsToString(), ok,
2097 JvOptionPane.WARNING_MESSAGE, true, false, true, -1);
2103 * To be populated by Info={} hash set by instantiating JalviewJS
2105 private Map<String, String> j2sInfo = null;
2108 * The non-j2s_-prefixed parameters to store
2110 private final String[] j2sSavedKeys = { "main", "core", "width", "height",
2111 "serverURL", "j2sPath", "console" };
2114 * The prefix for non-named keys in the Info={} block
2116 private static final String j2sParameterPrefix = "j2s_";
2119 * The Info key name for namespacing (query string parameters, class and id
2122 private static final String j2sNamespaceKey = j2sParameterPrefix
2126 * Get a value passed in from the Info={} hash. key should NOT use the
2130 * key name without the j2s_ namespace in the Info={} hash.
2131 * @return value value from the Info={} hash.
2133 public String getJ2sInfoValue(String key)
2135 if (j2sInfo == null || key == null)
2139 String j2sKey = Arrays.asList(j2sSavedKeys).contains(key) ? key
2140 : j2sParameterPrefix + key;
2141 return j2sInfo.get(j2sKey);
2145 * Get and save parameters and values from the Info={} hash.
2147 public void setJ2sInfo()
2149 if (!Platform.isJS())
2153 j2sInfo = new HashMap<>();
2157 * @j2sNative if (J2S.thisApplet.__Info !== undefined) {
2159 * Object.entries(J2S.thisApplet.__Info).forEach( entry => {
2165 if (key != null && (key.startsWith(j2sParameterPrefix)
2166 || Arrays.asList(j2sSavedKeys).contains(key)))
2168 j2sInfo.put(key, val);
2170 if (key.equals(j2sNamespaceKey))
2172 setJ2sNamespace(val);
2185 * Namespace (if set) by JalviewJS
2187 private String j2sNamespace = null;
2189 private void setJ2sNamespace(String ns)
2191 if (!Platform.isJS())
2195 Console.outPrintln("j2sNamespace set to '" + ns + "'");
2199 public String getJ2sNamespace()
2201 return j2sNamespace;