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.bin.groovy.JalviewObject;
77 import jalview.bin.groovy.JalviewObjectI;
78 import jalview.ext.so.SequenceOntology;
79 import jalview.gui.AlignFrame;
80 import jalview.gui.Desktop;
81 import jalview.gui.JvOptionPane;
82 import jalview.gui.PromptUserConfig;
83 import jalview.gui.QuitHandler;
84 import jalview.gui.QuitHandler.QResponse;
85 import jalview.gui.StructureViewerBase;
86 import jalview.io.AppletFormatAdapter;
87 import jalview.io.BioJsHTMLOutput;
88 import jalview.io.DataSourceType;
89 import jalview.io.FileFormat;
90 import jalview.io.FileFormatException;
91 import jalview.io.FileFormatI;
92 import jalview.io.FileFormats;
93 import jalview.io.FileLoader;
94 import jalview.io.HtmlSvgOutput;
95 import jalview.io.IdentifyFile;
96 import jalview.io.NewickFile;
97 import jalview.io.exceptions.ImageOutputException;
98 import jalview.io.gff.SequenceOntologyFactory;
99 import jalview.schemes.ColourSchemeI;
100 import jalview.schemes.ColourSchemeProperty;
101 import jalview.util.ChannelProperties;
102 import jalview.util.HttpUtils;
103 import jalview.util.IdUtils;
104 import jalview.util.IdUtils.IdType;
105 import jalview.util.LaunchUtils;
106 import jalview.util.MessageManager;
107 import jalview.util.Platform;
108 import jalview.ws.jws2.Jws2Discoverer;
111 * Main class for Jalview Application <br>
113 * start with: java -classpath "$PATH_TO_LIB$/*:$PATH_TO_CLASSES$" \
114 * jalview.bin.Jalview
116 * or on Windows: java -classpath "$PATH_TO_LIB$/*;$PATH_TO_CLASSES$" \
117 * jalview.bin.Jalview jalview.bin.Jalview
119 * (ensure -classpath arg is quoted to avoid shell expansion of '*' and do not
120 * embellish '*' to e.g. '*.jar')
123 * @version $Revision$
125 public class Jalview implements JalviewObjectI
129 Platform.getURLCommandArguments();
130 Platform.addJ2SDirectDatabaseCall("https://www.jalview.org");
131 Platform.addJ2SDirectDatabaseCall("http://www.jalview.org");
132 Platform.addJ2SDirectDatabaseCall("http://www.compbio.dundee.ac.uk");
133 Platform.addJ2SDirectDatabaseCall("https://www.compbio.dundee.ac.uk");
137 * singleton instance of this class
139 private static Jalview instance;
141 private Desktop desktop;
143 protected Commands cmds;
145 public AlignFrame currentAlignFrame = null;
147 private ArgParser argparser = null;
149 private BootstrapArgs bootstrapArgs = null;
151 private boolean QUIET = false;
153 public static boolean quiet()
155 return Jalview.getInstance() != null && Jalview.getInstance().QUIET;
160 if (!Platform.isJS())
167 // grab all the rights we can for the JVM
168 Policy.setPolicy(new Policy()
171 public PermissionCollection getPermissions(CodeSource codesource)
173 Permissions perms = new Permissions();
174 perms.add(new AllPermission());
179 public void refresh()
187 * keep track of feature fetching tasks.
195 * TODO: generalise to track all jalview events to orchestrate batch processing
199 private int queued = 0;
201 private int running = 0;
203 public FeatureFetcher()
208 public void addFetcher(final AlignFrame af,
209 final Vector<String> dasSources)
211 final long id = IdUtils.newId(IdType.PROGRESS);
213 final FeatureFetcher us = this;
214 new Thread(new Runnable()
226 af.setProgressBar(MessageManager
227 .getString("status.das_features_being_retrived"), id);
228 af.featureSettings_actionPerformed(null);
229 af.setProgressBar(null, id);
238 public synchronized boolean allFinished()
240 return queued == 0 && running == 0;
245 public static Jalview getInstance()
251 * main class for Jalview application
254 * open <em>filename</em>
256 public static void main(String[] args)
258 // setLogging(); // BH - for event debugging in JavaScript
259 instance = new Jalview();
260 instance.doMain(args);
263 private static void logClass(String name)
265 // BH - for event debugging in JavaScript
266 ConsoleHandler consoleHandler = new ConsoleHandler();
267 consoleHandler.setLevel(Level.ALL);
268 Logger logger = Logger.getLogger(name);
269 logger.setLevel(Level.ALL);
270 logger.addHandler(consoleHandler);
273 @SuppressWarnings("unused")
274 private static void setLogging()
282 Console.outPrintln("not in js");
285 // BH - for event debugging in JavaScript (Java mode only)
286 if (!Platform.isJS())
293 Logger.getLogger("").setLevel(Level.ALL);
294 logClass("java.awt.EventDispatchThread");
295 logClass("java.awt.EventQueue");
296 logClass("java.awt.Component");
297 logClass("java.awt.focus.Component");
298 logClass("java.awt.focus.DefaultKeyboardFocusManager");
306 void doMain(String[] args)
308 if (!Platform.isJS())
310 System.setSecurityManager(null);
313 if (args == null || args.length == 0 || (args.length == 1
314 && (args[0] == null || args[0].length() == 0)))
316 args = new String[] {};
319 // get args needed before proper ArgParser
320 bootstrapArgs = BootstrapArgs.getBootstrapArgs(args);
322 if (!Platform.isJS())
324 // are we being --quiet ?
325 if (bootstrapArgs.contains(Arg.QUIET))
328 OutputStream devNull = new OutputStream()
332 public void write(int b)
337 System.setOut(new PrintStream(devNull));
338 // redirecting stderr not working
339 if (bootstrapArgs.getList(Arg.QUIET).size() > 1)
341 System.setErr(new PrintStream(devNull));
345 if (bootstrapArgs.contains(Arg.HELP)
346 || bootstrapArgs.contains(Arg.VERSION))
352 // set individual session preferences
353 if (bootstrapArgs.contains(Arg.P))
355 for (String kev : bootstrapArgs.getValueList(Arg.P))
361 int equalsIndex = kev.indexOf(ArgParser.EQUALS);
362 if (equalsIndex > -1)
364 String key = kev.substring(0, equalsIndex);
365 String val = kev.substring(equalsIndex + 1);
366 Cache.setSessionProperty(key, val);
371 // Move any new getdown-launcher-new.jar into place over old
372 // getdown-launcher.jar
373 String appdirString = System.getProperty("getdownappdir");
374 if (appdirString != null && appdirString.length() > 0)
376 final File appdir = new File(appdirString);
383 LaunchUtil.upgradeGetdown(
384 new File(appdir, "getdown-launcher-old.jar"),
385 new File(appdir, "getdown-launcher.jar"),
386 new File(appdir, "getdown-launcher-new.jar"));
391 if (!quiet() || !bootstrapArgs.outputToStdout()
392 || bootstrapArgs.contains(Arg.VERSION))
395 "Java version: " + System.getProperty("java.version"));
396 Console.outPrintln("Java home: " + System.getProperty("java.home"));
397 Console.outPrintln("Java arch: " + System.getProperty("os.arch") + " "
398 + System.getProperty("os.name") + " "
399 + System.getProperty("os.version"));
401 String val = System.getProperty("sys.install4jVersion");
404 Console.outPrintln("Install4j version: " + val);
406 val = System.getProperty("installer_template_version");
409 Console.outPrintln("Install4j template version: " + val);
411 val = System.getProperty("launcher_version");
414 Console.outPrintln("Launcher version: " + val);
418 if (Platform.isLinux() && LaunchUtils.getJavaVersion() < 11)
420 System.setProperty("flatlaf.uiScale", "1");
423 // get bootstrap properties (mainly for the logger level)
424 Properties bootstrapProperties = Cache
425 .bootstrapProperties(bootstrapArgs.getValue(Arg.PROPS));
427 // report Jalview version
428 Cache.loadBuildProperties(
429 !quiet() || bootstrapArgs.contains(Arg.VERSION));
431 // stop now if only after --version
432 if (bootstrapArgs.contains(Arg.VERSION))
434 Jalview.exit(null, ExitCode.OK);
438 ArgsParser aparser = new ArgsParser(args);
441 boolean headless = false;
443 boolean headlessArg = false;
447 String logLevel = null;
448 if (bootstrapArgs.contains(Arg.TRACE))
452 else if (bootstrapArgs.contains(Arg.DEBUG))
454 logLevel = bootstrapArgs.getBoolean(Arg.DEBUG) ? "DEBUG" : "INFO";
456 if (logLevel == null && !(bootstrapProperties == null))
458 logLevel = bootstrapProperties.getProperty(Cache.JALVIEWLOGLEVEL);
460 Console.initLogger(logLevel);
461 } catch (NoClassDefFoundError error)
463 error.printStackTrace();
464 String message = "\nEssential logging libraries not found."
465 + "\nUse: java -classpath \"$PATH_TO_LIB$/*:$PATH_TO_CLASSES$\" jalview.bin.Jalview";
466 Jalview.exit(message, ExitCode.OK);
469 // register SIGTERM listener
470 Runtime.getRuntime().addShutdownHook(new Thread()
475 Console.debug("Running shutdown hook");
476 QuitHandler.startForceQuit();
477 boolean closeExternal = Cache
478 .getDefault("DEFAULT_CLOSE_EXTERNAL_VIEWERS", false)
479 || Cache.getDefault("ALWAYS_CLOSE_EXTERNAL_VIEWERS", false);
480 StructureViewerBase.setQuitClose(closeExternal);
483 for (JInternalFrame frame : Desktop.desktop.getAllFrames())
485 if (frame instanceof StructureViewerBase)
487 ((StructureViewerBase) frame).closeViewer(closeExternal);
492 if (QuitHandler.gotQuitResponse() == QResponse.CANCEL_QUIT)
494 // Got to here by a SIGTERM signal.
495 // Note we will not actually cancel the quit from here -- it's too
496 // late -- but we can wait for saving files and close external viewers
498 // Close viewers/Leave viewers open
499 Console.debug("Checking for saving files");
500 QuitHandler.getQuitResponse(false);
504 Console.debug("Nothing more to do");
506 Console.debug("Exiting, bye!");
507 // shutdownHook cannot be cancelled, JVM will now halt
511 String usrPropsFile = bootstrapArgs.contains(Arg.PROPS)
512 ? bootstrapArgs.getValue(Arg.PROPS)
513 : aparser.getValue("props");
514 // if usrPropsFile == null, loadProperties will use the Channel
516 Cache.loadProperties(usrPropsFile);
517 if (usrPropsFile != null)
520 "CMD [-props " + usrPropsFile + "] executed successfully!");
521 testoutput(bootstrapArgs, Arg.PROPS,
522 "test/jalview/bin/testProps.jvprops", usrPropsFile);
525 // --argfile=... -- OVERRIDES ALL NON-BOOTSTRAP ARGS
526 if (bootstrapArgs.contains(Arg.ARGFILE))
528 argparser = ArgParser.parseArgFiles(
529 bootstrapArgs.getValueList(Arg.ARGFILE),
530 bootstrapArgs.getBoolean(Arg.INITSUBSTITUTIONS),
535 argparser = new ArgParser(args,
536 bootstrapArgs.getBoolean(Arg.INITSUBSTITUTIONS),
540 if (!Platform.isJS())
547 if (bootstrapArgs.contains(Arg.HELP))
549 List<Map.Entry<Type, String>> helpArgs = bootstrapArgs
551 Console.outPrintln(Arg.usage(helpArgs.stream().map(e -> e.getKey())
552 .collect(Collectors.toList())));
553 Jalview.exit(null, ExitCode.OK);
555 if (aparser.contains("help") || aparser.contains("h"))
558 * Now using new usage statement.
561 Console.outPrintln(Arg.usage());
562 Jalview.exit(null, ExitCode.OK);
566 headlessArg = bootstrapArgs.isHeadless();
569 System.setProperty("java.awt.headless", "true");
572 if (aparser.contains("nodisplay") || aparser.contains("nogui")
573 || aparser.contains("headless"))
575 System.setProperty("java.awt.headless", "true");
580 // allow https handshakes to download intermediate certs if necessary
581 System.setProperty("com.sun.security.enableAIAcaIssuers", "true");
583 String jabawsUrl = bootstrapArgs.getValue(Arg.JABAWS);
584 if (jabawsUrl == null)
585 jabawsUrl = aparser.getValue("jabaws");
586 if (jabawsUrl != null)
590 Jws2Discoverer.getDiscoverer().setPreferredUrl(jabawsUrl);
592 "CMD [-jabaws " + jabawsUrl + "] executed successfully!");
593 testoutput(bootstrapArgs, Arg.JABAWS,
594 "http://www.compbio.dundee.ac.uk/jabaws", jabawsUrl);
595 } catch (MalformedURLException e)
597 jalview.bin.Console.errPrintln(
598 "Invalid jabaws parameter: " + jabawsUrl + " ignored");
603 List<String> setprops = new ArrayList<>();
604 if (bootstrapArgs.contains(Arg.SETPROP))
606 setprops = bootstrapArgs.getValueList(Arg.SETPROP);
610 String sp = aparser.getValue("setprop");
614 sp = aparser.getValue("setprop");
617 for (String setprop : setprops)
619 int p = setprop.indexOf('=');
623 .println("Ignoring invalid setprop argument : " + setprop);
628 .errPrintln("Executing setprop argument: " + setprop);
631 Cache.setProperty(setprop.substring(0, p),
632 setprop.substring(p + 1));
634 // DISABLED FOR SECURITY REASONS
635 // TODO: add a property to allow properties to be overriden by cli args
636 // Cache.setProperty(setprop.substring(0,p), setprop.substring(p+1));
639 if (System.getProperty("java.awt.headless") != null
640 && System.getProperty("java.awt.headless").equals("true"))
644 System.setProperty("http.agent", HttpUtils.getUserAgent());
648 Console.initLogger();
649 } catch (NoClassDefFoundError error)
651 error.printStackTrace();
652 String message = "\nEssential logging libraries not found."
653 + "\nUse: java -classpath \"$PATH_TO_LIB$/*:$PATH_TO_CLASSES$\" jalview.bin.Jalview";
654 Jalview.exit(message, ExitCode.NO_LOGGING);
658 if (!(headless || headlessArg))
662 * configure 'full' SO model if preferences say to, else use the default (full SO)
663 * - as JS currently doesn't have OBO parsing, it must use 'Lite' version
665 boolean soDefault = !Platform.isJS();
666 if (Cache.getDefault("USE_FULL_SO", soDefault))
668 SequenceOntologyFactory.setInstance(new SequenceOntology());
671 if (!(headless || headlessArg))
673 Desktop.nosplash = "false".equals(bootstrapArgs.getValue(Arg.SPLASH))
674 || aparser.contains("nosplash")
675 || Cache.getDefault("SPLASH", "true").equals("false");
676 desktop = new Desktop();
677 desktop.setInBatchMode(true); // indicate we are starting up
683 JalviewTaskbar.setTaskbar(this);
684 } catch (Exception e)
686 Console.info("Cannot set Taskbar");
687 Console.error(e.getMessage());
688 // e.printStackTrace();
689 } catch (Throwable t)
691 Console.info("Cannot set Taskbar");
692 Console.error(t.getMessage());
693 // t.printStackTrace();
696 // set Proxy settings before all the internet calls
697 Cache.setProxyPropertiesFromPreferences();
699 desktop.setVisible(true);
701 if (!Platform.isJS())
710 * Check to see that the JVM version being run is suitable for the Java
711 * version this Jalview was compiled for. Popup a warning if not.
713 if (!LaunchUtils.checkJavaVersion())
715 Console.warn("The Java version being used (Java "
716 + LaunchUtils.getJavaVersion()
717 + ") may lead to problems. This installation of Jalview should be used with Java "
718 + LaunchUtils.getJavaCompileVersion() + ".");
721 .getBooleanUserPreference("IGNORE_JVM_WARNING_POPUP"))
724 MessageManager.getString("label.continue") };
725 JOptionPane.showOptionDialog(null,
726 MessageManager.formatMessage(
727 "warning.wrong_jvm_version_message",
728 LaunchUtils.getJavaVersion(),
729 LaunchUtils.getJavaCompileVersion()),
731 .getString("warning.wrong_jvm_version_title"),
732 JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE,
733 null, options, options[0]);
737 boolean webservicediscovery = bootstrapArgs
738 .getBoolean(Arg.WEBSERVICEDISCOVERY);
739 if (aparser.contains("nowebservicediscovery"))
740 webservicediscovery = false;
741 if (webservicediscovery)
743 desktop.startServiceDiscovery();
747 testoutput(argparser, Arg.WEBSERVICEDISCOVERY);
750 boolean usagestats = !bootstrapArgs.getBoolean(Arg.NOUSAGESTATS);
751 if (aparser.contains("nousagestats"))
755 startUsageStats(desktop);
756 testoutput(argparser, Arg.NOUSAGESTATS);
760 Console.outPrintln("CMD [-nousagestats] executed successfully!");
761 testoutput(argparser, Arg.NOUSAGESTATS);
764 boolean questionnaire = bootstrapArgs.getBoolean(Arg.QUESTIONNAIRE);
765 if (aparser.contains("noquestionnaire"))
766 questionnaire = false;
769 String url = aparser.getValue("questionnaire");
772 // Start the desktop questionnaire prompter with the specified
774 Console.debug("Starting questionnaire url at " + url);
775 desktop.checkForQuestionnaire(url);
776 Console.outPrintln("CMD questionnaire[-" + url
777 + "] executed successfully!");
781 if (Cache.getProperty("NOQUESTIONNAIRES") == null)
783 // Start the desktop questionnaire prompter with the specified
786 // "http://anaplog.compbio.dundee.ac.uk/cgi-bin/questionnaire.pl";
788 String defurl = "https://www.jalview.org/cgi-bin/questionnaire.pl";
790 "Starting questionnaire with default url: " + defurl);
791 desktop.checkForQuestionnaire(defurl);
798 "CMD [-noquestionnaire] executed successfully!");
799 testoutput(argparser, Arg.QUESTIONNAIRE);
802 if ((!aparser.contains("nonews")
803 && Cache.getProperty("NONEWS") == null
804 && !"false".equals(bootstrapArgs.getValue(Arg.NEWS)))
805 || "true".equals(bootstrapArgs.getValue(Arg.NEWS)))
807 desktop.checkForNews();
810 if (!aparser.contains("nohtmltemplates")
811 && Cache.getProperty("NOHTMLTEMPLATES") == null)
813 BioJsHTMLOutput.updateBioJS();
820 if (getArgParser().isMixedStyle())
822 String warning = MessageManager.formatMessage(
823 "warning.using_mixed_command_line_arguments",
824 getArgParser().getMixedExamples());
825 Console.warn(warning);
827 "Exiting due to mixed old and new command line arguments",
828 ExitCode.INVALID_ARGUMENT);
830 if (getArgParser().isOldStyle())
832 String warning = MessageManager
833 .getString("warning.using_old_command_line_arguments")
835 + "https://www.jalview.org/help/html/features/commandline.html";
836 Console.warn(warning);
841 // Run Commands from cli
842 boolean commandsSuccess = false;
843 if (!(argparser.isMixedStyle() || argparser.isOldStyle()))
845 cmds = new Commands(argparser, headlessArg);
847 commandsSuccess = cmds.argsWereParsed();
853 if (argparser.getBoolean(Arg.NOQUIT))
855 Console.warn("Completed " + Arg.HEADLESS.getName()
856 + " commands, but " + Arg.NOQUIT
857 + " is set so not quitting!");
861 Jalview.exit("Successfully completed commands in headless mode",
865 Console.info("Successfully completed commands");
871 Jalview.exit("Error when running Commands in headless mode",
872 ExitCode.ERROR_RUNNING_COMMANDS);
874 Console.warn("Error when running commands");
878 // Check if JVM and compile version might cause problems and log if it
880 if (headless && !Platform.isJS() && !LaunchUtils.checkJavaVersion())
882 Console.warn("The Java version being used (Java "
883 + LaunchUtils.getJavaVersion()
884 + ") may lead to problems. This installation of Jalview should be used with Java "
885 + LaunchUtils.getJavaCompileVersion() + ".");
888 String file = null, data = null;
890 FileFormatI format = null;
892 DataSourceType protocol = null;
894 FileLoader fileLoader = new FileLoader(!headless);
896 String groovyscript = null; // script to execute after all loading is
897 // completed one way or another
898 // extract groovy argument and execute if necessary
899 groovyscript = aparser.getValue("groovy", true);
900 file = aparser.getValue("open", true);
902 if (file == null && desktop == null && !commandsSuccess)
904 Jalview.exit("No files to open!", ExitCode.NO_FILES);
908 // Finally, deal with the remaining input data.
913 desktop.setProgressBar(
915 .getString("status.processing_commandline_args"),
916 progress = IdUtils.newId(IdType.PROGRESS));
918 Console.outPrintln("CMD [-open " + file + "] executed successfully!");
920 if (!Platform.isJS())
922 * ignore in JavaScript -- can't just file existence - could load it?
927 if (!HttpUtils.startsWithHttpOrHttps(file))
929 if (!(new File(file)).exists())
934 "Can't find file '" + file + "' in headless mode",
935 ExitCode.FILE_NOT_FOUND);
937 Console.warn("Can't find file'" + file + "'");
942 protocol = AppletFormatAdapter.checkProtocol(file);
946 format = new IdentifyFile().identify(file, protocol);
947 } catch (FileFormatException e1)
952 AlignFrame af = fileLoader.LoadFileWaitTillLoaded(file, protocol,
956 Console.outPrintln("error");
960 setCurrentAlignFrame(af);
961 data = aparser.getValue("colour", true);
964 data.replaceAll("%20", " ");
966 ColourSchemeI cs = ColourSchemeProperty.getColourScheme(
967 af.getViewport(), af.getViewport().getAlignment(), data);
972 "CMD [-colour " + data + "] executed successfully!");
977 // Must maintain ability to use the groups flag
978 data = aparser.getValue("groups", true);
981 af.parseFeaturesFile(data,
982 AppletFormatAdapter.checkProtocol(data));
983 // Console.outPrintln("Added " + data);
985 "CMD groups[-" + data + "] executed successfully!");
987 data = aparser.getValue("features", true);
990 af.parseFeaturesFile(data,
991 AppletFormatAdapter.checkProtocol(data));
992 // Console.outPrintln("Added " + data);
994 "CMD [-features " + data + "] executed successfully!");
997 data = aparser.getValue("annotations", true);
1000 af.loadJalviewDataFile(data, null, null, null);
1001 // Console.outPrintln("Added " + data);
1003 "CMD [-annotations " + data + "] executed successfully!");
1005 // set or clear the sortbytree flag.
1006 if (aparser.contains("sortbytree"))
1008 af.getViewport().setSortByTree(true);
1009 if (af.getViewport().getSortByTree())
1011 Console.outPrintln("CMD [-sortbytree] executed successfully!");
1014 if (aparser.contains("no-annotation"))
1016 af.getViewport().setShowAnnotation(false);
1017 if (!af.getViewport().isShowAnnotation())
1019 Console.outPrintln("CMD no-annotation executed successfully!");
1022 if (aparser.contains("nosortbytree"))
1024 af.getViewport().setSortByTree(false);
1025 if (!af.getViewport().getSortByTree())
1028 "CMD [-nosortbytree] executed successfully!");
1031 data = aparser.getValue("tree", true);
1037 "CMD [-tree " + data + "] executed successfully!");
1038 NewickFile nf = new NewickFile(data,
1039 AppletFormatAdapter.checkProtocol(data));
1041 .setCurrentTree(af.showNewickTree(nf, data).getTree());
1042 } catch (IOException ex)
1044 jalview.bin.Console.errPrintln("Couldn't add tree " + data);
1045 ex.printStackTrace(System.err);
1049 if (groovyscript != null)
1051 // Execute the groovy script after we've done all the rendering stuff
1052 // and before any images or figures are generated.
1053 Console.outPrintln("Executing script " + groovyscript);
1054 executeGroovyScript(groovyscript, af);
1055 Console.outPrintln("CMD groovy[" + groovyscript
1056 + "] executed successfully!");
1057 groovyscript = null;
1059 String imageName = "unnamed.png";
1060 while (aparser.getSize() > 1)
1064 String outputFormat = aparser.nextValue();
1065 file = aparser.nextValue();
1067 if (outputFormat.equalsIgnoreCase("png"))
1069 Console.outPrintln("Creating PNG image: " + file);
1070 af.createPNG(new File(file));
1071 imageName = (new File(file)).getName();
1074 else if (outputFormat.equalsIgnoreCase("svg"))
1076 Console.outPrintln("Creating SVG image: " + file);
1077 File imageFile = new File(file);
1078 imageName = imageFile.getName();
1079 af.createSVG(imageFile);
1082 else if (outputFormat.equalsIgnoreCase("html"))
1084 File imageFile = new File(file);
1085 imageName = imageFile.getName();
1086 HtmlSvgOutput htmlSVG = new HtmlSvgOutput(af.alignPanel);
1088 Console.outPrintln("Creating HTML image: " + file);
1089 htmlSVG.exportHTML(file);
1092 else if (outputFormat.equalsIgnoreCase("biojsmsa"))
1096 jalview.bin.Console.errPrintln(
1097 "The output html file must not be null");
1102 BioJsHTMLOutput.refreshVersionInfo(
1103 BioJsHTMLOutput.BJS_TEMPLATES_LOCAL_DIRECTORY);
1104 } catch (URISyntaxException e)
1106 e.printStackTrace();
1108 BioJsHTMLOutput bjs = new BioJsHTMLOutput(af.alignPanel);
1110 "Creating BioJS MSA Viwer HTML file: " + file);
1111 bjs.exportHTML(file);
1114 else if (outputFormat.equalsIgnoreCase("imgMap"))
1116 Console.outPrintln("Creating image map: " + file);
1117 af.createImageMap(new File(file), imageName);
1120 else if (outputFormat.equalsIgnoreCase("eps"))
1122 File outputFile = new File(file);
1124 "Creating EPS file: " + outputFile.getAbsolutePath());
1125 af.createEPS(outputFile);
1129 FileFormatI outFormat = null;
1132 outFormat = FileFormats.getInstance().forName(outputFormat);
1133 } catch (Exception formatP)
1135 Console.outPrintln("Couldn't parse " + outFormat
1136 + " as a valid Jalview format string.");
1138 if (outFormat != null)
1140 if (!outFormat.isWritable())
1143 "This version of Jalview does not support alignment export as "
1148 af.saveAlignment(file, outFormat);
1149 if (af.isSaveAlignmentSuccessful())
1151 Console.outPrintln("Written alignment in "
1152 + outFormat.getName() + " format to " + file);
1156 Console.outPrintln("Error writing file " + file + " in "
1157 + outFormat.getName() + " format!!");
1161 } catch (ImageOutputException ioexc)
1164 "Unexpected error whilst exporting image to " + file);
1165 ioexc.printStackTrace();
1170 while (aparser.getSize() > 0)
1172 Console.outPrintln("Unknown arg: " + aparser.nextValue());
1177 AlignFrame startUpAlframe = null;
1178 // We'll only open the default file if the desktop is visible.
1180 // ////////////////////
1182 if (!Platform.isJS() && !headless && file == null
1183 && Cache.getDefault("SHOW_STARTUP_FILE", true)
1184 && !cmds.commandArgsProvided()
1185 && !bootstrapArgs.getBoolean(Arg.NOSTARTUPFILE))
1186 // don't open the startup file if command line args have been processed
1187 // (&& !Commands.commandArgsProvided())
1194 file = Cache.getDefault("STARTUP_FILE",
1195 Cache.getDefault("www.jalview.org", "https://www.jalview.org")
1196 + "/examples/exampleFile_2_7.jvp");
1197 if (file.equals("http://www.jalview.org/examples/exampleFile_2_3.jar")
1199 "http://www.jalview.org/examples/exampleFile_2_7.jar"))
1201 file.replace("http:", "https:");
1202 // hardwire upgrade of the startup file
1203 file.replace("_2_3", "_2_7");
1204 file.replace("2_7.jar", "2_7.jvp");
1205 // and remove the stale setting
1206 Cache.removeProperty("STARTUP_FILE");
1209 protocol = AppletFormatAdapter.checkProtocol(file);
1211 if (file.endsWith(".jar"))
1213 format = FileFormat.Jalview;
1219 format = new IdentifyFile().identify(file, protocol);
1220 } catch (FileFormatException e)
1226 startUpAlframe = fileLoader.LoadFileWaitTillLoaded(file, protocol,
1228 // don't ask to save when quitting if only the startup file has been
1230 Console.debug("Resetting up-to-date flag for startup file");
1231 startUpAlframe.getViewport().setSavedUpToDate(true);
1232 // extract groovy arguments before anything else.
1235 // Once all other stuff is done, execute any groovy scripts (in order)
1236 if (groovyscript != null)
1238 if (Cache.groovyJarsPresent())
1240 Console.outPrintln("Executing script " + groovyscript);
1241 executeGroovyScript(groovyscript, startUpAlframe);
1245 jalview.bin.Console.errPrintln(
1246 "Sorry. Groovy Support is not available, so ignoring the provided groovy script "
1250 // and finally, turn off batch mode indicator - if the desktop still exists
1251 if (desktop != null)
1255 desktop.setProgressBar(null, progress);
1257 desktop.setInBatchMode(false);
1263 private static void setLookAndFeel()
1265 if (!Platform.isJS())
1272 // property laf = "crossplatform", "system", "gtk", "metal", "nimbus",
1274 // If not set (or chosen laf fails), use the normal SystemLaF and if on
1276 // try Quaqua/Vaqua.
1277 String lafProp = System.getProperty("laf");
1278 String lafSetting = Cache.getDefault("PREFERRED_LAF", null);
1279 String laf = "none";
1280 if (lafProp != null)
1284 else if (lafSetting != null)
1288 boolean lafSet = false;
1291 case "crossplatform":
1292 lafSet = setCrossPlatformLookAndFeel();
1295 Console.error("Could not set requested laf=" + laf);
1299 lafSet = setSystemLookAndFeel();
1302 Console.error("Could not set requested laf=" + laf);
1306 lafSet = setGtkLookAndFeel();
1309 Console.error("Could not set requested laf=" + laf);
1313 lafSet = setMetalLookAndFeel();
1316 Console.error("Could not set requested laf=" + laf);
1320 lafSet = setNimbusLookAndFeel();
1323 Console.error("Could not set requested laf=" + laf);
1327 lafSet = setFlatLookAndFeel();
1330 Console.error("Could not set requested laf=" + laf);
1334 lafSet = setMacLookAndFeel();
1337 Console.error("Could not set requested laf=" + laf);
1343 Console.error("Requested laf=" + laf + " not implemented");
1347 // Flatlaf default for everyone!
1348 lafSet = setFlatLookAndFeel();
1351 setSystemLookAndFeel();
1353 if (Platform.isLinux())
1355 setLinuxLookAndFeel();
1357 if (Platform.isMac())
1359 setMacLookAndFeel();
1365 private static boolean setCrossPlatformLookAndFeel()
1367 boolean set = false;
1370 UIManager.setLookAndFeel(
1371 UIManager.getCrossPlatformLookAndFeelClassName());
1373 } catch (Exception ex)
1375 Console.error("Unexpected Look and Feel Exception");
1376 Console.error(ex.getMessage());
1377 Console.debug(Cache.getStackTraceString(ex));
1382 private static boolean setSystemLookAndFeel()
1384 boolean set = false;
1387 UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
1389 } catch (Exception ex)
1391 Console.error("Unexpected Look and Feel Exception");
1392 Console.error(ex.getMessage());
1393 Console.debug(Cache.getStackTraceString(ex));
1398 private static boolean setSpecificLookAndFeel(String name,
1399 String className, boolean nameStartsWith)
1401 boolean set = false;
1404 for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels())
1406 if (info.getName() != null && nameStartsWith
1407 ? info.getName().toLowerCase(Locale.ROOT)
1408 .startsWith(name.toLowerCase(Locale.ROOT))
1409 : info.getName().toLowerCase(Locale.ROOT)
1410 .equals(name.toLowerCase(Locale.ROOT)))
1412 className = info.getClassName();
1416 UIManager.setLookAndFeel(className);
1418 } catch (Exception ex)
1420 Console.error("Unexpected Look and Feel Exception");
1421 Console.error(ex.getMessage());
1422 Console.debug(Cache.getStackTraceString(ex));
1427 private static boolean setGtkLookAndFeel()
1429 return setSpecificLookAndFeel("gtk",
1430 "com.sun.java.swing.plaf.gtk.GTKLookAndFeel", true);
1433 private static boolean setMetalLookAndFeel()
1435 return setSpecificLookAndFeel("metal",
1436 "javax.swing.plaf.metal.MetalLookAndFeel", false);
1439 private static boolean setNimbusLookAndFeel()
1441 return setSpecificLookAndFeel("nimbus",
1442 "javax.swing.plaf.nimbus.NimbusLookAndFeel", false);
1445 private static boolean setFlatLookAndFeel()
1447 boolean set = false;
1448 if (SystemInfo.isMacOS)
1452 UIManager.setLookAndFeel(
1453 "com.formdev.flatlaf.themes.FlatMacLightLaf");
1455 Console.debug("Using FlatMacLightLaf");
1456 } catch (ClassNotFoundException | InstantiationException
1457 | IllegalAccessException | UnsupportedLookAndFeelException e)
1459 Console.debug("Exception loading FlatLightLaf", e);
1461 System.setProperty("apple.laf.useScreenMenuBar", "true");
1462 System.setProperty("apple.awt.application.name",
1463 ChannelProperties.getProperty("app_name"));
1464 System.setProperty("apple.awt.application.appearance", "system");
1465 if (SystemInfo.isMacFullWindowContentSupported
1466 && Desktop.desktop != null)
1468 Console.debug("Setting transparent title bar");
1469 Desktop.desktop.getRootPane()
1470 .putClientProperty("apple.awt.fullWindowContent", true);
1471 Desktop.desktop.getRootPane()
1472 .putClientProperty("apple.awt.transparentTitleBar", true);
1473 Desktop.desktop.getRootPane()
1474 .putClientProperty("apple.awt.fullscreenable", true);
1476 SwingUtilities.invokeLater(() -> {
1477 FlatMacLightLaf.setup();
1479 Console.debug("Using FlatMacLightLaf");
1486 UIManager.setLookAndFeel("com.formdev.flatlaf.FlatLightLaf");
1488 Console.debug("Using FlatLightLaf");
1489 } catch (ClassNotFoundException | InstantiationException
1490 | IllegalAccessException | UnsupportedLookAndFeelException e)
1492 Console.debug("Exception loading FlatLightLaf", e);
1494 // Windows specific properties here
1495 SwingUtilities.invokeLater(() -> {
1496 FlatLightLaf.setup();
1498 Console.debug("Using FlatLightLaf");
1501 else if (SystemInfo.isLinux)
1505 UIManager.setLookAndFeel("com.formdev.flatlaf.FlatLightLaf");
1507 Console.debug("Using FlatLightLaf");
1508 } catch (ClassNotFoundException | InstantiationException
1509 | IllegalAccessException | UnsupportedLookAndFeelException e)
1511 Console.debug("Exception loading FlatLightLaf", e);
1513 // enable custom window decorations
1514 JFrame.setDefaultLookAndFeelDecorated(true);
1515 JDialog.setDefaultLookAndFeelDecorated(true);
1516 SwingUtilities.invokeLater(() -> {
1517 FlatLightLaf.setup();
1519 Console.debug("Using FlatLightLaf");
1527 UIManager.setLookAndFeel("com.formdev.flatlaf.FlatLightLaf");
1529 Console.debug("Using FlatLightLaf");
1530 } catch (ClassNotFoundException | InstantiationException
1531 | IllegalAccessException | UnsupportedLookAndFeelException e)
1533 Console.debug("Exception loading FlatLightLaf", e);
1539 UIManager.put("TabbedPane.tabType", "card");
1540 UIManager.put("TabbedPane.showTabSeparators", true);
1541 UIManager.put("TabbedPane.showContentSeparator", true);
1542 // UIManager.put("TabbedPane.tabSeparatorsFullHeight", true);
1543 UIManager.put("TabbedPane.tabsOverlapBorder", true);
1544 UIManager.put("TabbedPane.hasFullBorder", true);
1545 UIManager.put("TabbedPane.tabLayoutPolicy", "scroll");
1546 UIManager.put("TabbedPane.scrollButtonsPolicy", "asNeeded");
1547 UIManager.put("TabbedPane.smoothScrolling", true);
1548 UIManager.put("TabbedPane.tabWidthMode", "compact");
1549 UIManager.put("TabbedPane.selectedBackground", Color.white);
1550 UIManager.put("TabbedPane.background", new Color(236, 236, 236));
1551 UIManager.put("TabbedPane.hoverColor", Color.lightGray);
1554 Desktop.setLiveDragMode(Cache.getDefault("FLAT_LIVE_DRAG_MODE", true));
1558 private static boolean setMacLookAndFeel()
1560 boolean set = false;
1561 System.setProperty("com.apple.mrj.application.apple.menu.about.name",
1562 ChannelProperties.getProperty("app_name"));
1563 System.setProperty("apple.laf.useScreenMenuBar", "true");
1565 * broken native LAFs on (ARM?) macbooks
1566 set = setQuaquaLookAndFeel();
1567 if ((!set) || !UIManager.getLookAndFeel().getClass().toString()
1568 .toLowerCase(Locale.ROOT).contains("quaqua"))
1570 set = setVaquaLookAndFeel();
1573 set = setFlatLookAndFeel();
1577 private static boolean setLinuxLookAndFeel()
1579 boolean set = false;
1580 set = setFlatLookAndFeel();
1582 set = setMetalLookAndFeel();
1583 // avoid GtkLookAndFeel -- not good results especially on HiDPI
1585 set = setNimbusLookAndFeel();
1590 private static void showUsage()
1592 jalview.bin.Console.outPrintln(
1593 "Usage: jalview -open [FILE] [OUTPUT_FORMAT] [OUTPUT_FILE]\n\n"
1594 + "-nodisplay\tRun Jalview without User Interface.\n"
1595 + "-props FILE\tUse the given Jalview properties file instead of users default.\n"
1596 + "-colour COLOURSCHEME\tThe colourscheme to be applied to the alignment\n"
1597 + "-annotations FILE\tAdd precalculated annotations to the alignment.\n"
1598 + "-tree FILE\tLoad the given newick format tree file onto the alignment\n"
1599 + "-features FILE\tUse the given file to mark features on the alignment.\n"
1600 + "-fasta FILE\tCreate alignment file FILE in Fasta format.\n"
1601 + "-clustal FILE\tCreate alignment file FILE in Clustal format.\n"
1602 + "-pfam FILE\tCreate alignment file FILE in PFAM format.\n"
1603 + "-msf FILE\tCreate alignment file FILE in MSF format.\n"
1604 + "-pileup FILE\tCreate alignment file FILE in Pileup format\n"
1605 + "-pir FILE\tCreate alignment file FILE in PIR format.\n"
1606 + "-blc FILE\tCreate alignment file FILE in BLC format.\n"
1607 + "-json FILE\tCreate alignment file FILE in JSON format.\n"
1608 + "-jalview FILE\tCreate alignment file FILE in Jalview format.\n"
1609 + "-png FILE\tCreate PNG image FILE from alignment.\n"
1610 + "-svg FILE\tCreate SVG image FILE from alignment.\n"
1611 + "-html FILE\tCreate HTML file from alignment.\n"
1612 + "-biojsMSA FILE\tCreate BioJS MSA Viewer HTML file from alignment.\n"
1613 + "-imgMap FILE\tCreate HTML file FILE with image map of PNG image.\n"
1614 + "-eps FILE\tCreate EPS file FILE from alignment.\n"
1615 + "-questionnaire URL\tQueries the given URL for information about any Jalview user questionnaires.\n"
1616 + "-noquestionnaire\tTurn off questionnaire check.\n"
1617 + "-nonews\tTurn off check for Jalview news.\n"
1618 + "-nousagestats\tTurn off analytics tracking for this session.\n"
1619 + "-sortbytree OR -nosortbytree\tEnable or disable sorting of the given alignment by the given tree\n"
1621 // "-setprop PROPERTY=VALUE\tSet the given Jalview property,
1622 // after all other properties files have been read\n\t
1623 // (quote the 'PROPERTY=VALUE' pair to ensure spaces are
1624 // passed in correctly)"
1625 + "-jabaws URL\tSpecify URL for Jabaws services (e.g. for a local installation).\n"
1626 + "-fetchfrom nickname\tQuery nickname for features for the alignments and display them.\n"
1627 + "-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"
1629 + "-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"
1630 + "\n~Read documentation in Application or visit https://www.jalview.org for description of Features and Annotations file~\n\n");
1634 private static void startUsageStats(final Desktop desktop)
1637 * start a User Config prompt asking if we can log usage statistics.
1639 PromptUserConfig prompter = new PromptUserConfig(Desktop.desktop,
1641 MessageManager.getString("prompt.analytics_title"),
1642 MessageManager.getString("prompt.analytics"), new Runnable()
1647 Console.debug("Initialising analytics for usage stats.");
1648 Cache.initAnalytics();
1649 Console.debug("Tracking enabled.");
1656 Console.debug("Not enabling analytics.");
1659 desktop.addDialogThread(prompter);
1663 * Locate the given string as a file and pass it to the groovy interpreter.
1665 * @param groovyscript
1666 * the script to execute
1667 * @param jalviewContext
1668 * the Jalview Desktop object passed in to the groovy binding as the
1671 protected void executeGroovyScript(String groovyscript, AlignFrame af)
1674 * for scripts contained in files
1681 if (groovyscript.trim().equals("STDIN"))
1683 // read from stdin into a tempfile and execute it
1686 tfile = File.createTempFile("jalview", "groovy");
1687 PrintWriter outfile = new PrintWriter(
1688 new OutputStreamWriter(new FileOutputStream(tfile)));
1689 BufferedReader br = new BufferedReader(
1690 new InputStreamReader(System.in));
1692 while ((line = br.readLine()) != null)
1694 outfile.write(line + "\n");
1700 } catch (Exception ex)
1703 .errPrintln("Failed to read from STDIN into tempfile "
1704 + ((tfile == null) ? "(tempfile wasn't created)"
1705 : tfile.toString()));
1706 ex.printStackTrace();
1711 sfile = tfile.toURI().toURL();
1712 } catch (Exception x)
1714 jalview.bin.Console.errPrintln(
1715 "Unexpected Malformed URL Exception for temporary file created from STDIN: "
1717 x.printStackTrace();
1725 sfile = new URI(groovyscript).toURL();
1726 } catch (Exception x)
1728 tfile = new File(groovyscript);
1729 if (!tfile.exists())
1731 jalview.bin.Console.errPrintln(
1732 "File '" + groovyscript + "' does not exist.");
1735 if (!tfile.canRead())
1737 jalview.bin.Console.errPrintln(
1738 "File '" + groovyscript + "' cannot be read.");
1741 if (tfile.length() < 1)
1744 .errPrintln("File '" + groovyscript + "' is empty.");
1749 sfile = tfile.getAbsoluteFile().toURI().toURL();
1750 } catch (Exception ex)
1752 jalview.bin.Console.errPrintln("Failed to create a file URL for "
1753 + tfile.getAbsoluteFile());
1760 JalviewObjectI j = new JalviewObject(this);
1761 Map<String, java.lang.Object> vbinding = new HashMap<>();
1762 vbinding.put(JalviewObjectI.jalviewObjectName, j);
1763 vbinding.put(JalviewObjectI.currentAlFrameName,
1764 af != null ? af : getCurrentAlignFrame());
1765 Binding gbinding = new Binding(vbinding);
1766 GroovyScriptEngine gse = new GroovyScriptEngine(new URL[] { sfile });
1767 gse.run(sfile.toString(), gbinding);
1768 if ("STDIN".equals(groovyscript))
1770 // delete temp file that we made -
1771 // only if it was successfully executed
1774 } catch (Exception e)
1777 .errPrintln("Exception Whilst trying to execute file " + sfile
1778 + " as a groovy script.");
1779 e.printStackTrace(System.err);
1783 public static boolean isHeadlessMode()
1785 String isheadless = System.getProperty("java.awt.headless");
1786 if (isheadless != null && isheadless.equalsIgnoreCase("true"))
1794 public AlignFrame[] getAlignFrames()
1796 return desktop == null ? new AlignFrame[] { getCurrentAlignFrame() }
1797 : Desktop.getDesktopAlignFrames();
1801 * jalview.bin.Jalview.quit() will just run the non-GUI shutdownHook and exit
1806 // System.exit will run the shutdownHook first
1807 Jalview.exit("Quitting now. Bye!", ExitCode.OK);
1811 public AlignFrame getCurrentAlignFrame()
1813 return currentAlignFrame;
1816 public void setCurrentAlignFrame(AlignFrame af)
1818 this.currentAlignFrame = af;
1821 public Commands getCommands()
1826 public static void exit(String message, ExitCode ec)
1828 int exitcode = ec == ExitCode.OK ? 0 : ec.ordinal() + 1;
1829 if (Console.log == null)
1831 // Don't start the logger just to exit!
1832 if (message != null)
1836 Console.outPrintln(message);
1840 jalview.bin.Console.errPrintln(message);
1846 Console.debug("Using Jalview.exit");
1847 if (message != null)
1851 Console.info(message);
1855 Console.error(message);
1861 System.exit(exitcode);
1865 public enum ExitCode
1867 // only add new ones to the end of the list (to preserve ordinal values)
1868 OK, FILE_NOT_FOUND, FILE_NOT_READABLE, NO_FILES, INVALID_FORMAT,
1869 INVALID_ARGUMENT, INVALID_VALUE, MIXED_CLI_ARGUMENTS,
1870 ERROR_RUNNING_COMMANDS, NO_LOGGING, GROOVY_ERROR;
1873 /******************************
1875 * TEST OUTPUT METHODS
1877 * these operate only when Arg.TESTOUTPUT has been passed, and variously check
1878 * if an expected value / arg was set and report it to the test framework.
1880 ******************************/
1882 * report string values parsed/processed during tests When the Bootstrap
1883 * argument Arg.TESTOUTPUT is present - reports on debug if given s1 is not
1884 * null and not equals s2, warns if given argument is not set, and calls
1885 * testoutput(true,a,s1,s2) to report processing progress.
1888 * - ArgParser handling parsing
1890 * - Arg currently being processed
1895 protected static void testoutput(ArgParser ap, Arg a, String s1,
1898 BootstrapArgs bsa = ap.getBootstrapArgs();
1899 if (!bsa.getBoolean(Arg.TESTOUTPUT))
1901 if (!((s1 == null && s2 == null) || (s1 != null && s1.equals(s2))))
1903 Console.debug("testoutput with unmatching values '" + s1 + "' and '"
1904 + s2 + "' for arg " + a.argString());
1907 boolean isset = a.hasOption(Opt.BOOTSTRAP) ? bsa.contains(a)
1911 Console.warn("Arg '" + a.getName() + "' not set at all");
1914 testoutput(true, a, s1, s2);
1918 * report values passed via bootstrap arguments
1920 * TODO: significant code duplication with testouput(Argparser...) - move it
1923 protected static void testoutput(BootstrapArgs bsa, Arg a, String s1,
1926 if (!bsa.getBoolean(Arg.TESTOUTPUT))
1928 if (!((s1 == null && s2 == null) || (s1 != null && s1.equals(s2))))
1930 Console.debug("testoutput with unmatching values '" + s1 + "' and '"
1931 + s2 + "' for arg " + a.argString());
1934 if (!a.hasOption(Opt.BOOTSTRAP))
1936 Console.error("Non-bootstrap Arg '" + a.getName()
1937 + "' given to testoutput(BootstrapArgs bsa, Arg a, String s1, String s2) with only BootstrapArgs");
1939 if (!bsa.contains(a))
1941 Console.warn("Arg '" + a.getName() + "' not set at all");
1944 testoutput(true, a, s1, s2);
1948 * conditionally (on @param yes) report that expected value s1 was set during
1949 * CommandsTest tests
1951 private static void testoutput(boolean yes, Arg a, String s1, String s2)
1953 if (yes && ((s1 == null && s2 == null)
1954 || (s1 != null && s1.equals(s2))))
1956 Console.outPrintln("[TESTOUTPUT] arg " + a.argString() + "='" + s1
1962 * testoutput for boolean and unary values
1964 protected static void testoutput(ArgParser ap, Arg a)
1968 BootstrapArgs bsa = ap.getBootstrapArgs();
1971 if (!bsa.getBoolean(Arg.TESTOUTPUT))
1973 boolean val = a.hasOption(Opt.BOOTSTRAP) ? bsa.getBoolean(a)
1975 boolean isset = a.hasOption(Opt.BOOTSTRAP) ? bsa.contains(a)
1979 Console.warn("Arg '" + a.getName() + "' not set at all");
1985 protected static void testoutput(BootstrapArgs bsa, Arg a)
1987 if (!bsa.getBoolean(Arg.TESTOUTPUT))
1989 if (!a.hasOption(Opt.BOOTSTRAP))
1991 Console.warn("Non-bootstrap Arg '" + a.getName()
1992 + "' given to testoutput(BootstrapArgs bsa, Arg a) with only BootstrapArgs");
1995 if (!bsa.contains(a))
1997 Console.warn("Arg '" + a.getName() + "' not set at all");
2000 testoutput(bsa.getBoolean(a), a);
2003 private static void testoutput(boolean yes, Arg a)
2005 String message = null;
2006 if (a.hasOption(Opt.BOOLEAN))
2008 message = (yes ? a.argString() : a.negateArgString()) + " was set";
2010 else if (a.hasOption(Opt.UNARY))
2012 message = a.argString() + (yes ? " was set" : " was not set");
2014 Console.outPrintln("[TESTOUTPUT] arg " + message);
2017 public ArgParser getArgParser()
2022 public BootstrapArgs getBootstrapArgs()
2024 return bootstrapArgs;
2027 public static boolean isBatchMode()
2029 return getInstance() != null && (getInstance().desktop == null
2030 || getInstance().desktop.isInBatchMode());
2034 * Warning about old or mixed command line arguments
2036 private void mixedCliWarning()
2038 Jalview j = Jalview.getInstance();
2039 boolean mixedStyle = j.getArgParser() != null
2040 && j.getArgParser().isMixedStyle();
2041 String title = MessageManager.getString("label.command_line_arguments");
2044 String warning = MessageManager.formatMessage(
2045 "warning.using_mixed_command_line_arguments",
2046 j.getArgParser().getMixedExamples());
2047 String quit = MessageManager.getString("action.quit");
2049 Desktop.instance.nonBlockingDialog(title, warning, null, quit,
2050 JvOptionPane.WARNING_MESSAGE, false, false, true, 30000);
2053 "Exiting due to mixed old and new command line arguments.",
2054 ExitCode.MIXED_CLI_ARGUMENTS);
2058 private void cliWarning()
2060 Jalview j = Jalview.getInstance();
2061 Commands c = j.getCommands();
2062 boolean oldStyle = j.getArgParser() != null
2063 && j.getArgParser().isOldStyle();
2064 String title = MessageManager.getString("label.command_line_arguments");
2067 String warning = MessageManager
2068 .getString("warning.using_old_command_line_arguments");
2069 String url = "<a href=\"https://www.jalview.org/help/html/features/commandline.html\">https://www.jalview.org/help/html/features/commandline.html</a>";
2070 if (Desktop.instance != null)
2072 String cont = MessageManager.getString("label.continue");
2074 Desktop.instance.nonBlockingDialog(title, warning, url, cont,
2075 JvOptionPane.WARNING_MESSAGE, false, true, true, 30000);
2078 if (j.getCommands() != null && j.getCommands().getErrors().size() > 0)
2080 if (Desktop.instance != null)
2082 String message = MessageManager
2083 .getString("warning.the_following_errors");
2084 String ok = MessageManager.getString("action.ok");
2086 List<String> errors = j.getCommands().getErrors();
2087 for (int i = 0; i < errors.size(); i++)
2089 shortest = Math.min(shortest, errors.get(i).length());
2091 Desktop.instance.nonBlockingDialog(
2092 Math.max(message.length(), Math.min(60, shortest)),
2093 Math.min(errors.size(), 20), title, message,
2094 j.getCommands().errorsToString(), ok,
2095 JvOptionPane.WARNING_MESSAGE, true, false, true, -1);