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.FileNotFoundException;
27 import java.io.FileOutputStream;
28 import java.io.IOException;
29 import java.io.InputStreamReader;
30 import java.io.OutputStream;
31 import java.io.OutputStreamWriter;
32 import java.io.PrintStream;
33 import java.io.PrintWriter;
34 import java.net.MalformedURLException;
36 import java.net.URISyntaxException;
38 import java.security.AllPermission;
39 import java.security.CodeSource;
40 import java.security.PermissionCollection;
41 import java.security.Permissions;
42 import java.security.Policy;
43 import java.util.ArrayList;
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.LaunchUtils;
105 import jalview.util.MessageManager;
106 import jalview.util.Platform;
107 import jalview.util.UserAgent;
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 = System.currentTimeMillis();
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", UserAgent.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 cmds = new Commands(argparser, headlessArg);
844 boolean commandsSuccess = cmds.argsWereParsed();
850 if (argparser.getBoolean(Arg.NOQUIT))
853 "Completed " + Arg.HEADLESS.getName() + " commands, but "
854 + Arg.NOQUIT + " is set so not quitting!");
858 Jalview.exit("Successfully completed commands in headless mode",
862 Console.info("Successfully completed commands");
868 Jalview.exit("Error when running Commands in headless mode",
869 ExitCode.ERROR_RUNNING_COMMANDS);
871 Console.warn("Error when running commands");
874 // Check if JVM and compile version might cause problems and log if it
876 if (headless && !Platform.isJS() && !LaunchUtils.checkJavaVersion())
878 Console.warn("The Java version being used (Java "
879 + LaunchUtils.getJavaVersion()
880 + ") may lead to problems. This installation of Jalview should be used with Java "
881 + LaunchUtils.getJavaCompileVersion() + ".");
884 String file = null, data = null;
886 FileFormatI format = null;
888 DataSourceType protocol = null;
890 FileLoader fileLoader = new FileLoader(!headless);
892 String groovyscript = null; // script to execute after all loading is
893 // completed one way or another
894 // extract groovy argument and execute if necessary
895 groovyscript = aparser.getValue("groovy", true);
896 file = aparser.getValue("open", true);
898 if (file == null && desktop == null && !commandsSuccess)
900 Jalview.exit("No files to open!", ExitCode.NO_FILES);
904 // Finally, deal with the remaining input data.
909 desktop.setProgressBar(
911 .getString("status.processing_commandline_args"),
912 progress = System.currentTimeMillis());
914 Console.outPrintln("CMD [-open " + file + "] executed successfully!");
916 if (!Platform.isJS())
918 * ignore in JavaScript -- can't just file existence - could load it?
923 if (!HttpUtils.startsWithHttpOrHttps(file))
925 if (!(new File(file)).exists())
930 "Can't find file '" + file + "' in headless mode",
931 ExitCode.FILE_NOT_FOUND);
933 Console.warn("Can't find file'" + file + "'");
938 protocol = AppletFormatAdapter.checkProtocol(file);
942 format = new IdentifyFile().identify(file, protocol);
943 } catch (FileNotFoundException e)
945 Console.error("File at '" + file + "' not found", e);
946 } catch (FileFormatException e)
948 Console.error("File '" + file + "' format not recognised", e);
951 AlignFrame af = fileLoader.LoadFileWaitTillLoaded(file, protocol,
955 Console.outPrintln("error");
959 setCurrentAlignFrame(af);
960 data = aparser.getValue("colour", true);
963 data.replaceAll("%20", " ");
965 ColourSchemeI cs = ColourSchemeProperty.getColourScheme(
966 af.getViewport(), af.getViewport().getAlignment(), data);
971 "CMD [-colour " + data + "] executed successfully!");
976 // Must maintain ability to use the groups flag
977 data = aparser.getValue("groups", true);
980 af.parseFeaturesFile(data,
981 AppletFormatAdapter.checkProtocol(data));
982 // Console.outPrintln("Added " + data);
984 "CMD groups[-" + data + "] executed successfully!");
986 data = aparser.getValue("features", true);
989 af.parseFeaturesFile(data,
990 AppletFormatAdapter.checkProtocol(data));
991 // Console.outPrintln("Added " + data);
993 "CMD [-features " + data + "] executed successfully!");
996 data = aparser.getValue("annotations", true);
999 af.loadJalviewDataFile(data, null, null, null);
1000 // Console.outPrintln("Added " + data);
1002 "CMD [-annotations " + data + "] executed successfully!");
1004 // set or clear the sortbytree flag.
1005 if (aparser.contains("sortbytree"))
1007 af.getViewport().setSortByTree(true);
1008 if (af.getViewport().getSortByTree())
1010 Console.outPrintln("CMD [-sortbytree] executed successfully!");
1013 if (aparser.contains("no-annotation"))
1015 af.getViewport().setShowAnnotation(false);
1016 if (!af.getViewport().isShowAnnotation())
1018 Console.outPrintln("CMD no-annotation executed successfully!");
1021 if (aparser.contains("nosortbytree"))
1023 af.getViewport().setSortByTree(false);
1024 if (!af.getViewport().getSortByTree())
1027 "CMD [-nosortbytree] executed successfully!");
1030 data = aparser.getValue("tree", true);
1036 "CMD [-tree " + data + "] executed successfully!");
1037 NewickFile nf = new NewickFile(data,
1038 AppletFormatAdapter.checkProtocol(data));
1040 .setCurrentTree(af.showNewickTree(nf, data).getTree());
1041 } catch (IOException ex)
1043 jalview.bin.Console.errPrintln("Couldn't add tree " + data);
1044 ex.printStackTrace(System.err);
1048 if (groovyscript != null)
1050 // Execute the groovy script after we've done all the rendering stuff
1051 // and before any images or figures are generated.
1052 Console.outPrintln("Executing script " + groovyscript);
1053 executeGroovyScript(groovyscript, af);
1054 Console.outPrintln("CMD groovy[" + groovyscript
1055 + "] executed successfully!");
1056 groovyscript = null;
1058 String imageName = "unnamed.png";
1059 while (aparser.getSize() > 1)
1063 String outputFormat = aparser.nextValue();
1064 file = aparser.nextValue();
1066 if (outputFormat.equalsIgnoreCase("png"))
1068 Console.outPrintln("Creating PNG image: " + file);
1069 af.createPNG(new File(file));
1070 imageName = (new File(file)).getName();
1073 else if (outputFormat.equalsIgnoreCase("svg"))
1075 Console.outPrintln("Creating SVG image: " + file);
1076 File imageFile = new File(file);
1077 imageName = imageFile.getName();
1078 af.createSVG(imageFile);
1081 else if (outputFormat.equalsIgnoreCase("html"))
1083 File imageFile = new File(file);
1084 imageName = imageFile.getName();
1085 HtmlSvgOutput htmlSVG = new HtmlSvgOutput(af.alignPanel);
1087 Console.outPrintln("Creating HTML image: " + file);
1088 htmlSVG.exportHTML(file);
1091 else if (outputFormat.equalsIgnoreCase("biojsmsa"))
1095 jalview.bin.Console.errPrintln(
1096 "The output html file must not be null");
1101 BioJsHTMLOutput.refreshVersionInfo(
1102 BioJsHTMLOutput.BJS_TEMPLATES_LOCAL_DIRECTORY);
1103 } catch (URISyntaxException e)
1105 e.printStackTrace();
1107 BioJsHTMLOutput bjs = new BioJsHTMLOutput(af.alignPanel);
1109 "Creating BioJS MSA Viwer HTML file: " + file);
1110 bjs.exportHTML(file);
1113 else if (outputFormat.equalsIgnoreCase("imgMap"))
1115 Console.outPrintln("Creating image map: " + file);
1116 af.createImageMap(new File(file), imageName);
1119 else if (outputFormat.equalsIgnoreCase("eps"))
1121 File outputFile = new File(file);
1123 "Creating EPS file: " + outputFile.getAbsolutePath());
1124 af.createEPS(outputFile);
1128 FileFormatI outFormat = null;
1131 outFormat = FileFormats.getInstance().forName(outputFormat);
1132 } catch (Exception formatP)
1134 Console.outPrintln("Couldn't parse " + outFormat
1135 + " as a valid Jalview format string.");
1137 if (outFormat != null)
1139 if (!outFormat.isWritable())
1142 "This version of Jalview does not support alignment export as "
1147 af.saveAlignment(file, outFormat);
1148 if (af.isSaveAlignmentSuccessful())
1150 Console.outPrintln("Written alignment in "
1151 + outFormat.getName() + " format to " + file);
1155 Console.outPrintln("Error writing file " + file + " in "
1156 + outFormat.getName() + " format!!");
1160 } catch (ImageOutputException ioexc)
1163 "Unexpected error whilst exporting image to " + file);
1164 ioexc.printStackTrace();
1169 while (aparser.getSize() > 0)
1171 Console.outPrintln("Unknown arg: " + aparser.nextValue());
1176 AlignFrame startUpAlframe = null;
1177 // We'll only open the default file if the desktop is visible.
1179 // ////////////////////
1181 if (!Platform.isJS() && !headless && file == null
1182 && Cache.getDefault("SHOW_STARTUP_FILE", true)
1183 && !cmds.commandArgsProvided()
1184 && !bootstrapArgs.getBoolean(Arg.NOSTARTUPFILE))
1185 // don't open the startup file if command line args have been processed
1186 // (&& !Commands.commandArgsProvided())
1193 file = Cache.getDefault("STARTUP_FILE",
1194 Cache.getDefault("www.jalview.org", "https://www.jalview.org")
1195 + "/examples/exampleFile_2_7.jvp");
1196 if (file.equals("http://www.jalview.org/examples/exampleFile_2_3.jar")
1198 "http://www.jalview.org/examples/exampleFile_2_7.jar"))
1200 file.replace("http:", "https:");
1201 // hardwire upgrade of the startup file
1202 file.replace("_2_3", "_2_7");
1203 file.replace("2_7.jar", "2_7.jvp");
1204 // and remove the stale setting
1205 Cache.removeProperty("STARTUP_FILE");
1208 protocol = AppletFormatAdapter.checkProtocol(file);
1210 if (file.endsWith(".jar"))
1212 format = FileFormat.Jalview;
1218 format = new IdentifyFile().identify(file, protocol);
1219 } catch (FileNotFoundException e)
1221 Console.error("File at '" + file + "' not found", e);
1222 } catch (FileFormatException e)
1224 Console.error("File '" + file + "' format not recognised", e);
1228 startUpAlframe = fileLoader.LoadFileWaitTillLoaded(file, protocol,
1230 // don't ask to save when quitting if only the startup file has been
1232 Console.debug("Resetting up-to-date flag for startup file");
1233 startUpAlframe.getViewport().setSavedUpToDate(true);
1234 // extract groovy arguments before anything else.
1237 // Once all other stuff is done, execute any groovy scripts (in order)
1238 if (groovyscript != null)
1240 if (Cache.groovyJarsPresent())
1242 Console.outPrintln("Executing script " + groovyscript);
1243 executeGroovyScript(groovyscript, startUpAlframe);
1247 jalview.bin.Console.errPrintln(
1248 "Sorry. Groovy Support is not available, so ignoring the provided groovy script "
1252 // and finally, turn off batch mode indicator - if the desktop still exists
1253 if (desktop != null)
1257 desktop.setProgressBar(null, progress);
1259 desktop.setInBatchMode(false);
1265 private static void setLookAndFeel()
1267 if (!Platform.isJS())
1274 // property laf = "crossplatform", "system", "gtk", "metal", "nimbus",
1276 // If not set (or chosen laf fails), use the normal SystemLaF and if on
1278 // try Quaqua/Vaqua.
1279 String lafProp = System.getProperty("laf");
1280 String lafSetting = Cache.getDefault("PREFERRED_LAF", null);
1281 String laf = "none";
1282 if (lafProp != null)
1286 else if (lafSetting != null)
1290 boolean lafSet = false;
1293 case "crossplatform":
1294 lafSet = setCrossPlatformLookAndFeel();
1297 Console.error("Could not set requested laf=" + laf);
1301 lafSet = setSystemLookAndFeel();
1304 Console.error("Could not set requested laf=" + laf);
1308 lafSet = setGtkLookAndFeel();
1311 Console.error("Could not set requested laf=" + laf);
1315 lafSet = setMetalLookAndFeel();
1318 Console.error("Could not set requested laf=" + laf);
1322 lafSet = setNimbusLookAndFeel();
1325 Console.error("Could not set requested laf=" + laf);
1329 lafSet = setFlatLookAndFeel();
1332 Console.error("Could not set requested laf=" + laf);
1336 lafSet = setMacLookAndFeel();
1339 Console.error("Could not set requested laf=" + laf);
1345 Console.error("Requested laf=" + laf + " not implemented");
1349 // Flatlaf default for everyone!
1350 lafSet = setFlatLookAndFeel();
1353 setSystemLookAndFeel();
1355 if (Platform.isLinux())
1357 setLinuxLookAndFeel();
1359 if (Platform.isMac())
1361 setMacLookAndFeel();
1367 private static boolean setCrossPlatformLookAndFeel()
1369 boolean set = false;
1372 UIManager.setLookAndFeel(
1373 UIManager.getCrossPlatformLookAndFeelClassName());
1375 } catch (Exception ex)
1377 Console.error("Unexpected Look and Feel Exception");
1378 Console.error(ex.getMessage());
1379 Console.debug(Cache.getStackTraceString(ex));
1384 private static boolean setSystemLookAndFeel()
1386 boolean set = false;
1389 UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
1391 } catch (Exception ex)
1393 Console.error("Unexpected Look and Feel Exception");
1394 Console.error(ex.getMessage());
1395 Console.debug(Cache.getStackTraceString(ex));
1400 private static boolean setSpecificLookAndFeel(String name,
1401 String className, boolean nameStartsWith)
1403 boolean set = false;
1406 for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels())
1408 if (info.getName() != null && nameStartsWith
1409 ? info.getName().toLowerCase(Locale.ROOT)
1410 .startsWith(name.toLowerCase(Locale.ROOT))
1411 : info.getName().toLowerCase(Locale.ROOT)
1412 .equals(name.toLowerCase(Locale.ROOT)))
1414 className = info.getClassName();
1418 UIManager.setLookAndFeel(className);
1420 } catch (Exception ex)
1422 Console.error("Unexpected Look and Feel Exception");
1423 Console.error(ex.getMessage());
1424 Console.debug(Cache.getStackTraceString(ex));
1429 private static boolean setGtkLookAndFeel()
1431 return setSpecificLookAndFeel("gtk",
1432 "com.sun.java.swing.plaf.gtk.GTKLookAndFeel", true);
1435 private static boolean setMetalLookAndFeel()
1437 return setSpecificLookAndFeel("metal",
1438 "javax.swing.plaf.metal.MetalLookAndFeel", false);
1441 private static boolean setNimbusLookAndFeel()
1443 return setSpecificLookAndFeel("nimbus",
1444 "javax.swing.plaf.nimbus.NimbusLookAndFeel", false);
1447 private static boolean setFlatLookAndFeel()
1449 boolean set = false;
1450 if (SystemInfo.isMacOS)
1454 UIManager.setLookAndFeel(
1455 "com.formdev.flatlaf.themes.FlatMacLightLaf");
1457 Console.debug("Using FlatMacLightLaf");
1458 } catch (ClassNotFoundException | InstantiationException
1459 | IllegalAccessException | UnsupportedLookAndFeelException e)
1461 Console.debug("Exception loading FlatLightLaf", e);
1463 System.setProperty("apple.laf.useScreenMenuBar", "true");
1464 System.setProperty("apple.awt.application.name",
1465 ChannelProperties.getProperty("app_name"));
1466 System.setProperty("apple.awt.application.appearance", "system");
1467 if (SystemInfo.isMacFullWindowContentSupported
1468 && Desktop.desktop != null)
1470 Console.debug("Setting transparent title bar");
1471 Desktop.desktop.getRootPane()
1472 .putClientProperty("apple.awt.fullWindowContent", true);
1473 Desktop.desktop.getRootPane()
1474 .putClientProperty("apple.awt.transparentTitleBar", true);
1475 Desktop.desktop.getRootPane()
1476 .putClientProperty("apple.awt.fullscreenable", true);
1478 SwingUtilities.invokeLater(() -> {
1479 FlatMacLightLaf.setup();
1481 Console.debug("Using FlatMacLightLaf");
1488 UIManager.setLookAndFeel("com.formdev.flatlaf.FlatLightLaf");
1490 Console.debug("Using FlatLightLaf");
1491 } catch (ClassNotFoundException | InstantiationException
1492 | IllegalAccessException | UnsupportedLookAndFeelException e)
1494 Console.debug("Exception loading FlatLightLaf", e);
1496 // Windows specific properties here
1497 SwingUtilities.invokeLater(() -> {
1498 FlatLightLaf.setup();
1500 Console.debug("Using FlatLightLaf");
1503 else if (SystemInfo.isLinux)
1507 UIManager.setLookAndFeel("com.formdev.flatlaf.FlatLightLaf");
1509 Console.debug("Using FlatLightLaf");
1510 } catch (ClassNotFoundException | InstantiationException
1511 | IllegalAccessException | UnsupportedLookAndFeelException e)
1513 Console.debug("Exception loading FlatLightLaf", e);
1515 // enable custom window decorations
1516 JFrame.setDefaultLookAndFeelDecorated(true);
1517 JDialog.setDefaultLookAndFeelDecorated(true);
1518 SwingUtilities.invokeLater(() -> {
1519 FlatLightLaf.setup();
1521 Console.debug("Using FlatLightLaf");
1529 UIManager.setLookAndFeel("com.formdev.flatlaf.FlatLightLaf");
1531 Console.debug("Using FlatLightLaf");
1532 } catch (ClassNotFoundException | InstantiationException
1533 | IllegalAccessException | UnsupportedLookAndFeelException e)
1535 Console.debug("Exception loading FlatLightLaf", e);
1541 UIManager.put("TabbedPane.tabType", "card");
1542 UIManager.put("TabbedPane.showTabSeparators", true);
1543 UIManager.put("TabbedPane.showContentSeparator", true);
1544 // UIManager.put("TabbedPane.tabSeparatorsFullHeight", true);
1545 UIManager.put("TabbedPane.tabsOverlapBorder", true);
1546 UIManager.put("TabbedPane.hasFullBorder", true);
1547 UIManager.put("TabbedPane.tabLayoutPolicy", "scroll");
1548 UIManager.put("TabbedPane.scrollButtonsPolicy", "asNeeded");
1549 UIManager.put("TabbedPane.smoothScrolling", true);
1550 UIManager.put("TabbedPane.tabWidthMode", "compact");
1551 UIManager.put("TabbedPane.selectedBackground", Color.white);
1552 UIManager.put("TabbedPane.background", new Color(236, 236, 236));
1553 UIManager.put("TabbedPane.hoverColor", Color.lightGray);
1556 Desktop.setLiveDragMode(Cache.getDefault("FLAT_LIVE_DRAG_MODE", true));
1560 private static boolean setMacLookAndFeel()
1562 boolean set = false;
1563 System.setProperty("com.apple.mrj.application.apple.menu.about.name",
1564 ChannelProperties.getProperty("app_name"));
1565 System.setProperty("apple.laf.useScreenMenuBar", "true");
1567 * broken native LAFs on (ARM?) macbooks
1568 set = setQuaquaLookAndFeel();
1569 if ((!set) || !UIManager.getLookAndFeel().getClass().toString()
1570 .toLowerCase(Locale.ROOT).contains("quaqua"))
1572 set = setVaquaLookAndFeel();
1575 set = setFlatLookAndFeel();
1579 private static boolean setLinuxLookAndFeel()
1581 boolean set = false;
1582 set = setFlatLookAndFeel();
1584 set = setMetalLookAndFeel();
1585 // avoid GtkLookAndFeel -- not good results especially on HiDPI
1587 set = setNimbusLookAndFeel();
1592 private static void showUsage()
1594 jalview.bin.Console.outPrintln(
1595 "Usage: jalview -open [FILE] [OUTPUT_FORMAT] [OUTPUT_FILE]\n\n"
1596 + "-nodisplay\tRun Jalview without User Interface.\n"
1597 + "-props FILE\tUse the given Jalview properties file instead of users default.\n"
1598 + "-colour COLOURSCHEME\tThe colourscheme to be applied to the alignment\n"
1599 + "-annotations FILE\tAdd precalculated annotations to the alignment.\n"
1600 + "-tree FILE\tLoad the given newick format tree file onto the alignment\n"
1601 + "-features FILE\tUse the given file to mark features on the alignment.\n"
1602 + "-fasta FILE\tCreate alignment file FILE in Fasta format.\n"
1603 + "-clustal FILE\tCreate alignment file FILE in Clustal format.\n"
1604 + "-pfam FILE\tCreate alignment file FILE in PFAM format.\n"
1605 + "-msf FILE\tCreate alignment file FILE in MSF format.\n"
1606 + "-pileup FILE\tCreate alignment file FILE in Pileup format\n"
1607 + "-pir FILE\tCreate alignment file FILE in PIR format.\n"
1608 + "-blc FILE\tCreate alignment file FILE in BLC format.\n"
1609 + "-json FILE\tCreate alignment file FILE in JSON format.\n"
1610 + "-jalview FILE\tCreate alignment file FILE in Jalview format.\n"
1611 + "-png FILE\tCreate PNG image FILE from alignment.\n"
1612 + "-svg FILE\tCreate SVG image FILE from alignment.\n"
1613 + "-html FILE\tCreate HTML file from alignment.\n"
1614 + "-biojsMSA FILE\tCreate BioJS MSA Viewer HTML file from alignment.\n"
1615 + "-imgMap FILE\tCreate HTML file FILE with image map of PNG image.\n"
1616 + "-eps FILE\tCreate EPS file FILE from alignment.\n"
1617 + "-questionnaire URL\tQueries the given URL for information about any Jalview user questionnaires.\n"
1618 + "-noquestionnaire\tTurn off questionnaire check.\n"
1619 + "-nonews\tTurn off check for Jalview news.\n"
1620 + "-nousagestats\tTurn off analytics tracking for this session.\n"
1621 + "-sortbytree OR -nosortbytree\tEnable or disable sorting of the given alignment by the given tree\n"
1623 // "-setprop PROPERTY=VALUE\tSet the given Jalview property,
1624 // after all other properties files have been read\n\t
1625 // (quote the 'PROPERTY=VALUE' pair to ensure spaces are
1626 // passed in correctly)"
1627 + "-jabaws URL\tSpecify URL for Jabaws services (e.g. for a local installation).\n"
1628 + "-fetchfrom nickname\tQuery nickname for features for the alignments and display them.\n"
1629 + "-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"
1630 + "-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"
1631 + "-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);