2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
23 import java.awt.Color;
24 import java.io.BufferedReader;
26 import java.io.FileOutputStream;
27 import java.io.IOException;
28 import java.io.InputStreamReader;
29 import java.io.OutputStream;
30 import java.io.OutputStreamWriter;
31 import java.io.PrintStream;
32 import java.io.PrintWriter;
33 import java.net.MalformedURLException;
35 import java.net.URISyntaxException;
37 import java.security.AllPermission;
38 import java.security.CodeSource;
39 import java.security.PermissionCollection;
40 import java.security.Permissions;
41 import java.security.Policy;
42 import java.util.ArrayList;
43 import java.util.HashMap;
44 import java.util.List;
45 import java.util.Locale;
47 import java.util.Properties;
48 import java.util.Vector;
49 import java.util.logging.ConsoleHandler;
50 import java.util.logging.Level;
51 import java.util.logging.Logger;
52 import java.util.stream.Collectors;
54 import javax.swing.JDialog;
55 import javax.swing.JFrame;
56 import javax.swing.JInternalFrame;
57 import javax.swing.JOptionPane;
58 import javax.swing.SwingUtilities;
59 import javax.swing.UIManager;
60 import javax.swing.UIManager.LookAndFeelInfo;
61 import javax.swing.UnsupportedLookAndFeelException;
63 import com.formdev.flatlaf.FlatLightLaf;
64 import com.formdev.flatlaf.themes.FlatMacLightLaf;
65 import com.formdev.flatlaf.util.SystemInfo;
66 import com.threerings.getdown.util.LaunchUtil;
68 //import edu.stanford.ejalbert.launching.IBrowserLaunching;
69 import groovy.lang.Binding;
70 import groovy.util.GroovyScriptEngine;
71 import jalview.bin.argparser.Arg;
72 import jalview.bin.argparser.Arg.Opt;
73 import jalview.bin.argparser.Arg.Type;
74 import jalview.bin.argparser.ArgParser;
75 import jalview.bin.argparser.BootstrapArgs;
76 import jalview.ext.so.SequenceOntology;
77 import jalview.gui.AlignFrame;
78 import jalview.gui.Desktop;
79 import jalview.gui.PromptUserConfig;
80 import jalview.gui.QuitHandler;
81 import jalview.gui.QuitHandler.QResponse;
82 import jalview.gui.StructureViewerBase;
83 import jalview.io.AppletFormatAdapter;
84 import jalview.io.BioJsHTMLOutput;
85 import jalview.io.DataSourceType;
86 import jalview.io.FileFormat;
87 import jalview.io.FileFormatException;
88 import jalview.io.FileFormatI;
89 import jalview.io.FileFormats;
90 import jalview.io.FileLoader;
91 import jalview.io.HtmlSvgOutput;
92 import jalview.io.IdentifyFile;
93 import jalview.io.NewickFile;
94 import jalview.io.gff.SequenceOntologyFactory;
95 import jalview.schemes.ColourSchemeI;
96 import jalview.schemes.ColourSchemeProperty;
97 import jalview.util.ChannelProperties;
98 import jalview.util.HttpUtils;
99 import jalview.util.LaunchUtils;
100 import jalview.util.MessageManager;
101 import jalview.util.Platform;
102 import jalview.ws.jws2.Jws2Discoverer;
105 * Main class for Jalview Application <br>
107 * start with: java -classpath "$PATH_TO_LIB$/*:$PATH_TO_CLASSES$" \
108 * jalview.bin.Jalview
110 * or on Windows: java -classpath "$PATH_TO_LIB$/*;$PATH_TO_CLASSES$" \
111 * jalview.bin.Jalview jalview.bin.Jalview
113 * (ensure -classpath arg is quoted to avoid shell expansion of '*' and do not
114 * embellish '*' to e.g. '*.jar')
117 * @version $Revision$
123 Platform.getURLCommandArguments();
124 Platform.addJ2SDirectDatabaseCall("https://www.jalview.org");
125 Platform.addJ2SDirectDatabaseCall("http://www.jalview.org");
126 Platform.addJ2SDirectDatabaseCall("http://www.compbio.dundee.ac.uk");
127 Platform.addJ2SDirectDatabaseCall("https://www.compbio.dundee.ac.uk");
131 * singleton instance of this class
133 private static Jalview instance;
135 private Desktop desktop;
137 protected Commands cmds;
139 public static AlignFrame currentAlignFrame;
141 public ArgParser argparser = null;
143 public BootstrapArgs bootstrapArgs = null;
145 private boolean QUIET = false;
147 public static boolean quiet()
149 return Jalview.getInstance() != null && Jalview.getInstance().QUIET;
154 if (!Platform.isJS())
161 // grab all the rights we can for the JVM
162 Policy.setPolicy(new Policy()
165 public PermissionCollection getPermissions(CodeSource codesource)
167 Permissions perms = new Permissions();
168 perms.add(new AllPermission());
173 public void refresh()
181 * keep track of feature fetching tasks.
189 * TODO: generalise to track all jalview events to orchestrate batch processing
193 private int queued = 0;
195 private int running = 0;
197 public FeatureFetcher()
202 public void addFetcher(final AlignFrame af,
203 final Vector<String> dasSources)
205 final long id = System.currentTimeMillis();
207 final FeatureFetcher us = this;
208 new Thread(new Runnable()
220 af.setProgressBar(MessageManager
221 .getString("status.das_features_being_retrived"), id);
222 af.featureSettings_actionPerformed(null);
223 af.setProgressBar(null, id);
232 public synchronized boolean allFinished()
234 return queued == 0 && running == 0;
239 public static Jalview getInstance()
245 * main class for Jalview application
248 * open <em>filename</em>
250 public static void main(String[] args)
252 // setLogging(); // BH - for event debugging in JavaScript
253 instance = new Jalview();
254 instance.doMain(args);
257 private static void logClass(String name)
259 // BH - for event debugging in JavaScript
260 ConsoleHandler consoleHandler = new ConsoleHandler();
261 consoleHandler.setLevel(Level.ALL);
262 Logger logger = Logger.getLogger(name);
263 logger.setLevel(Level.ALL);
264 logger.addHandler(consoleHandler);
267 @SuppressWarnings("unused")
268 private static void setLogging()
276 System.out.println("not in js");
279 // BH - for event debugging in JavaScript (Java mode only)
280 if (!Platform.isJS())
287 Logger.getLogger("").setLevel(Level.ALL);
288 logClass("java.awt.EventDispatchThread");
289 logClass("java.awt.EventQueue");
290 logClass("java.awt.Component");
291 logClass("java.awt.focus.Component");
292 logClass("java.awt.focus.DefaultKeyboardFocusManager");
300 void doMain(String[] args)
302 if (!Platform.isJS())
304 System.setSecurityManager(null);
307 if (args == null || args.length == 0 || (args.length == 1
308 && (args[0] == null || args[0].length() == 0)))
310 args = new String[] {};
313 // get args needed before proper ArgParser
314 bootstrapArgs = BootstrapArgs.getBootstrapArgs(args);
316 if (!Platform.isJS())
318 // are we being --quiet ?
319 if (bootstrapArgs.contains(Arg.QUIET))
322 OutputStream devNull = new OutputStream()
326 public void write(int b)
331 System.setOut(new PrintStream(devNull));
332 // redirecting stderr not working
333 if (bootstrapArgs.getList(Arg.QUIET).size() > 1)
335 System.setErr(new PrintStream(devNull));
339 if (bootstrapArgs.contains(Arg.HELP)
340 || bootstrapArgs.contains(Arg.VERSION))
346 // set individual session preferences
347 if (bootstrapArgs.contains(Arg.P))
349 for (String kev : bootstrapArgs.getValueList(Arg.P))
355 int equalsIndex = kev.indexOf(ArgParser.EQUALS);
356 if (equalsIndex > -1)
358 String key = kev.substring(0, equalsIndex);
359 String val = kev.substring(equalsIndex + 1);
360 Cache.setSessionProperty(key, val);
365 // Move any new getdown-launcher-new.jar into place over old
366 // getdown-launcher.jar
367 String appdirString = System.getProperty("getdownappdir");
368 if (appdirString != null && appdirString.length() > 0)
370 final File appdir = new File(appdirString);
377 LaunchUtil.upgradeGetdown(
378 new File(appdir, "getdown-launcher-old.jar"),
379 new File(appdir, "getdown-launcher.jar"),
380 new File(appdir, "getdown-launcher-new.jar"));
385 if (!quiet() || bootstrapArgs.contains(Arg.VERSION))
388 "Java version: " + System.getProperty("java.version"));
389 System.out.println("Java home: " + System.getProperty("java.home"));
390 System.out.println("Java arch: " + System.getProperty("os.arch") + " "
391 + System.getProperty("os.name") + " "
392 + System.getProperty("os.version"));
394 String val = System.getProperty("sys.install4jVersion");
397 System.out.println("Install4j version: " + val);
399 val = System.getProperty("installer_template_version");
402 System.out.println("Install4j template version: " + val);
404 val = System.getProperty("launcher_version");
407 System.out.println("Launcher version: " + val);
411 if (Platform.isLinux() && LaunchUtils.getJavaVersion() < 11)
413 System.setProperty("flatlaf.uiScale", "1");
416 // get bootstrap properties (mainly for the logger level)
417 Properties bootstrapProperties = Cache
418 .bootstrapProperties(bootstrapArgs.getValue(Arg.PROPS));
420 // report Jalview version
421 Cache.loadBuildProperties(
422 !quiet() || bootstrapArgs.contains(Arg.VERSION));
424 // stop now if only after --version
425 if (bootstrapArgs.contains(Arg.VERSION))
427 Jalview.exit(null, 0);
431 ArgsParser aparser = new ArgsParser(args);
434 boolean headless = false;
436 boolean headlessArg = false;
440 String logLevel = null;
441 if (bootstrapArgs.contains(Arg.TRACE))
445 else if (bootstrapArgs.contains(Arg.DEBUG))
449 if (logLevel == null && !(bootstrapProperties == null))
451 logLevel = bootstrapProperties.getProperty(Cache.JALVIEWLOGLEVEL);
453 Console.initLogger(logLevel);
454 } catch (NoClassDefFoundError error)
456 error.printStackTrace();
457 String message = "\nEssential logging libraries not found."
458 + "\nUse: java -classpath \"$PATH_TO_LIB$/*:$PATH_TO_CLASSES$\" jalview.bin.Jalview";
459 Jalview.exit(message, 0);
462 // register SIGTERM listener
463 Runtime.getRuntime().addShutdownHook(new Thread()
467 Console.debug("Running shutdown hook");
468 QuitHandler.startForceQuit();
469 boolean closeExternal = Cache
470 .getDefault("DEFAULT_CLOSE_EXTERNAL_VIEWERS", false)
471 || Cache.getDefault("ALWAYS_CLOSE_EXTERNAL_VIEWERS", false);
472 StructureViewerBase.setQuitClose(closeExternal);
475 for (JInternalFrame frame : Desktop.desktop.getAllFrames())
477 if (frame instanceof StructureViewerBase)
479 ((StructureViewerBase) frame).closeViewer(closeExternal);
484 if (QuitHandler.gotQuitResponse() == QResponse.CANCEL_QUIT)
486 // Got to here by a SIGTERM signal.
487 // Note we will not actually cancel the quit from here -- it's too
488 // late -- but we can wait for saving files and close external viewers
490 // Close viewers/Leave viewers open
491 Console.debug("Checking for saving files");
492 QuitHandler.getQuitResponse(false);
496 Console.debug("Nothing more to do");
498 Console.debug("Exiting, bye!");
499 // shutdownHook cannot be cancelled, JVM will now halt
503 String usrPropsFile = bootstrapArgs.contains(Arg.PROPS)
504 ? bootstrapArgs.getValue(Arg.PROPS)
505 : aparser.getValue("props");
506 // if usrPropsFile == null, loadProperties will use the Channel
508 Cache.loadProperties(usrPropsFile);
509 if (usrPropsFile != null)
512 "CMD [-props " + usrPropsFile + "] executed successfully!");
513 testoutput(bootstrapArgs, Arg.PROPS,
514 "test/jalview/bin/testProps.jvprops", usrPropsFile);
517 // --argfile=... -- OVERRIDES ALL NON-BOOTSTRAP ARGS
518 if (bootstrapArgs.contains(Arg.ARGFILE))
520 argparser = ArgParser.parseArgFiles(
521 bootstrapArgs.getValueList(Arg.ARGFILE),
522 bootstrapArgs.getBoolean(Arg.INITSUBSTITUTIONS),
527 argparser = new ArgParser(args,
528 bootstrapArgs.getBoolean(Arg.INITSUBSTITUTIONS),
532 if (!Platform.isJS())
539 if (bootstrapArgs.contains(Arg.HELP))
541 List<Map.Entry<Type, String>> helpArgs = bootstrapArgs
543 System.out.println(Arg.usage(helpArgs.stream().map(e -> e.getKey())
544 .collect(Collectors.toList())));
545 Jalview.exit(null, 0);
547 if (aparser.contains("help") || aparser.contains("h"))
550 * Now using new usage statement.
553 System.out.println(Arg.usage());
554 Jalview.exit(null, 0);
558 headlessArg = bootstrapArgs.isHeadless();
561 System.setProperty("java.awt.headless", "true");
564 if (aparser.contains("nodisplay") || aparser.contains("nogui")
565 || aparser.contains("headless"))
567 System.setProperty("java.awt.headless", "true");
572 // allow https handshakes to download intermediate certs if necessary
573 System.setProperty("com.sun.security.enableAIAcaIssuers", "true");
575 String jabawsUrl = bootstrapArgs.getValue(Arg.JABAWS);
576 if (jabawsUrl == null)
577 jabawsUrl = aparser.getValue("jabaws");
578 if (jabawsUrl != null)
582 Jws2Discoverer.getDiscoverer().setPreferredUrl(jabawsUrl);
584 "CMD [-jabaws " + jabawsUrl + "] executed successfully!");
585 testoutput(bootstrapArgs, Arg.JABAWS,
586 "http://www.compbio.dundee.ac.uk/jabaws", jabawsUrl);
587 } catch (MalformedURLException e)
590 "Invalid jabaws parameter: " + jabawsUrl + " ignored");
595 List<String> setprops = new ArrayList<>();
596 if (bootstrapArgs.contains(Arg.SETPROP))
598 setprops = bootstrapArgs.getValueList(Arg.SETPROP);
602 String sp = aparser.getValue("setprop");
606 sp = aparser.getValue("setprop");
609 for (String setprop : setprops)
611 int p = setprop.indexOf('=');
615 .println("Ignoring invalid setprop argument : " + setprop);
619 System.out.println("Executing setprop argument: " + setprop);
622 Cache.setProperty(setprop.substring(0, p),
623 setprop.substring(p + 1));
625 // DISABLED FOR SECURITY REASONS
626 // TODO: add a property to allow properties to be overriden by cli args
627 // Cache.setProperty(setprop.substring(0,p), setprop.substring(p+1));
630 if (System.getProperty("java.awt.headless") != null
631 && System.getProperty("java.awt.headless").equals("true"))
635 System.setProperty("http.agent",
636 "Jalview Desktop/" + Cache.getDefault("VERSION", "Unknown"));
640 Console.initLogger();
643 NoClassDefFoundError error)
645 error.printStackTrace();
646 String message = "\nEssential logging libraries not found."
647 + "\nUse: java -classpath \"$PATH_TO_LIB$/*:$PATH_TO_CLASSES$\" jalview.bin.Jalview";
648 Jalview.exit(message, 0);
652 if (!(headless || headlessArg))
656 * configure 'full' SO model if preferences say to, else use the default (full SO)
657 * - as JS currently doesn't have OBO parsing, it must use 'Lite' version
659 boolean soDefault = !Platform.isJS();
660 if (Cache.getDefault("USE_FULL_SO", soDefault))
662 SequenceOntologyFactory.setInstance(new SequenceOntology());
665 if (!(headless || headlessArg))
667 Desktop.nosplash = "false".equals(bootstrapArgs.getValue(Arg.SPLASH))
668 || aparser.contains("nosplash")
669 || Cache.getDefault("SPLASH", "true").equals("false");
670 desktop = new Desktop();
671 desktop.setInBatchMode(true); // indicate we are starting up
675 JalviewTaskbar.setTaskbar(this);
676 } catch (Exception e)
678 Console.info("Cannot set Taskbar");
679 Console.error(e.getMessage());
680 // e.printStackTrace();
681 } catch (Throwable t)
683 Console.info("Cannot set Taskbar");
684 Console.error(t.getMessage());
685 // t.printStackTrace();
688 // set Proxy settings before all the internet calls
689 Cache.setProxyPropertiesFromPreferences();
691 desktop.setVisible(true);
693 if (!Platform.isJS())
702 * Check to see that the JVM version being run is suitable for the Java
703 * version this Jalview was compiled for. Popup a warning if not.
705 if (!LaunchUtils.checkJavaVersion())
707 Console.warn("The Java version being used (Java "
708 + LaunchUtils.getJavaVersion()
709 + ") may lead to problems. This installation of Jalview should be used with Java "
710 + LaunchUtils.getJavaCompileVersion() + ".");
713 .getBooleanUserPreference("IGNORE_JVM_WARNING_POPUP"))
716 MessageManager.getString("label.continue") };
717 JOptionPane.showOptionDialog(null,
718 MessageManager.formatMessage(
719 "warning.wrong_jvm_version_message",
720 LaunchUtils.getJavaVersion(),
721 LaunchUtils.getJavaCompileVersion()),
723 .getString("warning.wrong_jvm_version_title"),
724 JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE,
725 null, options, options[0]);
729 boolean webservicediscovery = bootstrapArgs
730 .getBoolean(Arg.WEBSERVICEDISCOVERY);
731 if (aparser.contains("nowebservicediscovery"))
732 webservicediscovery = false;
733 if (webservicediscovery)
735 desktop.startServiceDiscovery();
739 testoutput(argparser, Arg.WEBSERVICEDISCOVERY);
742 boolean usagestats = !bootstrapArgs.getBoolean(Arg.NOUSAGESTATS);
743 if (aparser.contains("nousagestats"))
747 startUsageStats(desktop);
748 testoutput(argparser, Arg.NOUSAGESTATS);
752 System.out.println("CMD [-nousagestats] executed successfully!");
753 testoutput(argparser, Arg.NOUSAGESTATS);
756 boolean questionnaire = bootstrapArgs.getBoolean(Arg.QUESTIONNAIRE);
757 if (aparser.contains("noquestionnaire"))
758 questionnaire = false;
761 String url = aparser.getValue("questionnaire");
764 // Start the desktop questionnaire prompter with the specified
766 Console.debug("Starting questionnaire url at " + url);
767 desktop.checkForQuestionnaire(url);
768 System.out.println("CMD questionnaire[-" + url
769 + "] executed successfully!");
773 if (Cache.getProperty("NOQUESTIONNAIRES") == null)
775 // Start the desktop questionnaire prompter with the specified
778 // "http://anaplog.compbio.dundee.ac.uk/cgi-bin/questionnaire.pl";
780 String defurl = "https://www.jalview.org/cgi-bin/questionnaire.pl";
782 "Starting questionnaire with default url: " + defurl);
783 desktop.checkForQuestionnaire(defurl);
790 .println("CMD [-noquestionnaire] executed successfully!");
791 testoutput(argparser, Arg.QUESTIONNAIRE);
794 if ((!aparser.contains("nonews")
795 && Cache.getProperty("NONEWS") == null
796 && !"false".equals(bootstrapArgs.getValue(Arg.NEWS)))
797 || "true".equals(bootstrapArgs.getValue(Arg.NEWS)))
799 desktop.checkForNews();
802 if (!aparser.contains("nohtmltemplates")
803 && Cache.getProperty("NOHTMLTEMPLATES") == null)
805 BioJsHTMLOutput.updateBioJS();
809 // Run Commands from cli
810 cmds = new Commands(argparser, headlessArg);
811 boolean commandsSuccess = cmds.argsWereParsed();
816 if (argparser.getBoolean(Arg.NOQUIT))
819 "Completed " + Arg.HEADLESS.getName() + " commands, but "
820 + Arg.NOQUIT + " is set so not quitting!");
824 Jalview.exit("Successfully completed commands in headless mode",
828 Console.info("Successfully completed commands");
834 Jalview.exit("Error when running Commands in headless mode", 1);
836 Console.warn("Error when running commands");
839 // Check if JVM and compile version might cause problems and log if it
841 if (headless && !Platform.isJS() && !LaunchUtils.checkJavaVersion())
843 Console.warn("The Java version being used (Java "
844 + LaunchUtils.getJavaVersion()
845 + ") may lead to problems. This installation of Jalview should be used with Java "
846 + LaunchUtils.getJavaCompileVersion() + ".");
849 String file = null, data = null;
851 FileFormatI format = null;
853 DataSourceType protocol = null;
855 FileLoader fileLoader = new FileLoader(!headless);
857 String groovyscript = null; // script to execute after all loading is
858 // completed one way or another
859 // extract groovy argument and execute if necessary
860 groovyscript = aparser.getValue("groovy", true);
861 file = aparser.getValue("open", true);
863 if (file == null && desktop == null && !commandsSuccess)
865 Jalview.exit("No files to open!", 1);
869 // Finally, deal with the remaining input data.
874 desktop.setProgressBar(
876 .getString("status.processing_commandline_args"),
877 progress = System.currentTimeMillis());
879 System.out.println("CMD [-open " + file + "] executed successfully!");
881 if (!Platform.isJS())
883 * ignore in JavaScript -- can't just file existence - could load it?
888 if (!HttpUtils.startsWithHttpOrHttps(file))
890 if (!(new File(file)).exists())
895 "Can't find file '" + file + "' in headless mode", 1);
897 Console.warn("Can't find file'" + file + "'");
902 protocol = AppletFormatAdapter.checkProtocol(file);
906 format = new IdentifyFile().identify(file, protocol);
907 } catch (FileFormatException e1)
912 AlignFrame af = fileLoader.LoadFileWaitTillLoaded(file, protocol,
916 System.out.println("error");
920 setCurrentAlignFrame(af);
921 data = aparser.getValue("colour", true);
924 data.replaceAll("%20", " ");
926 ColourSchemeI cs = ColourSchemeProperty.getColourScheme(
927 af.getViewport(), af.getViewport().getAlignment(), data);
932 "CMD [-colour " + data + "] executed successfully!");
937 // Must maintain ability to use the groups flag
938 data = aparser.getValue("groups", true);
941 af.parseFeaturesFile(data,
942 AppletFormatAdapter.checkProtocol(data));
943 // System.out.println("Added " + data);
945 "CMD groups[-" + data + "] executed successfully!");
947 data = aparser.getValue("features", true);
950 af.parseFeaturesFile(data,
951 AppletFormatAdapter.checkProtocol(data));
952 // System.out.println("Added " + data);
954 "CMD [-features " + data + "] executed successfully!");
957 data = aparser.getValue("annotations", true);
960 af.loadJalviewDataFile(data, null, null, null);
961 // System.out.println("Added " + data);
963 "CMD [-annotations " + data + "] executed successfully!");
965 // set or clear the sortbytree flag.
966 if (aparser.contains("sortbytree"))
968 af.getViewport().setSortByTree(true);
969 if (af.getViewport().getSortByTree())
971 System.out.println("CMD [-sortbytree] executed successfully!");
974 if (aparser.contains("no-annotation"))
976 af.getViewport().setShowAnnotation(false);
977 if (!af.getViewport().isShowAnnotation())
979 System.out.println("CMD no-annotation executed successfully!");
982 if (aparser.contains("nosortbytree"))
984 af.getViewport().setSortByTree(false);
985 if (!af.getViewport().getSortByTree())
988 .println("CMD [-nosortbytree] executed successfully!");
991 data = aparser.getValue("tree", true);
997 "CMD [-tree " + data + "] executed successfully!");
998 NewickFile nf = new NewickFile(data,
999 AppletFormatAdapter.checkProtocol(data));
1001 .setCurrentTree(af.showNewickTree(nf, data).getTree());
1002 } catch (IOException ex)
1004 System.err.println("Couldn't add tree " + data);
1005 ex.printStackTrace(System.err);
1009 if (groovyscript != null)
1011 // Execute the groovy script after we've done all the rendering stuff
1012 // and before any images or figures are generated.
1013 System.out.println("Executing script " + groovyscript);
1014 executeGroovyScript(groovyscript, af);
1015 System.out.println("CMD groovy[" + groovyscript
1016 + "] executed successfully!");
1017 groovyscript = null;
1019 String imageName = "unnamed.png";
1020 while (aparser.getSize() > 1)
1022 String outputFormat = aparser.nextValue();
1023 file = aparser.nextValue();
1025 if (outputFormat.equalsIgnoreCase("png"))
1027 af.createPNG(new File(file));
1028 imageName = (new File(file)).getName();
1029 System.out.println("Creating PNG image: " + file);
1032 else if (outputFormat.equalsIgnoreCase("svg"))
1034 File imageFile = new File(file);
1035 imageName = imageFile.getName();
1036 af.createSVG(imageFile);
1037 System.out.println("Creating SVG image: " + file);
1040 else if (outputFormat.equalsIgnoreCase("html"))
1042 File imageFile = new File(file);
1043 imageName = imageFile.getName();
1044 HtmlSvgOutput htmlSVG = new HtmlSvgOutput(af.alignPanel);
1045 htmlSVG.exportHTML(file);
1047 System.out.println("Creating HTML image: " + file);
1050 else if (outputFormat.equalsIgnoreCase("biojsmsa"))
1054 System.err.println("The output html file must not be null");
1059 BioJsHTMLOutput.refreshVersionInfo(
1060 BioJsHTMLOutput.BJS_TEMPLATES_LOCAL_DIRECTORY);
1061 } catch (URISyntaxException e)
1063 e.printStackTrace();
1065 BioJsHTMLOutput bjs = new BioJsHTMLOutput(af.alignPanel);
1066 bjs.exportHTML(file);
1068 .println("Creating BioJS MSA Viwer HTML file: " + file);
1071 else if (outputFormat.equalsIgnoreCase("imgMap"))
1073 af.createImageMap(new File(file), imageName);
1074 System.out.println("Creating image map: " + file);
1077 else if (outputFormat.equalsIgnoreCase("eps"))
1079 File outputFile = new File(file);
1081 "Creating EPS file: " + outputFile.getAbsolutePath());
1082 af.createEPS(outputFile);
1085 FileFormatI outFormat = null;
1088 outFormat = FileFormats.getInstance().forName(outputFormat);
1089 } catch (Exception formatP)
1091 System.out.println("Couldn't parse " + outFormat
1092 + " as a valid Jalview format string.");
1094 if (outFormat != null)
1096 if (!outFormat.isWritable())
1099 "This version of Jalview does not support alignment export as "
1104 af.saveAlignment(file, outFormat);
1105 if (af.isSaveAlignmentSuccessful())
1107 System.out.println("Written alignment in "
1108 + outFormat.getName() + " format to " + file);
1112 System.out.println("Error writing file " + file + " in "
1113 + outFormat.getName() + " format!!");
1120 while (aparser.getSize() > 0)
1122 System.out.println("Unknown arg: " + aparser.nextValue());
1127 AlignFrame startUpAlframe = null;
1128 // We'll only open the default file if the desktop is visible.
1130 // ////////////////////
1132 if (!Platform.isJS() && !headless && file == null
1133 && Cache.getDefault("SHOW_STARTUP_FILE", true)
1134 && !cmds.commandArgsProvided()
1135 && !bootstrapArgs.getBoolean(Arg.NOSTARTUPFILE))
1136 // don't open the startup file if command line args have been processed
1137 // (&& !Commands.commandArgsProvided())
1144 file = Cache.getDefault("STARTUP_FILE",
1145 Cache.getDefault("www.jalview.org", "https://www.jalview.org")
1146 + "/examples/exampleFile_2_7.jvp");
1147 if (file.equals("http://www.jalview.org/examples/exampleFile_2_3.jar")
1149 "http://www.jalview.org/examples/exampleFile_2_7.jar"))
1151 file.replace("http:", "https:");
1152 // hardwire upgrade of the startup file
1153 file.replace("_2_3", "_2_7");
1154 file.replace("2_7.jar", "2_7.jvp");
1155 // and remove the stale setting
1156 Cache.removeProperty("STARTUP_FILE");
1159 protocol = AppletFormatAdapter.checkProtocol(file);
1161 if (file.endsWith(".jar"))
1163 format = FileFormat.Jalview;
1169 format = new IdentifyFile().identify(file, protocol);
1170 } catch (FileFormatException e)
1176 startUpAlframe = fileLoader.LoadFileWaitTillLoaded(file, protocol,
1178 // don't ask to save when quitting if only the startup file has been
1180 Console.debug("Resetting up-to-date flag for startup file");
1181 startUpAlframe.getViewport().setSavedUpToDate(true);
1182 // extract groovy arguments before anything else.
1185 // Once all other stuff is done, execute any groovy scripts (in order)
1186 if (groovyscript != null)
1188 if (Cache.groovyJarsPresent())
1190 System.out.println("Executing script " + groovyscript);
1191 executeGroovyScript(groovyscript, startUpAlframe);
1196 "Sorry. Groovy Support is not available, so ignoring the provided groovy script "
1200 // and finally, turn off batch mode indicator - if the desktop still exists
1201 if (desktop != null)
1205 desktop.setProgressBar(null, progress);
1207 desktop.setInBatchMode(false);
1211 private static void setLookAndFeel()
1213 // property laf = "crossplatform", "system", "gtk", "metal", "nimbus",
1215 // If not set (or chosen laf fails), use the normal SystemLaF and if on Mac,
1216 // try Quaqua/Vaqua.
1217 String lafProp = System.getProperty("laf");
1218 String lafSetting = Cache.getDefault("PREFERRED_LAF", null);
1219 String laf = "none";
1220 if (lafProp != null)
1224 else if (lafSetting != null)
1228 boolean lafSet = false;
1231 case "crossplatform":
1232 lafSet = setCrossPlatformLookAndFeel();
1235 Console.error("Could not set requested laf=" + laf);
1239 lafSet = setSystemLookAndFeel();
1242 Console.error("Could not set requested laf=" + laf);
1246 lafSet = setGtkLookAndFeel();
1249 Console.error("Could not set requested laf=" + laf);
1253 lafSet = setMetalLookAndFeel();
1256 Console.error("Could not set requested laf=" + laf);
1260 lafSet = setNimbusLookAndFeel();
1263 Console.error("Could not set requested laf=" + laf);
1267 lafSet = setFlatLookAndFeel();
1270 Console.error("Could not set requested laf=" + laf);
1274 lafSet = setMacLookAndFeel();
1277 Console.error("Could not set requested laf=" + laf);
1283 Console.error("Requested laf=" + laf + " not implemented");
1287 // Flatlaf default for everyone!
1288 lafSet = setFlatLookAndFeel();
1291 setSystemLookAndFeel();
1293 if (Platform.isLinux())
1295 setLinuxLookAndFeel();
1297 if (Platform.isMac())
1299 setMacLookAndFeel();
1304 private static boolean setCrossPlatformLookAndFeel()
1306 boolean set = false;
1309 UIManager.setLookAndFeel(
1310 UIManager.getCrossPlatformLookAndFeelClassName());
1312 } catch (Exception ex)
1314 Console.error("Unexpected Look and Feel Exception");
1315 Console.error(ex.getMessage());
1316 Console.debug(Cache.getStackTraceString(ex));
1321 private static boolean setSystemLookAndFeel()
1323 boolean set = false;
1326 UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
1328 } catch (Exception ex)
1330 Console.error("Unexpected Look and Feel Exception");
1331 Console.error(ex.getMessage());
1332 Console.debug(Cache.getStackTraceString(ex));
1337 private static boolean setSpecificLookAndFeel(String name,
1338 String className, boolean nameStartsWith)
1340 boolean set = false;
1343 for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels())
1345 if (info.getName() != null && nameStartsWith
1346 ? info.getName().toLowerCase(Locale.ROOT)
1347 .startsWith(name.toLowerCase(Locale.ROOT))
1348 : info.getName().toLowerCase(Locale.ROOT)
1349 .equals(name.toLowerCase(Locale.ROOT)))
1351 className = info.getClassName();
1355 UIManager.setLookAndFeel(className);
1357 } catch (Exception ex)
1359 Console.error("Unexpected Look and Feel Exception");
1360 Console.error(ex.getMessage());
1361 Console.debug(Cache.getStackTraceString(ex));
1366 private static boolean setGtkLookAndFeel()
1368 return setSpecificLookAndFeel("gtk",
1369 "com.sun.java.swing.plaf.gtk.GTKLookAndFeel", true);
1372 private static boolean setMetalLookAndFeel()
1374 return setSpecificLookAndFeel("metal",
1375 "javax.swing.plaf.metal.MetalLookAndFeel", false);
1378 private static boolean setNimbusLookAndFeel()
1380 return setSpecificLookAndFeel("nimbus",
1381 "javax.swing.plaf.nimbus.NimbusLookAndFeel", false);
1384 private static boolean setFlatLookAndFeel()
1386 boolean set = false;
1387 if (SystemInfo.isMacOS)
1391 UIManager.setLookAndFeel(
1392 "com.formdev.flatlaf.themes.FlatMacLightLaf");
1394 Console.debug("Using FlatMacLightLaf");
1395 } catch (ClassNotFoundException | InstantiationException
1396 | IllegalAccessException | UnsupportedLookAndFeelException e)
1398 Console.debug("Exception loading FlatLightLaf", e);
1400 System.setProperty("apple.laf.useScreenMenuBar", "true");
1401 System.setProperty("apple.awt.application.name",
1402 ChannelProperties.getProperty("app_name"));
1403 System.setProperty("apple.awt.application.appearance", "system");
1404 if (SystemInfo.isMacFullWindowContentSupported
1405 && Desktop.desktop != null)
1407 Console.debug("Setting transparent title bar");
1408 Desktop.desktop.getRootPane()
1409 .putClientProperty("apple.awt.fullWindowContent", true);
1410 Desktop.desktop.getRootPane()
1411 .putClientProperty("apple.awt.transparentTitleBar", true);
1412 Desktop.desktop.getRootPane()
1413 .putClientProperty("apple.awt.fullscreenable", true);
1415 SwingUtilities.invokeLater(() -> {
1416 FlatMacLightLaf.setup();
1418 Console.debug("Using FlatMacLightLaf");
1425 UIManager.setLookAndFeel("com.formdev.flatlaf.FlatLightLaf");
1427 Console.debug("Using FlatLightLaf");
1428 } catch (ClassNotFoundException | InstantiationException
1429 | IllegalAccessException | UnsupportedLookAndFeelException e)
1431 Console.debug("Exception loading FlatLightLaf", e);
1433 // Windows specific properties here
1434 SwingUtilities.invokeLater(() -> {
1435 FlatLightLaf.setup();
1437 Console.debug("Using FlatLightLaf");
1440 else if (SystemInfo.isLinux)
1444 UIManager.setLookAndFeel("com.formdev.flatlaf.FlatLightLaf");
1446 Console.debug("Using FlatLightLaf");
1447 } catch (ClassNotFoundException | InstantiationException
1448 | IllegalAccessException | UnsupportedLookAndFeelException e)
1450 Console.debug("Exception loading FlatLightLaf", e);
1452 // enable custom window decorations
1453 JFrame.setDefaultLookAndFeelDecorated(true);
1454 JDialog.setDefaultLookAndFeelDecorated(true);
1455 SwingUtilities.invokeLater(() -> {
1456 FlatLightLaf.setup();
1458 Console.debug("Using FlatLightLaf");
1466 UIManager.setLookAndFeel("com.formdev.flatlaf.FlatLightLaf");
1468 Console.debug("Using FlatLightLaf");
1469 } catch (ClassNotFoundException | InstantiationException
1470 | IllegalAccessException | UnsupportedLookAndFeelException e)
1472 Console.debug("Exception loading FlatLightLaf", e);
1478 UIManager.put("TabbedPane.tabType", "card");
1479 UIManager.put("TabbedPane.showTabSeparators", true);
1480 UIManager.put("TabbedPane.showContentSeparator", true);
1481 UIManager.put("TabbedPane.tabSeparatorsFullHeight", true);
1482 UIManager.put("TabbedPane.tabsOverlapBorder", true);
1483 UIManager.put("TabbedPane.hasFullBorder", true);
1484 UIManager.put("TabbedPane.tabLayoutPolicy", "scroll");
1485 UIManager.put("TabbedPane.scrollButtonsPolicy", "asNeeded");
1486 UIManager.put("TabbedPane.smoothScrolling", true);
1487 UIManager.put("TabbedPane.tabWidthMode", "compact");
1488 UIManager.put("TabbedPane.selectedBackground", Color.white);
1489 UIManager.put("TabbedPane.background", new Color(236, 236, 236));
1490 UIManager.put("TabbedPane.hoverColor", Color.lightGray);
1493 Desktop.setLiveDragMode(Cache.getDefault("FLAT_LIVE_DRAG_MODE", true));
1497 private static boolean setMacLookAndFeel()
1499 boolean set = false;
1500 System.setProperty("com.apple.mrj.application.apple.menu.about.name",
1501 ChannelProperties.getProperty("app_name"));
1502 System.setProperty("apple.laf.useScreenMenuBar", "true");
1504 * broken native LAFs on (ARM?) macbooks
1505 set = setQuaquaLookAndFeel();
1506 if ((!set) || !UIManager.getLookAndFeel().getClass().toString()
1507 .toLowerCase(Locale.ROOT).contains("quaqua"))
1509 set = setVaquaLookAndFeel();
1512 set = setFlatLookAndFeel();
1516 private static boolean setLinuxLookAndFeel()
1518 boolean set = false;
1519 set = setFlatLookAndFeel();
1521 set = setMetalLookAndFeel();
1522 // avoid GtkLookAndFeel -- not good results especially on HiDPI
1524 set = setNimbusLookAndFeel();
1529 private static void showUsage()
1532 "Usage: jalview -open [FILE] [OUTPUT_FORMAT] [OUTPUT_FILE]\n\n"
1533 + "-nodisplay\tRun Jalview without User Interface.\n"
1534 + "-props FILE\tUse the given Jalview properties file instead of users default.\n"
1535 + "-colour COLOURSCHEME\tThe colourscheme to be applied to the alignment\n"
1536 + "-annotations FILE\tAdd precalculated annotations to the alignment.\n"
1537 + "-tree FILE\tLoad the given newick format tree file onto the alignment\n"
1538 + "-features FILE\tUse the given file to mark features on the alignment.\n"
1539 + "-fasta FILE\tCreate alignment file FILE in Fasta format.\n"
1540 + "-clustal FILE\tCreate alignment file FILE in Clustal format.\n"
1541 + "-pfam FILE\tCreate alignment file FILE in PFAM format.\n"
1542 + "-msf FILE\tCreate alignment file FILE in MSF format.\n"
1543 + "-pileup FILE\tCreate alignment file FILE in Pileup format\n"
1544 + "-pir FILE\tCreate alignment file FILE in PIR format.\n"
1545 + "-blc FILE\tCreate alignment file FILE in BLC format.\n"
1546 + "-json FILE\tCreate alignment file FILE in JSON format.\n"
1547 + "-jalview FILE\tCreate alignment file FILE in Jalview format.\n"
1548 + "-png FILE\tCreate PNG image FILE from alignment.\n"
1549 + "-svg FILE\tCreate SVG image FILE from alignment.\n"
1550 + "-html FILE\tCreate HTML file from alignment.\n"
1551 + "-biojsMSA FILE\tCreate BioJS MSA Viewer HTML file from alignment.\n"
1552 + "-imgMap FILE\tCreate HTML file FILE with image map of PNG image.\n"
1553 + "-eps FILE\tCreate EPS file FILE from alignment.\n"
1554 + "-questionnaire URL\tQueries the given URL for information about any Jalview user questionnaires.\n"
1555 + "-noquestionnaire\tTurn off questionnaire check.\n"
1556 + "-nonews\tTurn off check for Jalview news.\n"
1557 + "-nousagestats\tTurn off google analytics tracking for this session.\n"
1558 + "-sortbytree OR -nosortbytree\tEnable or disable sorting of the given alignment by the given tree\n"
1560 // "-setprop PROPERTY=VALUE\tSet the given Jalview property,
1561 // after all other properties files have been read\n\t
1562 // (quote the 'PROPERTY=VALUE' pair to ensure spaces are
1563 // passed in correctly)"
1564 + "-jabaws URL\tSpecify URL for Jabaws services (e.g. for a local installation).\n"
1565 + "-fetchfrom nickname\tQuery nickname for features for the alignments and display them.\n"
1566 + "-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"
1567 + "-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"
1568 + "-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"
1569 + "\n~Read documentation in Application or visit https://www.jalview.org for description of Features and Annotations file~\n\n");
1573 private static void startUsageStats(final Desktop desktop)
1576 * start a User Config prompt asking if we can log usage statistics.
1578 PromptUserConfig prompter = new PromptUserConfig(Desktop.desktop,
1579 "USAGESTATS", "Jalview Usage Statistics",
1580 "Do you want to help make Jalview better by enabling "
1581 + "the collection of usage statistics with Google Analytics ?"
1582 + "\n\n(you can enable or disable usage tracking in the preferences)",
1589 "Initialising googletracker for usage stats.");
1590 Cache.initGoogleTracker();
1591 Console.debug("Tracking enabled.");
1598 Console.debug("Not enabling Google Tracking.");
1601 desktop.addDialogThread(prompter);
1605 * Locate the given string as a file and pass it to the groovy interpreter.
1607 * @param groovyscript
1608 * the script to execute
1609 * @param jalviewContext
1610 * the Jalview Desktop object passed in to the groovy binding as the
1613 protected void executeGroovyScript(String groovyscript, AlignFrame af)
1616 * for scripts contained in files
1623 if (groovyscript.trim().equals("STDIN"))
1625 // read from stdin into a tempfile and execute it
1628 tfile = File.createTempFile("jalview", "groovy");
1629 PrintWriter outfile = new PrintWriter(
1630 new OutputStreamWriter(new FileOutputStream(tfile)));
1631 BufferedReader br = new BufferedReader(
1632 new InputStreamReader(System.in));
1634 while ((line = br.readLine()) != null)
1636 outfile.write(line + "\n");
1642 } catch (Exception ex)
1644 System.err.println("Failed to read from STDIN into tempfile "
1645 + ((tfile == null) ? "(tempfile wasn't created)"
1646 : tfile.toString()));
1647 ex.printStackTrace();
1652 sfile = tfile.toURI().toURL();
1653 } catch (Exception x)
1656 "Unexpected Malformed URL Exception for temporary file created from STDIN: "
1658 x.printStackTrace();
1666 sfile = new URI(groovyscript).toURL();
1667 } catch (Exception x)
1669 tfile = new File(groovyscript);
1670 if (!tfile.exists())
1672 System.err.println("File '" + groovyscript + "' does not exist.");
1675 if (!tfile.canRead())
1677 System.err.println("File '" + groovyscript + "' cannot be read.");
1680 if (tfile.length() < 1)
1682 System.err.println("File '" + groovyscript + "' is empty.");
1687 sfile = tfile.getAbsoluteFile().toURI().toURL();
1688 } catch (Exception ex)
1690 System.err.println("Failed to create a file URL for "
1691 + tfile.getAbsoluteFile());
1698 Map<String, java.lang.Object> vbinding = new HashMap<>();
1699 vbinding.put("Jalview", this);
1702 vbinding.put("currentAlFrame", af);
1704 Binding gbinding = new Binding(vbinding);
1705 GroovyScriptEngine gse = new GroovyScriptEngine(new URL[] { sfile });
1706 gse.run(sfile.toString(), gbinding);
1707 if ("STDIN".equals(groovyscript))
1709 // delete temp file that we made -
1710 // only if it was successfully executed
1713 } catch (Exception e)
1715 System.err.println("Exception Whilst trying to execute file " + sfile
1716 + " as a groovy script.");
1717 e.printStackTrace(System.err);
1722 public static boolean isHeadlessMode()
1724 String isheadless = System.getProperty("java.awt.headless");
1725 if (isheadless != null && isheadless.equalsIgnoreCase("true"))
1732 public AlignFrame[] getAlignFrames()
1734 return desktop == null ? new AlignFrame[] { getCurrentAlignFrame() }
1735 : Desktop.getAlignFrames();
1740 * jalview.bin.Jalview.quit() will just run the non-GUI shutdownHook and exit
1744 // System.exit will run the shutdownHook first
1745 Jalview.exit("Quitting now. Bye!", 0);
1748 public static AlignFrame getCurrentAlignFrame()
1750 return Jalview.currentAlignFrame;
1753 public static void setCurrentAlignFrame(AlignFrame currentAlignFrame)
1755 Jalview.currentAlignFrame = currentAlignFrame;
1758 protected Commands getCommands()
1763 public static void exit(String message, int exitcode)
1765 if (Console.log == null)
1767 // Don't start the logger just to exit!
1768 if (message != null)
1772 System.out.println(message);
1776 System.err.println(message);
1782 Console.debug("Using Jalview.exit");
1783 if (message != null)
1787 Console.info(message);
1791 Console.error(message);
1797 System.exit(exitcode);
1801 /******************************
1803 * TEST OUTPUT METHODS
1805 ******************************/
1807 * method for reporting string values parsed/processed during tests
1810 protected static void testoutput(ArgParser ap, Arg a, String s1,
1813 BootstrapArgs bsa = ap.getBootstrapArgs();
1814 if (!bsa.getBoolean(Arg.TESTOUTPUT))
1816 if (!((s1 == null && s2 == null) || (s1 != null && s1.equals(s2))))
1818 Console.debug("testoutput with unmatching values '" + s1 + "' and '"
1819 + s2 + "' for arg " + a.argString());
1822 boolean isset = a.hasOption(Opt.BOOTSTRAP) ? bsa.contains(a)
1826 Console.warn("Arg '" + a.getName() + "' not set at all");
1829 testoutput(true, a, s1, s2);
1833 * method for reporting string values parsed/processed during tests
1836 protected static void testoutput(BootstrapArgs bsa, Arg a, String s1,
1839 if (!bsa.getBoolean(Arg.TESTOUTPUT))
1841 if (!((s1 == null && s2 == null) || (s1 != null && s1.equals(s2))))
1843 Console.debug("testoutput with unmatching values '" + s1 + "' and '"
1844 + s2 + "' for arg " + a.argString());
1847 if (!a.hasOption(Opt.BOOTSTRAP))
1849 Console.error("Non-bootstrap Arg '" + a.getName()
1850 + "' given to testoutput(BootstrapArgs bsa, Arg a, String s1, String s2) with only BootstrapArgs");
1852 if (!bsa.contains(a))
1854 Console.warn("Arg '" + a.getName() + "' not set at all");
1857 testoutput(true, a, s1, s2);
1861 * report value set for string values parsed/processed during tests
1863 private static void testoutput(boolean yes, Arg a, String s1, String s2)
1865 if (yes && ((s1 == null && s2 == null)
1866 || (s1 != null && s1.equals(s2))))
1868 System.out.println("[TESTOUTPUT] arg " + a.argString() + "='" + s1
1874 * testoutput for boolean and unary values
1876 protected static void testoutput(ArgParser ap, Arg a)
1880 BootstrapArgs bsa = ap.getBootstrapArgs();
1883 if (!bsa.getBoolean(Arg.TESTOUTPUT))
1885 boolean val = a.hasOption(Opt.BOOTSTRAP) ? bsa.getBoolean(a)
1887 boolean isset = a.hasOption(Opt.BOOTSTRAP) ? bsa.contains(a)
1891 Console.warn("Arg '" + a.getName() + "' not set at all");
1897 protected static void testoutput(BootstrapArgs bsa, Arg a)
1899 if (!bsa.getBoolean(Arg.TESTOUTPUT))
1901 if (!a.hasOption(Opt.BOOTSTRAP))
1903 Console.warn("Non-bootstrap Arg '" + a.getName()
1904 + "' given to testoutput(BootstrapArgs bsa, Arg a) with only BootstrapArgs");
1907 if (!bsa.contains(a))
1909 Console.warn("Arg '" + a.getName() + "' not set at all");
1912 testoutput(bsa.getBoolean(a), a);
1915 private static void testoutput(boolean yes, Arg a)
1917 String message = null;
1918 if (a.hasOption(Opt.BOOLEAN))
1920 message = (yes ? a.argString() : a.negateArgString()) + " was set";
1922 else if (a.hasOption(Opt.UNARY))
1924 message = a.argString() + (yes ? " was set" : " was not set");
1926 System.out.println("[TESTOUTPUT] arg " + message);