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);
317 if (args == null || args.length == 0 || (args.length == 1
318 && (args[0] == null || args[0].length() == 0)))
320 args = new String[] {};
323 // get args needed before proper ArgParser
324 bootstrapArgs = BootstrapArgs.getBootstrapArgs(args);
326 if (!Platform.isJS())
328 // are we being --quiet ?
329 if (bootstrapArgs.contains(Arg.QUIET))
332 OutputStream devNull = new OutputStream()
336 public void write(int b)
341 System.setOut(new PrintStream(devNull));
342 // redirecting stderr not working
343 if (bootstrapArgs.getList(Arg.QUIET).size() > 1)
345 System.setErr(new PrintStream(devNull));
349 if (bootstrapArgs.contains(Arg.HELP)
350 || bootstrapArgs.contains(Arg.VERSION))
356 // set individual session preferences
357 if (bootstrapArgs.contains(Arg.P))
359 for (String kev : bootstrapArgs.getValueList(Arg.P))
365 int equalsIndex = kev.indexOf(ArgParser.EQUALS);
366 if (equalsIndex > -1)
368 String key = kev.substring(0, equalsIndex);
369 String val = kev.substring(equalsIndex + 1);
370 Cache.setSessionProperty(key, val);
375 // Move any new getdown-launcher-new.jar into place over old
376 // getdown-launcher.jar
377 String appdirString = System.getProperty("getdownappdir");
378 if (appdirString != null && appdirString.length() > 0)
380 final File appdir = new File(appdirString);
387 LaunchUtil.upgradeGetdown(
388 new File(appdir, "getdown-launcher-old.jar"),
389 new File(appdir, "getdown-launcher.jar"),
390 new File(appdir, "getdown-launcher-new.jar"));
395 if (!quiet() || !bootstrapArgs.outputToStdout()
396 || bootstrapArgs.contains(Arg.VERSION))
399 "Java version: " + System.getProperty("java.version"));
400 Console.outPrintln("Java home: " + System.getProperty("java.home"));
401 Console.outPrintln("Java arch: " + System.getProperty("os.arch") + " "
402 + System.getProperty("os.name") + " "
403 + System.getProperty("os.version"));
405 String val = System.getProperty("sys.install4jVersion");
408 Console.outPrintln("Install4j version: " + val);
410 val = System.getProperty("installer_template_version");
413 Console.outPrintln("Install4j template version: " + val);
415 val = System.getProperty("launcher_version");
418 Console.outPrintln("Launcher version: " + val);
422 if (Platform.isLinux() && LaunchUtils.getJavaVersion() < 11)
424 System.setProperty("flatlaf.uiScale", "1");
427 // get bootstrap properties (mainly for the logger level)
428 Properties bootstrapProperties = Cache
429 .bootstrapProperties(bootstrapArgs.getValue(Arg.PROPS));
431 // report Jalview version
432 Cache.loadBuildProperties(
433 !quiet() || bootstrapArgs.contains(Arg.VERSION));
435 // stop now if only after --version
436 if (bootstrapArgs.contains(Arg.VERSION))
438 Jalview.exit(null, ExitCode.OK);
442 ArgsParser aparser = new ArgsParser(args);
445 boolean headless = false;
447 boolean headlessArg = false;
451 String logLevel = null;
452 if (bootstrapArgs.contains(Arg.TRACE))
456 else if (bootstrapArgs.contains(Arg.DEBUG))
458 logLevel = bootstrapArgs.getBoolean(Arg.DEBUG) ? "DEBUG" : "INFO";
460 if (logLevel == null && !(bootstrapProperties == null))
462 logLevel = bootstrapProperties.getProperty(Cache.JALVIEWLOGLEVEL);
464 Console.initLogger(logLevel);
465 } catch (NoClassDefFoundError error)
467 error.printStackTrace();
468 String message = "\nEssential logging libraries not found."
469 + "\nUse: java -classpath \"$PATH_TO_LIB$/*:$PATH_TO_CLASSES$\" jalview.bin.Jalview";
470 Jalview.exit(message, ExitCode.OK);
473 // register SIGTERM listener
474 Runtime.getRuntime().addShutdownHook(new Thread()
479 Console.debug("Running shutdown hook");
480 QuitHandler.startForceQuit();
481 boolean closeExternal = Cache
482 .getDefault("DEFAULT_CLOSE_EXTERNAL_VIEWERS", false)
483 || Cache.getDefault("ALWAYS_CLOSE_EXTERNAL_VIEWERS", false);
484 StructureViewerBase.setQuitClose(closeExternal);
487 for (JInternalFrame frame : Desktop.desktop.getAllFrames())
489 if (frame instanceof StructureViewerBase)
491 ((StructureViewerBase) frame).closeViewer(closeExternal);
496 if (QuitHandler.gotQuitResponse() == QResponse.CANCEL_QUIT)
498 // Got to here by a SIGTERM signal.
499 // Note we will not actually cancel the quit from here -- it's too
500 // late -- but we can wait for saving files and close external viewers
502 // Close viewers/Leave viewers open
503 Console.debug("Checking for saving files");
504 QuitHandler.getQuitResponse(false);
508 Console.debug("Nothing more to do");
510 Console.debug("Exiting, bye!");
511 // shutdownHook cannot be cancelled, JVM will now halt
515 String usrPropsFile = bootstrapArgs.contains(Arg.PROPS)
516 ? bootstrapArgs.getValue(Arg.PROPS)
517 : aparser.getValue("props");
518 // if usrPropsFile == null, loadProperties will use the Channel
520 Cache.loadProperties(usrPropsFile);
521 if (usrPropsFile != null)
524 "CMD [-props " + usrPropsFile + "] executed successfully!");
525 testoutput(bootstrapArgs, Arg.PROPS,
526 "test/jalview/bin/testProps.jvprops", usrPropsFile);
529 // --argfile=... -- OVERRIDES ALL NON-BOOTSTRAP ARGS
530 if (bootstrapArgs.contains(Arg.ARGFILE))
532 argparser = ArgParser.parseArgFiles(
533 bootstrapArgs.getValueList(Arg.ARGFILE),
534 bootstrapArgs.getBoolean(Arg.INITSUBSTITUTIONS),
539 argparser = new ArgParser(args,
540 bootstrapArgs.getBoolean(Arg.INITSUBSTITUTIONS),
544 if (!Platform.isJS())
551 if (bootstrapArgs.contains(Arg.HELP))
553 List<Map.Entry<Type, String>> helpArgs = bootstrapArgs
555 Console.outPrintln(Arg.usage(helpArgs.stream().map(e -> e.getKey())
556 .collect(Collectors.toList())));
557 Jalview.exit(null, ExitCode.OK);
559 if (aparser.contains("help") || aparser.contains("h"))
562 * Now using new usage statement. showUsage();
564 Console.outPrintln(Arg.usage());
565 Jalview.exit(null, ExitCode.OK);
569 headlessArg = bootstrapArgs.isHeadless();
572 System.setProperty("java.awt.headless", "true");
575 if (aparser.contains("nodisplay") || aparser.contains("nogui")
576 || aparser.contains("headless"))
578 System.setProperty("java.awt.headless", "true");
583 // allow https handshakes to download intermediate certs if necessary
584 System.setProperty("com.sun.security.enableAIAcaIssuers", "true");
586 String jabawsUrl = bootstrapArgs.getValue(Arg.JABAWS);
587 if (jabawsUrl == null)
588 jabawsUrl = aparser.getValue("jabaws");
589 if (jabawsUrl != null)
593 Jws2Discoverer.getDiscoverer().setPreferredUrl(jabawsUrl);
595 "CMD [-jabaws " + jabawsUrl + "] executed successfully!");
596 testoutput(bootstrapArgs, Arg.JABAWS,
597 "http://www.compbio.dundee.ac.uk/jabaws", jabawsUrl);
598 } catch (MalformedURLException e)
600 jalview.bin.Console.errPrintln(
601 "Invalid jabaws parameter: " + jabawsUrl + " ignored");
606 List<String> setprops = new ArrayList<>();
607 if (bootstrapArgs.contains(Arg.SETPROP))
609 setprops = bootstrapArgs.getValueList(Arg.SETPROP);
613 String sp = aparser.getValue("setprop");
617 sp = aparser.getValue("setprop");
620 for (String setprop : setprops)
622 int p = setprop.indexOf('=');
626 .println("Ignoring invalid setprop argument : " + setprop);
631 .errPrintln("Executing setprop argument: " + setprop);
634 Cache.setProperty(setprop.substring(0, p),
635 setprop.substring(p + 1));
637 // DISABLED FOR SECURITY REASONS
638 // TODO: add a property to allow properties to be overriden by cli args
639 // Cache.setProperty(setprop.substring(0,p), setprop.substring(p+1));
642 if (System.getProperty("java.awt.headless") != null
643 && System.getProperty("java.awt.headless").equals("true"))
647 System.setProperty("http.agent", HttpUtils.getUserAgent());
651 Console.initLogger();
652 } catch (NoClassDefFoundError error)
654 error.printStackTrace();
655 String message = "\nEssential logging libraries not found."
656 + "\nUse: java -classpath \"$PATH_TO_LIB$/*:$PATH_TO_CLASSES$\" jalview.bin.Jalview";
657 Jalview.exit(message, ExitCode.NO_LOGGING);
661 if (!(headless || headlessArg))
665 * configure 'full' SO model if preferences say to, else use the default (full
666 * SO) - as JS currently doesn't have OBO parsing, it must use 'Lite' version
668 boolean soDefault = !Platform.isJS();
669 if (Cache.getDefault("USE_FULL_SO", soDefault))
671 SequenceOntologyFactory.setInstance(new SequenceOntology());
674 if (!(headless || headlessArg))
676 Desktop.nosplash = "false".equals(bootstrapArgs.getValue(Arg.SPLASH))
677 || aparser.contains("nosplash")
678 || Cache.getDefault("SPLASH", "true").equals("false");
679 desktop = new Desktop();
680 desktop.setInBatchMode(true); // indicate we are starting up
686 JalviewTaskbar.setTaskbar(this);
687 } catch (Exception e)
689 Console.info("Cannot set Taskbar");
690 Console.error(e.getMessage());
691 // e.printStackTrace();
692 } catch (Throwable t)
694 Console.info("Cannot set Taskbar");
695 Console.error(t.getMessage());
696 // t.printStackTrace();
699 // set Proxy settings before all the internet calls
700 Cache.setProxyPropertiesFromPreferences();
702 desktop.setVisible(true);
704 if (!Platform.isJS())
713 * Check to see that the JVM version being run is suitable for the Java
714 * version this Jalview was compiled for. Popup a warning if not.
716 if (!LaunchUtils.checkJavaVersion())
718 Console.warn("The Java version being used (Java "
719 + LaunchUtils.getJavaVersion()
720 + ") may lead to problems. This installation of Jalview should be used with Java "
721 + LaunchUtils.getJavaCompileVersion() + ".");
724 .getBooleanUserPreference("IGNORE_JVM_WARNING_POPUP"))
727 MessageManager.getString("label.continue") };
728 JOptionPane.showOptionDialog(null,
729 MessageManager.formatMessage(
730 "warning.wrong_jvm_version_message",
731 LaunchUtils.getJavaVersion(),
732 LaunchUtils.getJavaCompileVersion()),
734 .getString("warning.wrong_jvm_version_title"),
735 JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE,
736 null, options, options[0]);
740 boolean webservicediscovery = bootstrapArgs
741 .getBoolean(Arg.WEBSERVICEDISCOVERY);
742 if (aparser.contains("nowebservicediscovery"))
743 webservicediscovery = false;
744 if (webservicediscovery)
746 desktop.startServiceDiscovery();
750 testoutput(argparser, Arg.WEBSERVICEDISCOVERY);
753 boolean usagestats = !bootstrapArgs.getBoolean(Arg.NOUSAGESTATS);
754 if (aparser.contains("nousagestats"))
758 startUsageStats(desktop);
759 testoutput(argparser, Arg.NOUSAGESTATS);
763 Console.outPrintln("CMD [-nousagestats] executed successfully!");
764 testoutput(argparser, Arg.NOUSAGESTATS);
767 boolean questionnaire = bootstrapArgs.getBoolean(Arg.QUESTIONNAIRE);
768 if (aparser.contains("noquestionnaire"))
769 questionnaire = false;
772 String url = aparser.getValue("questionnaire");
775 // Start the desktop questionnaire prompter with the specified
777 Console.debug("Starting questionnaire url at " + url);
778 desktop.checkForQuestionnaire(url);
779 Console.outPrintln("CMD questionnaire[-" + url
780 + "] executed successfully!");
784 if (Cache.getProperty("NOQUESTIONNAIRES") == null)
786 // Start the desktop questionnaire prompter with the specified
789 // "http://anaplog.compbio.dundee.ac.uk/cgi-bin/questionnaire.pl";
791 String defurl = "https://www.jalview.org/cgi-bin/questionnaire.pl";
793 "Starting questionnaire with default url: " + defurl);
794 desktop.checkForQuestionnaire(defurl);
801 "CMD [-noquestionnaire] executed successfully!");
802 testoutput(argparser, Arg.QUESTIONNAIRE);
805 if ((!aparser.contains("nonews")
806 && Cache.getProperty("NONEWS") == null
807 && !"false".equals(bootstrapArgs.getValue(Arg.NEWS)))
808 || "true".equals(bootstrapArgs.getValue(Arg.NEWS)))
810 desktop.checkForNews();
813 if (!aparser.contains("nohtmltemplates")
814 && Cache.getProperty("NOHTMLTEMPLATES") == null)
816 BioJsHTMLOutput.updateBioJS();
823 if (getArgParser().isMixedStyle())
825 String warning = MessageManager.formatMessage(
826 "warning.using_mixed_command_line_arguments",
827 getArgParser().getMixedExamples());
828 Console.warn(warning);
830 "Exiting due to mixed old and new command line arguments",
831 ExitCode.INVALID_ARGUMENT);
833 if (getArgParser().isOldStyle())
835 String warning = MessageManager
836 .getString("warning.using_old_command_line_arguments")
838 + "https://www.jalview.org/help/html/features/commandline.html";
839 Console.warn(warning);
844 // Run Commands from cli
845 boolean commandsSuccess = false;
846 if (!(argparser.isMixedStyle() || argparser.isOldStyle()))
848 cmds = new Commands(argparser, headlessArg);
850 commandsSuccess = cmds.argsWereParsed();
856 if (argparser.getBoolean(Arg.NOQUIT))
858 Console.warn("Completed " + Arg.HEADLESS.getName()
859 + " commands, but " + Arg.NOQUIT
860 + " is set so not quitting!");
864 Jalview.exit("Successfully completed commands in headless mode",
868 Console.info("Successfully completed commands");
874 Jalview.exit("Error when running Commands in headless mode",
875 ExitCode.ERROR_RUNNING_COMMANDS);
877 Console.warn("Error when running commands");
881 // Check if JVM and compile version might cause problems and log if it
883 if (headless && !Platform.isJS() && !LaunchUtils.checkJavaVersion())
885 Console.warn("The Java version being used (Java "
886 + LaunchUtils.getJavaVersion()
887 + ") may lead to problems. This installation of Jalview should be used with Java "
888 + LaunchUtils.getJavaCompileVersion() + ".");
891 String file = null, data = null;
893 FileFormatI format = null;
895 DataSourceType protocol = null;
897 FileLoader fileLoader = new FileLoader(!headless);
899 String groovyscript = null; // script to execute after all loading is
900 // completed one way or another
901 // extract groovy argument and execute if necessary
902 groovyscript = aparser.getValue("groovy", true);
903 file = aparser.getValue("open", true);
905 if (file == null && desktop == null && !commandsSuccess)
907 Jalview.exit("No files to open!", ExitCode.NO_FILES);
911 // Finally, deal with the remaining input data.
916 desktop.setProgressBar(
918 .getString("status.processing_commandline_args"),
919 progress = IdUtils.newId(IdType.PROGRESS));
921 Console.outPrintln("CMD [-open " + file + "] executed successfully!");
923 if (!Platform.isJS())
925 * ignore in JavaScript -- can't just file existence - could load it?
930 if (!HttpUtils.startsWithHttpOrHttps(file))
932 if (!(new File(file)).exists())
937 "Can't find file '" + file + "' in headless mode",
938 ExitCode.FILE_NOT_FOUND);
940 Console.warn("Can't find file'" + file + "'");
945 protocol = AppletFormatAdapter.checkProtocol(file);
949 format = new IdentifyFile().identify(file, protocol);
950 } catch (FileFormatException e1)
955 AlignFrame af = fileLoader.LoadFileWaitTillLoaded(file, protocol,
959 Console.outPrintln("error");
963 setCurrentAlignFrame(af);
964 data = aparser.getValue("colour", true);
967 data.replaceAll("%20", " ");
969 ColourSchemeI cs = ColourSchemeProperty.getColourScheme(
970 af.getViewport(), af.getViewport().getAlignment(), data);
975 "CMD [-colour " + data + "] executed successfully!");
980 // Must maintain ability to use the groups flag
981 data = aparser.getValue("groups", true);
984 af.parseFeaturesFile(data,
985 AppletFormatAdapter.checkProtocol(data));
986 // Console.outPrintln("Added " + data);
988 "CMD groups[-" + data + "] executed successfully!");
990 data = aparser.getValue("features", true);
993 af.parseFeaturesFile(data,
994 AppletFormatAdapter.checkProtocol(data));
995 // Console.outPrintln("Added " + data);
997 "CMD [-features " + data + "] executed successfully!");
1000 data = aparser.getValue("annotations", true);
1003 af.loadJalviewDataFile(data, null, null, null);
1004 // Console.outPrintln("Added " + data);
1006 "CMD [-annotations " + data + "] executed successfully!");
1008 // set or clear the sortbytree flag.
1009 if (aparser.contains("sortbytree"))
1011 af.getViewport().setSortByTree(true);
1012 if (af.getViewport().getSortByTree())
1014 Console.outPrintln("CMD [-sortbytree] executed successfully!");
1017 if (aparser.contains("no-annotation"))
1019 af.getViewport().setShowAnnotation(false);
1020 if (!af.getViewport().isShowAnnotation())
1022 Console.outPrintln("CMD no-annotation executed successfully!");
1025 if (aparser.contains("nosortbytree"))
1027 af.getViewport().setSortByTree(false);
1028 if (!af.getViewport().getSortByTree())
1031 "CMD [-nosortbytree] executed successfully!");
1034 data = aparser.getValue("tree", true);
1040 "CMD [-tree " + data + "] executed successfully!");
1041 NewickFile nf = new NewickFile(data,
1042 AppletFormatAdapter.checkProtocol(data));
1044 .setCurrentTree(af.showNewickTree(nf, data).getTree());
1045 } catch (IOException ex)
1047 jalview.bin.Console.errPrintln("Couldn't add tree " + data);
1048 ex.printStackTrace(System.err);
1052 if (groovyscript != null)
1054 // Execute the groovy script after we've done all the rendering stuff
1055 // and before any images or figures are generated.
1056 Console.outPrintln("Executing script " + groovyscript);
1057 executeGroovyScript(groovyscript, af);
1058 Console.outPrintln("CMD groovy[" + groovyscript
1059 + "] executed successfully!");
1060 groovyscript = null;
1062 String imageName = "unnamed.png";
1063 while (aparser.getSize() > 1)
1067 String outputFormat = aparser.nextValue();
1068 file = aparser.nextValue();
1070 if (outputFormat.equalsIgnoreCase("png"))
1072 Console.outPrintln("Creating PNG image: " + file);
1073 af.createPNG(new File(file));
1074 imageName = (new File(file)).getName();
1077 else if (outputFormat.equalsIgnoreCase("svg"))
1079 Console.outPrintln("Creating SVG image: " + file);
1080 File imageFile = new File(file);
1081 imageName = imageFile.getName();
1082 af.createSVG(imageFile);
1085 else if (outputFormat.equalsIgnoreCase("html"))
1087 File imageFile = new File(file);
1088 imageName = imageFile.getName();
1089 HtmlSvgOutput htmlSVG = new HtmlSvgOutput(af.alignPanel);
1091 Console.outPrintln("Creating HTML image: " + file);
1092 htmlSVG.exportHTML(file);
1095 else if (outputFormat.equalsIgnoreCase("biojsmsa"))
1099 jalview.bin.Console.errPrintln(
1100 "The output html file must not be null");
1105 BioJsHTMLOutput.refreshVersionInfo(
1106 BioJsHTMLOutput.BJS_TEMPLATES_LOCAL_DIRECTORY);
1107 } catch (URISyntaxException e)
1109 e.printStackTrace();
1111 BioJsHTMLOutput bjs = new BioJsHTMLOutput(af.alignPanel);
1113 "Creating BioJS MSA Viwer HTML file: " + file);
1114 bjs.exportHTML(file);
1117 else if (outputFormat.equalsIgnoreCase("imgMap"))
1119 Console.outPrintln("Creating image map: " + file);
1120 af.createImageMap(new File(file), imageName);
1123 else if (outputFormat.equalsIgnoreCase("eps"))
1125 File outputFile = new File(file);
1127 "Creating EPS file: " + outputFile.getAbsolutePath());
1128 af.createEPS(outputFile);
1132 FileFormatI outFormat = null;
1135 outFormat = FileFormats.getInstance().forName(outputFormat);
1136 } catch (Exception formatP)
1138 Console.outPrintln("Couldn't parse " + outFormat
1139 + " as a valid Jalview format string.");
1141 if (outFormat != null)
1143 if (!outFormat.isWritable())
1146 "This version of Jalview does not support alignment export as "
1151 af.saveAlignment(file, outFormat);
1152 if (af.isSaveAlignmentSuccessful())
1154 Console.outPrintln("Written alignment in "
1155 + outFormat.getName() + " format to " + file);
1159 Console.outPrintln("Error writing file " + file + " in "
1160 + outFormat.getName() + " format!!");
1164 } catch (ImageOutputException ioexc)
1167 "Unexpected error whilst exporting image to " + file);
1168 ioexc.printStackTrace();
1173 while (aparser.getSize() > 0)
1175 Console.outPrintln("Unknown arg: " + aparser.nextValue());
1180 AlignFrame startUpAlframe = null;
1181 // We'll only open the default file if the desktop is visible.
1183 // ////////////////////
1185 if (!Platform.isJS() && !headless && file == null
1186 && Cache.getDefault("SHOW_STARTUP_FILE", true)
1187 && !cmds.commandArgsProvided()
1188 && !bootstrapArgs.getBoolean(Arg.NOSTARTUPFILE))
1189 // don't open the startup file if command line args have been processed
1190 // (&& !Commands.commandArgsProvided())
1197 file = Cache.getDefault("STARTUP_FILE",
1198 Cache.getDefault("www.jalview.org", "https://www.jalview.org")
1199 + "/examples/exampleFile_2_7.jvp");
1200 if (file.equals("http://www.jalview.org/examples/exampleFile_2_3.jar")
1202 "http://www.jalview.org/examples/exampleFile_2_7.jar"))
1204 file.replace("http:", "https:");
1205 // hardwire upgrade of the startup file
1206 file.replace("_2_3", "_2_7");
1207 file.replace("2_7.jar", "2_7.jvp");
1208 // and remove the stale setting
1209 Cache.removeProperty("STARTUP_FILE");
1212 protocol = AppletFormatAdapter.checkProtocol(file);
1214 if (file.endsWith(".jar"))
1216 format = FileFormat.Jalview;
1222 format = new IdentifyFile().identify(file, protocol);
1223 } catch (FileFormatException e)
1229 startUpAlframe = fileLoader.LoadFileWaitTillLoaded(file, protocol,
1231 // don't ask to save when quitting if only the startup file has been
1233 Console.debug("Resetting up-to-date flag for startup file");
1234 startUpAlframe.getViewport().setSavedUpToDate(true);
1235 // extract groovy arguments before anything else.
1238 // Once all other stuff is done, execute any groovy scripts (in order)
1239 if (groovyscript != null)
1241 if (Cache.groovyJarsPresent())
1243 Console.outPrintln("Executing script " + groovyscript);
1244 executeGroovyScript(groovyscript, startUpAlframe);
1248 jalview.bin.Console.errPrintln(
1249 "Sorry. Groovy Support is not available, so ignoring the provided groovy script "
1253 // and finally, turn off batch mode indicator - if the desktop still exists
1254 if (desktop != null)
1258 desktop.setProgressBar(null, progress);
1260 desktop.setInBatchMode(false);
1266 private static void setLookAndFeel()
1268 if (!Platform.isJS())
1275 // property laf = "crossplatform", "system", "gtk", "metal", "nimbus",
1277 // If not set (or chosen laf fails), use the normal SystemLaF and if on
1279 // try Quaqua/Vaqua.
1280 String lafProp = System.getProperty("laf");
1281 String lafSetting = Cache.getDefault("PREFERRED_LAF", null);
1282 String laf = "none";
1283 if (lafProp != null)
1287 else if (lafSetting != null)
1291 boolean lafSet = false;
1294 case "crossplatform":
1295 lafSet = setCrossPlatformLookAndFeel();
1298 Console.error("Could not set requested laf=" + laf);
1302 lafSet = setSystemLookAndFeel();
1305 Console.error("Could not set requested laf=" + laf);
1309 lafSet = setGtkLookAndFeel();
1312 Console.error("Could not set requested laf=" + laf);
1316 lafSet = setMetalLookAndFeel();
1319 Console.error("Could not set requested laf=" + laf);
1323 lafSet = setNimbusLookAndFeel();
1326 Console.error("Could not set requested laf=" + laf);
1330 lafSet = setFlatLookAndFeel();
1333 Console.error("Could not set requested laf=" + laf);
1337 lafSet = setMacLookAndFeel();
1340 Console.error("Could not set requested laf=" + laf);
1346 Console.error("Requested laf=" + laf + " not implemented");
1350 // Flatlaf default for everyone!
1351 lafSet = setFlatLookAndFeel();
1354 setSystemLookAndFeel();
1356 if (Platform.isLinux())
1358 setLinuxLookAndFeel();
1360 if (Platform.isMac())
1362 setMacLookAndFeel();
1368 private static boolean setCrossPlatformLookAndFeel()
1370 boolean set = false;
1373 UIManager.setLookAndFeel(
1374 UIManager.getCrossPlatformLookAndFeelClassName());
1376 } catch (Exception ex)
1378 Console.error("Unexpected Look and Feel Exception");
1379 Console.error(ex.getMessage());
1380 Console.debug(Cache.getStackTraceString(ex));
1385 private static boolean setSystemLookAndFeel()
1387 boolean set = false;
1390 UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
1392 } catch (Exception ex)
1394 Console.error("Unexpected Look and Feel Exception");
1395 Console.error(ex.getMessage());
1396 Console.debug(Cache.getStackTraceString(ex));
1401 private static boolean setSpecificLookAndFeel(String name,
1402 String className, boolean nameStartsWith)
1404 boolean set = false;
1407 for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels())
1409 if (info.getName() != null && nameStartsWith
1410 ? info.getName().toLowerCase(Locale.ROOT)
1411 .startsWith(name.toLowerCase(Locale.ROOT))
1412 : info.getName().toLowerCase(Locale.ROOT)
1413 .equals(name.toLowerCase(Locale.ROOT)))
1415 className = info.getClassName();
1419 UIManager.setLookAndFeel(className);
1421 } catch (Exception ex)
1423 Console.error("Unexpected Look and Feel Exception");
1424 Console.error(ex.getMessage());
1425 Console.debug(Cache.getStackTraceString(ex));
1430 private static boolean setGtkLookAndFeel()
1432 return setSpecificLookAndFeel("gtk",
1433 "com.sun.java.swing.plaf.gtk.GTKLookAndFeel", true);
1436 private static boolean setMetalLookAndFeel()
1438 return setSpecificLookAndFeel("metal",
1439 "javax.swing.plaf.metal.MetalLookAndFeel", false);
1442 private static boolean setNimbusLookAndFeel()
1444 return setSpecificLookAndFeel("nimbus",
1445 "javax.swing.plaf.nimbus.NimbusLookAndFeel", false);
1448 private static boolean setFlatLookAndFeel()
1450 boolean set = false;
1451 if (SystemInfo.isMacOS)
1455 UIManager.setLookAndFeel(
1456 "com.formdev.flatlaf.themes.FlatMacLightLaf");
1458 Console.debug("Using FlatMacLightLaf");
1459 } catch (ClassNotFoundException | InstantiationException
1460 | IllegalAccessException | UnsupportedLookAndFeelException e)
1462 Console.debug("Exception loading FlatLightLaf", e);
1464 System.setProperty("apple.laf.useScreenMenuBar", "true");
1465 System.setProperty("apple.awt.application.name",
1466 ChannelProperties.getProperty("app_name"));
1467 System.setProperty("apple.awt.application.appearance", "system");
1468 if (SystemInfo.isMacFullWindowContentSupported
1469 && Desktop.desktop != null)
1471 Console.debug("Setting transparent title bar");
1472 Desktop.desktop.getRootPane()
1473 .putClientProperty("apple.awt.fullWindowContent", true);
1474 Desktop.desktop.getRootPane()
1475 .putClientProperty("apple.awt.transparentTitleBar", true);
1476 Desktop.desktop.getRootPane()
1477 .putClientProperty("apple.awt.fullscreenable", true);
1479 SwingUtilities.invokeLater(() -> {
1480 FlatMacLightLaf.setup();
1482 Console.debug("Using FlatMacLightLaf");
1489 UIManager.setLookAndFeel("com.formdev.flatlaf.FlatLightLaf");
1491 Console.debug("Using FlatLightLaf");
1492 } catch (ClassNotFoundException | InstantiationException
1493 | IllegalAccessException | UnsupportedLookAndFeelException e)
1495 Console.debug("Exception loading FlatLightLaf", e);
1497 // Windows specific properties here
1498 SwingUtilities.invokeLater(() -> {
1499 FlatLightLaf.setup();
1501 Console.debug("Using FlatLightLaf");
1504 else if (SystemInfo.isLinux)
1508 UIManager.setLookAndFeel("com.formdev.flatlaf.FlatLightLaf");
1510 Console.debug("Using FlatLightLaf");
1511 } catch (ClassNotFoundException | InstantiationException
1512 | IllegalAccessException | UnsupportedLookAndFeelException e)
1514 Console.debug("Exception loading FlatLightLaf", e);
1516 // enable custom window decorations
1517 JFrame.setDefaultLookAndFeelDecorated(true);
1518 JDialog.setDefaultLookAndFeelDecorated(true);
1519 SwingUtilities.invokeLater(() -> {
1520 FlatLightLaf.setup();
1522 Console.debug("Using FlatLightLaf");
1530 UIManager.setLookAndFeel("com.formdev.flatlaf.FlatLightLaf");
1532 Console.debug("Using FlatLightLaf");
1533 } catch (ClassNotFoundException | InstantiationException
1534 | IllegalAccessException | UnsupportedLookAndFeelException e)
1536 Console.debug("Exception loading FlatLightLaf", e);
1542 UIManager.put("TabbedPane.tabType", "card");
1543 UIManager.put("TabbedPane.showTabSeparators", true);
1544 UIManager.put("TabbedPane.showContentSeparator", true);
1545 // UIManager.put("TabbedPane.tabSeparatorsFullHeight", true);
1546 UIManager.put("TabbedPane.tabsOverlapBorder", true);
1547 UIManager.put("TabbedPane.hasFullBorder", true);
1548 UIManager.put("TabbedPane.tabLayoutPolicy", "scroll");
1549 UIManager.put("TabbedPane.scrollButtonsPolicy", "asNeeded");
1550 UIManager.put("TabbedPane.smoothScrolling", true);
1551 UIManager.put("TabbedPane.tabWidthMode", "compact");
1552 UIManager.put("TabbedPane.selectedBackground", Color.white);
1553 UIManager.put("TabbedPane.background", new Color(236, 236, 236));
1554 UIManager.put("TabbedPane.hoverColor", Color.lightGray);
1557 Desktop.setLiveDragMode(Cache.getDefault("FLAT_LIVE_DRAG_MODE", true));
1561 private static boolean setMacLookAndFeel()
1563 boolean set = false;
1564 System.setProperty("com.apple.mrj.application.apple.menu.about.name",
1565 ChannelProperties.getProperty("app_name"));
1566 System.setProperty("apple.laf.useScreenMenuBar", "true");
1568 * broken native LAFs on (ARM?) macbooks set = setQuaquaLookAndFeel(); if
1569 * ((!set) || !UIManager.getLookAndFeel().getClass().toString()
1570 * .toLowerCase(Locale.ROOT).contains("quaqua")) { 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() { jalview.bin.Console.outPrintln(
1591 * "Usage: jalview -open [FILE] [OUTPUT_FORMAT] [OUTPUT_FILE]\n\n" +
1592 * "-nodisplay\tRun Jalview without User Interface.\n" +
1593 * "-props FILE\tUse the given Jalview properties file instead of users default.\n"
1594 * + "-colour COLOURSCHEME\tThe colourscheme to be applied to the alignment\n" +
1595 * "-annotations FILE\tAdd precalculated annotations to the alignment.\n" +
1596 * "-tree FILE\tLoad the given newick format tree file onto the alignment\n" +
1597 * "-features FILE\tUse the given file to mark features on the alignment.\n" +
1598 * "-fasta FILE\tCreate alignment file FILE in Fasta format.\n" +
1599 * "-clustal FILE\tCreate alignment file FILE in Clustal format.\n" +
1600 * "-pfam FILE\tCreate alignment file FILE in PFAM format.\n" +
1601 * "-msf FILE\tCreate alignment file FILE in MSF format.\n" +
1602 * "-pileup FILE\tCreate alignment file FILE in Pileup format\n" +
1603 * "-pir FILE\tCreate alignment file FILE in PIR format.\n" +
1604 * "-blc FILE\tCreate alignment file FILE in BLC format.\n" +
1605 * "-json FILE\tCreate alignment file FILE in JSON format.\n" +
1606 * "-jalview FILE\tCreate alignment file FILE in Jalview format.\n" +
1607 * "-png FILE\tCreate PNG image FILE from alignment.\n" +
1608 * "-svg FILE\tCreate SVG image FILE from alignment.\n" +
1609 * "-html FILE\tCreate HTML file from alignment.\n" +
1610 * "-biojsMSA FILE\tCreate BioJS MSA Viewer HTML file from alignment.\n" +
1611 * "-imgMap FILE\tCreate HTML file FILE with image map of PNG image.\n" +
1612 * "-eps FILE\tCreate EPS file FILE from alignment.\n" +
1613 * "-questionnaire URL\tQueries the given URL for information about any Jalview user questionnaires.\n"
1614 * + "-noquestionnaire\tTurn off questionnaire check.\n" +
1615 * "-nonews\tTurn off check for Jalview news.\n" +
1616 * "-nousagestats\tTurn off analytics tracking for this session.\n" +
1617 * "-sortbytree OR -nosortbytree\tEnable or disable sorting of the given alignment by the given tree\n"
1618 * // + // "-setprop PROPERTY=VALUE\tSet the given Jalview property, // after
1619 * all other properties files have been read\n\t // (quote the 'PROPERTY=VALUE'
1620 * pair to ensure spaces are // passed in correctly)" +
1621 * "-jabaws URL\tSpecify URL for Jabaws services (e.g. for a local installation).\n"
1623 * "-fetchfrom nickname\tQuery nickname for features for the alignments and display them.\n"
1625 * "-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"
1627 * "-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"
1631 * "\n~Read documentation in Application or visit https://www.jalview.org for description of Features and Annotations file~\n\n"
1635 private static void startUsageStats(final Desktop desktop)
1638 * start a User Config prompt asking if we can log usage statistics.
1640 PromptUserConfig prompter = new PromptUserConfig(Desktop.desktop,
1642 MessageManager.getString("prompt.analytics_title"),
1643 MessageManager.getString("prompt.analytics"), new Runnable()
1648 Console.debug("Initialising analytics for usage stats.");
1649 Cache.initAnalytics();
1650 Console.debug("Tracking enabled.");
1657 Console.debug("Not enabling analytics.");
1660 desktop.addDialogThread(prompter);
1664 * Locate the given string as a file and pass it to the groovy interpreter.
1666 * @param groovyscript
1667 * the script to execute
1668 * @param jalviewContext
1669 * the Jalview Desktop object passed in to the groovy binding as the
1672 protected void executeGroovyScript(String groovyscript, AlignFrame af)
1675 * for scripts contained in files
1682 if (groovyscript.trim().equals("STDIN"))
1684 // read from stdin into a tempfile and execute it
1687 tfile = File.createTempFile("jalview", "groovy");
1688 PrintWriter outfile = new PrintWriter(
1689 new OutputStreamWriter(new FileOutputStream(tfile)));
1690 BufferedReader br = new BufferedReader(
1691 new InputStreamReader(System.in));
1693 while ((line = br.readLine()) != null)
1695 outfile.write(line + "\n");
1701 } catch (Exception ex)
1704 .errPrintln("Failed to read from STDIN into tempfile "
1705 + ((tfile == null) ? "(tempfile wasn't created)"
1706 : tfile.toString()));
1707 ex.printStackTrace();
1712 sfile = tfile.toURI().toURL();
1713 } catch (Exception x)
1715 jalview.bin.Console.errPrintln(
1716 "Unexpected Malformed URL Exception for temporary file created from STDIN: "
1718 x.printStackTrace();
1726 sfile = new URI(groovyscript).toURL();
1727 } catch (Exception x)
1729 tfile = new File(groovyscript);
1730 if (!tfile.exists())
1732 jalview.bin.Console.errPrintln(
1733 "File '" + groovyscript + "' does not exist.");
1736 if (!tfile.canRead())
1738 jalview.bin.Console.errPrintln(
1739 "File '" + groovyscript + "' cannot be read.");
1742 if (tfile.length() < 1)
1745 .errPrintln("File '" + groovyscript + "' is empty.");
1750 sfile = tfile.getAbsoluteFile().toURI().toURL();
1751 } catch (Exception ex)
1753 jalview.bin.Console.errPrintln("Failed to create a file URL for "
1754 + tfile.getAbsoluteFile());
1761 JalviewObjectI j = new JalviewObject(this);
1762 Map<String, java.lang.Object> vbinding = new HashMap<>();
1763 vbinding.put(JalviewObjectI.jalviewObjectName, j);
1764 vbinding.put(JalviewObjectI.currentAlFrameName,
1765 af != null ? af : getCurrentAlignFrame());
1766 Binding gbinding = new Binding(vbinding);
1767 GroovyScriptEngine gse = new GroovyScriptEngine(new URL[] { sfile });
1768 gse.run(sfile.toString(), gbinding);
1769 if ("STDIN".equals(groovyscript))
1771 // delete temp file that we made -
1772 // only if it was successfully executed
1775 } catch (Exception e)
1778 .errPrintln("Exception Whilst trying to execute file " + sfile
1779 + " as a groovy script.");
1780 e.printStackTrace(System.err);
1784 public static boolean isHeadlessMode()
1786 String isheadless = System.getProperty("java.awt.headless");
1787 if (isheadless != null && isheadless.equalsIgnoreCase("true"))
1795 public AlignFrame[] getAlignFrames()
1797 return desktop == null ? new AlignFrame[] { getCurrentAlignFrame() }
1798 : Desktop.getDesktopAlignFrames();
1802 * jalview.bin.Jalview.quit() will just run the non-GUI shutdownHook and exit
1807 // System.exit will run the shutdownHook first
1808 Jalview.exit("Quitting now. Bye!", ExitCode.OK);
1812 public AlignFrame getCurrentAlignFrame()
1814 return currentAlignFrame;
1817 public void setCurrentAlignFrame(AlignFrame af)
1819 this.currentAlignFrame = af;
1822 public Commands getCommands()
1827 public static void exit(String message, ExitCode ec)
1829 int exitcode = ec == ExitCode.OK ? 0 : ec.ordinal() + 1;
1830 if (Console.log == null)
1832 // Don't start the logger just to exit!
1833 if (message != null)
1837 Console.outPrintln(message);
1841 jalview.bin.Console.errPrintln(message);
1847 Console.debug("Using Jalview.exit");
1848 if (message != null)
1852 Console.info(message);
1856 Console.error(message);
1862 System.exit(exitcode);
1866 public enum ExitCode
1868 // only add new ones to the end of the list (to preserve ordinal values)
1869 OK, FILE_NOT_FOUND, FILE_NOT_READABLE, NO_FILES, INVALID_FORMAT,
1870 INVALID_ARGUMENT, INVALID_VALUE, MIXED_CLI_ARGUMENTS,
1871 ERROR_RUNNING_COMMANDS, NO_LOGGING, GROOVY_ERROR;
1874 /******************************
1876 * TEST OUTPUT METHODS
1878 * these operate only when Arg.TESTOUTPUT has been passed, and variously check
1879 * if an expected value / arg was set and report it to the test framework.
1881 ******************************/
1883 * report string values parsed/processed during tests When the Bootstrap
1884 * argument Arg.TESTOUTPUT is present - reports on debug if given s1 is not
1885 * null and not equals s2, warns if given argument is not set, and calls
1886 * testoutput(true,a,s1,s2) to report processing progress.
1889 * - ArgParser handling parsing
1891 * - Arg currently being processed
1896 protected static void testoutput(ArgParser ap, Arg a, String s1,
1899 BootstrapArgs bsa = ap.getBootstrapArgs();
1900 if (!bsa.getBoolean(Arg.TESTOUTPUT))
1902 if (!((s1 == null && s2 == null) || (s1 != null && s1.equals(s2))))
1904 Console.debug("testoutput with unmatching values '" + s1 + "' and '"
1905 + s2 + "' for arg " + a.argString());
1908 boolean isset = a.hasOption(Opt.BOOTSTRAP) ? bsa.contains(a)
1912 Console.warn("Arg '" + a.getName() + "' not set at all");
1915 testoutput(true, a, s1, s2);
1919 * report values passed via bootstrap arguments
1921 * TODO: significant code duplication with testouput(Argparser...) - move it
1924 protected static void testoutput(BootstrapArgs bsa, Arg a, String s1,
1927 if (!bsa.getBoolean(Arg.TESTOUTPUT))
1929 if (!((s1 == null && s2 == null) || (s1 != null && s1.equals(s2))))
1931 Console.debug("testoutput with unmatching values '" + s1 + "' and '"
1932 + s2 + "' for arg " + a.argString());
1935 if (!a.hasOption(Opt.BOOTSTRAP))
1937 Console.error("Non-bootstrap Arg '" + a.getName()
1938 + "' given to testoutput(BootstrapArgs bsa, Arg a, String s1, String s2) with only BootstrapArgs");
1940 if (!bsa.contains(a))
1942 Console.warn("Arg '" + a.getName() + "' not set at all");
1945 testoutput(true, a, s1, s2);
1949 * conditionally (on @param yes) report that expected value s1 was set during
1950 * CommandsTest tests
1952 private static void testoutput(boolean yes, Arg a, String s1, String s2)
1954 if (yes && ((s1 == null && s2 == null)
1955 || (s1 != null && s1.equals(s2))))
1957 Console.outPrintln("[TESTOUTPUT] arg " + a.argString() + "='" + s1
1963 * testoutput for boolean and unary values
1965 protected static void testoutput(ArgParser ap, Arg a)
1969 BootstrapArgs bsa = ap.getBootstrapArgs();
1972 if (!bsa.getBoolean(Arg.TESTOUTPUT))
1974 boolean val = a.hasOption(Opt.BOOTSTRAP) ? bsa.getBoolean(a)
1976 boolean isset = a.hasOption(Opt.BOOTSTRAP) ? bsa.contains(a)
1980 Console.warn("Arg '" + a.getName() + "' not set at all");
1986 protected static void testoutput(BootstrapArgs bsa, Arg a)
1988 if (!bsa.getBoolean(Arg.TESTOUTPUT))
1990 if (!a.hasOption(Opt.BOOTSTRAP))
1992 Console.warn("Non-bootstrap Arg '" + a.getName()
1993 + "' given to testoutput(BootstrapArgs bsa, Arg a) with only BootstrapArgs");
1996 if (!bsa.contains(a))
1998 Console.warn("Arg '" + a.getName() + "' not set at all");
2001 testoutput(bsa.getBoolean(a), a);
2004 private static void testoutput(boolean yes, Arg a)
2006 String message = null;
2007 if (a.hasOption(Opt.BOOLEAN))
2009 message = (yes ? a.argString() : a.negateArgString()) + " was set";
2011 else if (a.hasOption(Opt.UNARY))
2013 message = a.argString() + (yes ? " was set" : " was not set");
2015 Console.outPrintln("[TESTOUTPUT] arg " + message);
2018 public ArgParser getArgParser()
2023 public BootstrapArgs getBootstrapArgs()
2025 return bootstrapArgs;
2028 public static boolean isBatchMode()
2030 return getInstance() != null && (getInstance().desktop == null
2031 || getInstance().desktop.isInBatchMode());
2035 * Warning about old or mixed command line arguments
2037 private void mixedCliWarning()
2039 Jalview j = Jalview.getInstance();
2040 boolean mixedStyle = j.getArgParser() != null
2041 && j.getArgParser().isMixedStyle();
2042 String title = MessageManager.getString("label.command_line_arguments");
2045 String warning = MessageManager.formatMessage(
2046 "warning.using_mixed_command_line_arguments",
2047 j.getArgParser().getMixedExamples());
2048 String quit = MessageManager.getString("action.quit");
2050 Desktop.instance.nonBlockingDialog(title, warning, null, quit,
2051 JvOptionPane.WARNING_MESSAGE, false, false, true, 30000);
2054 "Exiting due to mixed old and new command line arguments.",
2055 ExitCode.MIXED_CLI_ARGUMENTS);
2059 private void cliWarning()
2061 Jalview j = Jalview.getInstance();
2062 Commands c = j.getCommands();
2063 boolean oldStyle = j.getArgParser() != null
2064 && j.getArgParser().isOldStyle();
2065 String title = MessageManager.getString("label.command_line_arguments");
2068 String warning = MessageManager
2069 .getString("warning.using_old_command_line_arguments");
2070 String url = "<a href=\"https://www.jalview.org/help/html/features/commandline.html\">https://www.jalview.org/help/html/features/commandline.html</a>";
2071 if (Desktop.instance != null)
2073 String cont = MessageManager.getString("label.continue");
2075 Desktop.instance.nonBlockingDialog(title, warning, url, cont,
2076 JvOptionPane.WARNING_MESSAGE, false, true, true, 30000);
2079 if (j.getCommands() != null && j.getCommands().getErrors().size() > 0)
2081 if (Desktop.instance != null)
2083 String message = MessageManager
2084 .getString("warning.the_following_errors");
2085 String ok = MessageManager.getString("action.ok");
2087 List<String> errors = j.getCommands().getErrors();
2088 for (int i = 0; i < errors.size(); i++)
2090 shortest = Math.min(shortest, errors.get(i).length());
2092 Desktop.instance.nonBlockingDialog(
2093 Math.max(message.length(), Math.min(60, shortest)),
2094 Math.min(errors.size(), 20), title, message,
2095 j.getCommands().errorsToString(), ok,
2096 JvOptionPane.WARNING_MESSAGE, true, false, true, -1);
2102 * Namespace (if set) by JalviewJS
2104 private String JSNamespace = null;
2106 private void setJSNamespace(String ns)
2108 if (!Platform.isJS())
2112 Console.outPrintln("JSNamespace set to '" + ns + "'");
2116 public String getJSNamespace()
2121 public void setJSNamespace()
2123 if (!Platform.isJS())
2129 * @j2sNative var namespace = J2S.thisApplet.__Info.namespace;
2131 * if (namespace === undefined)
2135 * System.out.println("No namespace given");