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.OutputStreamWriter;
30 import java.io.PrintWriter;
31 import java.net.MalformedURLException;
33 import java.net.URISyntaxException;
35 import java.security.AllPermission;
36 import java.security.CodeSource;
37 import java.security.PermissionCollection;
38 import java.security.Permissions;
39 import java.security.Policy;
40 import java.util.HashMap;
41 import java.util.Locale;
43 import java.util.Vector;
44 import java.util.logging.ConsoleHandler;
45 import java.util.logging.Level;
46 import java.util.logging.Logger;
48 import javax.swing.JOptionPane;
49 import javax.swing.SwingUtilities;
50 import javax.swing.UIManager;
51 import javax.swing.UIManager.LookAndFeelInfo;
53 import com.formdev.flatlaf.FlatLightLaf;
54 import com.formdev.flatlaf.util.SystemInfo;
55 import com.threerings.getdown.util.LaunchUtil;
57 //import edu.stanford.ejalbert.launching.IBrowserLaunching;
58 import groovy.lang.Binding;
59 import groovy.util.GroovyScriptEngine;
60 import jalview.ext.so.SequenceOntology;
61 import jalview.gui.AlignFrame;
62 import jalview.gui.Desktop;
63 import jalview.gui.PromptUserConfig;
64 import jalview.io.AppletFormatAdapter;
65 import jalview.io.BioJsHTMLOutput;
66 import jalview.io.DataSourceType;
67 import jalview.io.FileFormat;
68 import jalview.io.FileFormatException;
69 import jalview.io.FileFormatI;
70 import jalview.io.FileFormats;
71 import jalview.io.FileLoader;
72 import jalview.io.HtmlSvgOutput;
73 import jalview.io.IdentifyFile;
74 import jalview.io.NewickFile;
75 import jalview.io.gff.SequenceOntologyFactory;
76 import jalview.jbgui.QuitHandler;
77 import jalview.jbgui.QuitHandler.QResponse;
78 import jalview.schemes.ColourSchemeI;
79 import jalview.schemes.ColourSchemeProperty;
80 import jalview.util.ChannelProperties;
81 import jalview.util.HttpUtils;
82 import jalview.util.LaunchUtils;
83 import jalview.util.MessageManager;
84 import jalview.util.Platform;
85 import jalview.ws.jws2.Jws2Discoverer;
88 * Main class for Jalview Application <br>
90 * start with: java -classpath "$PATH_TO_LIB$/*:$PATH_TO_CLASSES$" \
93 * or on Windows: java -classpath "$PATH_TO_LIB$/*;$PATH_TO_CLASSES$" \
94 * jalview.bin.Jalview jalview.bin.Jalview
96 * (ensure -classpath arg is quoted to avoid shell expansion of '*' and do not
97 * embellish '*' to e.g. '*.jar')
100 * @version $Revision$
106 Platform.getURLCommandArguments();
107 Platform.addJ2SDirectDatabaseCall("https://www.jalview.org");
108 Platform.addJ2SDirectDatabaseCall("http://www.jalview.org");
109 Platform.addJ2SDirectDatabaseCall("http://www.compbio.dundee.ac.uk");
110 Platform.addJ2SDirectDatabaseCall("https://www.compbio.dundee.ac.uk");
114 * singleton instance of this class
116 private static Jalview instance;
118 private Desktop desktop;
120 public static AlignFrame currentAlignFrame;
124 if (!Platform.isJS())
131 // grab all the rights we can for the JVM
132 Policy.setPolicy(new Policy()
135 public PermissionCollection getPermissions(CodeSource codesource)
137 Permissions perms = new Permissions();
138 perms.add(new AllPermission());
143 public void refresh()
151 * keep track of feature fetching tasks.
159 * TODO: generalise to track all jalview events to orchestrate batch processing
163 private int queued = 0;
165 private int running = 0;
167 public FeatureFetcher()
172 public void addFetcher(final AlignFrame af,
173 final Vector<String> dasSources)
175 final long id = System.currentTimeMillis();
177 final FeatureFetcher us = this;
178 new Thread(new Runnable()
190 af.setProgressBar(MessageManager
191 .getString("status.das_features_being_retrived"), id);
192 af.featureSettings_actionPerformed(null);
193 af.setProgressBar(null, id);
202 public synchronized boolean allFinished()
204 return queued == 0 && running == 0;
209 public static Jalview getInstance()
215 * main class for Jalview application
218 * open <em>filename</em>
220 public static void main(String[] args)
222 // setLogging(); // BH - for event debugging in JavaScript
223 instance = new Jalview();
224 instance.doMain(args);
227 private static void logClass(String name)
229 // BH - for event debugging in JavaScript
230 ConsoleHandler consoleHandler = new ConsoleHandler();
231 consoleHandler.setLevel(Level.ALL);
232 Logger logger = Logger.getLogger(name);
233 logger.setLevel(Level.ALL);
234 logger.addHandler(consoleHandler);
237 @SuppressWarnings("unused")
238 private static void setLogging()
246 System.out.println("not in js");
249 // BH - for event debugging in JavaScript (Java mode only)
250 if (!Platform.isJS())
257 Logger.getLogger("").setLevel(Level.ALL);
258 logClass("java.awt.EventDispatchThread");
259 logClass("java.awt.EventQueue");
260 logClass("java.awt.Component");
261 logClass("java.awt.focus.Component");
262 logClass("java.awt.focus.DefaultKeyboardFocusManager");
270 void doMain(String[] args)
273 if (!Platform.isJS())
275 System.setSecurityManager(null);
277 Runtime.getRuntime().addShutdownHook(new Thread()
281 Console.debug("Running shutdown hook");
282 if (QuitHandler.gotQuitResponse() == QResponse.CANCEL_QUIT)
284 Console.debug("Checking for saving files");
285 QuitHandler.getQuitResponse(false);
289 Console.debug("Nothing more to do");
291 Console.debug("Exiting, bye!");
292 // shutdownHook cannot be cancelled, JVM will now halt
298 .println("Java version: " + System.getProperty("java.version"));
299 System.out.println("Java Home: " + System.getProperty("java.home"));
300 System.out.println(System.getProperty("os.arch") + " "
301 + System.getProperty("os.name") + " "
302 + System.getProperty("os.version"));
304 String val = System.getProperty("sys.install4jVersion");
307 System.out.println("Install4j version: " + val);
309 val = System.getProperty("installer_template_version");
312 System.out.println("Install4j template version: " + val);
314 val = System.getProperty("launcher_version");
317 System.out.println("Launcher version: " + val);
320 // report Jalview version
321 Cache.loadBuildProperties(true);
323 ArgsParser aparser = new ArgsParser(args);
325 boolean headless = false;
327 String usrPropsFile = aparser.getValue("props");
328 Cache.loadProperties(usrPropsFile); // must do this
330 if (usrPropsFile != null)
333 "CMD [-props " + usrPropsFile + "] executed successfully!");
336 if (!Platform.isJS())
343 if (aparser.contains("help") || aparser.contains("h"))
348 if (aparser.contains("nodisplay") || aparser.contains("nogui")
349 || aparser.contains("headless"))
351 System.setProperty("java.awt.headless", "true");
356 // allow https handshakes to download intermediate certs if necessary
357 System.setProperty("com.sun.security.enableAIAcaIssuers", "true");
359 final String jabawsUrl = aparser.getValue("jabaws");
360 if (jabawsUrl != null)
364 Jws2Discoverer.getDiscoverer().setPreferredUrl(jabawsUrl);
366 "CMD [-jabaws " + jabawsUrl + "] executed successfully!");
367 } catch (MalformedURLException e)
370 "Invalid jabaws parameter: " + jabawsUrl + " ignored");
375 String defs = aparser.getValue("setprop");
378 int p = defs.indexOf('=');
381 System.err.println("Ignoring invalid setprop argument : " + defs);
385 System.out.println("Executing setprop argument: " + defs);
388 Cache.setProperty(defs.substring(0, p), defs.substring(p + 1));
390 // DISABLED FOR SECURITY REASONS
391 // TODO: add a property to allow properties to be overriden by cli args
392 // Cache.setProperty(defs.substring(0,p), defs.substring(p+1));
394 defs = aparser.getValue("setprop");
396 if (System.getProperty("java.awt.headless") != null
397 && System.getProperty("java.awt.headless").equals("true"))
401 System.setProperty("http.agent",
402 "Jalview Desktop/" + Cache.getDefault("VERSION", "Unknown"));
406 Console.initLogger();
409 NoClassDefFoundError error)
411 error.printStackTrace();
412 System.out.println("\nEssential logging libraries not found."
413 + "\nUse: java -classpath \"$PATH_TO_LIB$/*:$PATH_TO_CLASSES$\" jalview.bin.Jalview");
422 * configure 'full' SO model if preferences say to, else use the default (full SO)
423 * - as JS currently doesn't have OBO parsing, it must use 'Lite' version
425 boolean soDefault = !Platform.isJS();
426 if (Cache.getDefault("USE_FULL_SO", soDefault))
428 SequenceOntologyFactory.setInstance(new SequenceOntology());
433 Desktop.nosplash = aparser.contains("nosplash");
434 desktop = new Desktop();
435 desktop.setInBatchMode(true); // indicate we are starting up
439 JalviewTaskbar.setTaskbar(this);
440 } catch (Exception e)
442 Console.info("Cannot set Taskbar");
443 Console.error(e.getMessage());
444 // e.printStackTrace();
445 } catch (Throwable t)
447 Console.info("Cannot set Taskbar");
448 Console.error(t.getMessage());
449 // t.printStackTrace();
452 // set Proxy settings before all the internet calls
453 Cache.setProxyPropertiesFromPreferences();
455 desktop.setVisible(true);
457 if (!Platform.isJS())
466 * Check to see that the JVM version being run is suitable for the Java
467 * version this Jalview was compiled for. Popup a warning if not.
469 if (!LaunchUtils.checkJavaVersion())
471 Console.warn("The Java version being used (Java "
472 + LaunchUtils.getJavaVersion()
473 + ") may lead to problems. This installation of Jalview should be used with Java "
474 + LaunchUtils.getJavaCompileVersion() + ".");
477 .getBooleanUserPreference("IGNORE_JVM_WARNING_POPUP"))
480 MessageManager.getString("label.continue") };
481 JOptionPane.showOptionDialog(null,
482 MessageManager.formatMessage(
483 "warning.wrong_jvm_version_message",
484 LaunchUtils.getJavaVersion(),
485 LaunchUtils.getJavaCompileVersion()),
487 .getString("warning.wrong_jvm_version_title"),
488 JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE,
489 null, options, options[0]);
493 if (!aparser.contains("nowebservicediscovery"))
495 desktop.startServiceDiscovery();
497 if (!aparser.contains("nousagestats"))
499 startUsageStats(desktop);
503 System.err.println("CMD [-nousagestats] executed successfully!");
506 if (!aparser.contains("noquestionnaire"))
508 String url = aparser.getValue("questionnaire");
511 // Start the desktop questionnaire prompter with the specified
513 Console.debug("Starting questionnaire url at " + url);
514 desktop.checkForQuestionnaire(url);
515 System.out.println("CMD questionnaire[-" + url
516 + "] executed successfully!");
520 if (Cache.getProperty("NOQUESTIONNAIRES") == null)
522 // Start the desktop questionnaire prompter with the specified
525 // "http://anaplog.compbio.dundee.ac.uk/cgi-bin/questionnaire.pl";
527 String defurl = "https://www.jalview.org/cgi-bin/questionnaire.pl";
529 "Starting questionnaire with default url: " + defurl);
530 desktop.checkForQuestionnaire(defurl);
537 .println("CMD [-noquestionnaire] executed successfully!");
540 if (!aparser.contains("nonews")
541 || Cache.getProperty("NONEWS") == null)
543 desktop.checkForNews();
546 if (!aparser.contains("nohtmltemplates")
547 || Cache.getProperty("NOHTMLTEMPLATES") == null)
549 BioJsHTMLOutput.updateBioJS();
554 // Check if JVM and compile version might cause problems and log if it
556 if (headless && !Platform.isJS() && !LaunchUtils.checkJavaVersion())
558 Console.warn("The Java version being used (Java "
559 + LaunchUtils.getJavaVersion()
560 + ") may lead to problems. This installation of Jalview should be used with Java "
561 + LaunchUtils.getJavaCompileVersion() + ".");
564 // Move any new getdown-launcher-new.jar into place over old
565 // getdown-launcher.jar
566 String appdirString = System.getProperty("getdownappdir");
567 if (appdirString != null && appdirString.length() > 0)
569 final File appdir = new File(appdirString);
575 LaunchUtil.upgradeGetdown(
576 new File(appdir, "getdown-launcher-old.jar"),
577 new File(appdir, "getdown-launcher.jar"),
578 new File(appdir, "getdown-launcher-new.jar"));
583 String file = null, data = null;
585 FileFormatI format = null;
587 DataSourceType protocol = null;
589 FileLoader fileLoader = new FileLoader(!headless);
591 String groovyscript = null; // script to execute after all loading is
592 // completed one way or another
593 // extract groovy argument and execute if necessary
594 groovyscript = aparser.getValue("groovy", true);
595 file = aparser.getValue("open", true);
597 if (file == null && desktop == null)
599 System.out.println("No files to open!");
604 // Finally, deal with the remaining input data.
609 desktop.setProgressBar(
611 .getString("status.processing_commandline_args"),
612 progress = System.currentTimeMillis());
614 System.out.println("CMD [-open " + file + "] executed successfully!");
616 if (!Platform.isJS())
618 * ignore in JavaScript -- can't just file existence - could load it?
623 if (!HttpUtils.startsWithHttpOrHttps(file))
625 if (!(new File(file)).exists())
627 System.out.println("Can't find " + file);
636 protocol = AppletFormatAdapter.checkProtocol(file);
640 format = new IdentifyFile().identify(file, protocol);
641 } catch (FileFormatException e1)
646 AlignFrame af = fileLoader.LoadFileWaitTillLoaded(file, protocol,
650 System.out.println("error");
654 setCurrentAlignFrame(af);
655 data = aparser.getValue("colour", true);
658 data.replaceAll("%20", " ");
660 ColourSchemeI cs = ColourSchemeProperty.getColourScheme(
661 af.getViewport(), af.getViewport().getAlignment(), data);
666 "CMD [-color " + data + "] executed successfully!");
671 // Must maintain ability to use the groups flag
672 data = aparser.getValue("groups", true);
675 af.parseFeaturesFile(data,
676 AppletFormatAdapter.checkProtocol(data));
677 // System.out.println("Added " + data);
679 "CMD groups[-" + data + "] executed successfully!");
681 data = aparser.getValue("features", true);
684 af.parseFeaturesFile(data,
685 AppletFormatAdapter.checkProtocol(data));
686 // System.out.println("Added " + data);
688 "CMD [-features " + data + "] executed successfully!");
691 data = aparser.getValue("annotations", true);
694 af.loadJalviewDataFile(data, null, null, null);
695 // System.out.println("Added " + data);
697 "CMD [-annotations " + data + "] executed successfully!");
699 // set or clear the sortbytree flag.
700 if (aparser.contains("sortbytree"))
702 af.getViewport().setSortByTree(true);
703 if (af.getViewport().getSortByTree())
705 System.out.println("CMD [-sortbytree] executed successfully!");
708 if (aparser.contains("no-annotation"))
710 af.getViewport().setShowAnnotation(false);
711 if (!af.getViewport().isShowAnnotation())
713 System.out.println("CMD no-annotation executed successfully!");
716 if (aparser.contains("nosortbytree"))
718 af.getViewport().setSortByTree(false);
719 if (!af.getViewport().getSortByTree())
722 .println("CMD [-nosortbytree] executed successfully!");
725 data = aparser.getValue("tree", true);
731 "CMD [-tree " + data + "] executed successfully!");
732 NewickFile nf = new NewickFile(data,
733 AppletFormatAdapter.checkProtocol(data));
735 .setCurrentTree(af.showNewickTree(nf, data).getTree());
736 } catch (IOException ex)
738 System.err.println("Couldn't add tree " + data);
739 ex.printStackTrace(System.err);
742 // TODO - load PDB structure(s) to alignment JAL-629
743 // (associate with identical sequence in alignment, or a specified
745 if (groovyscript != null)
747 // Execute the groovy script after we've done all the rendering stuff
748 // and before any images or figures are generated.
749 System.out.println("Executing script " + groovyscript);
750 executeGroovyScript(groovyscript, af);
751 System.out.println("CMD groovy[" + groovyscript
752 + "] executed successfully!");
755 String imageName = "unnamed.png";
756 while (aparser.getSize() > 1)
758 String outputFormat = aparser.nextValue();
759 file = aparser.nextValue();
761 if (outputFormat.equalsIgnoreCase("png"))
763 af.createPNG(new File(file));
764 imageName = (new File(file)).getName();
765 System.out.println("Creating PNG image: " + file);
768 else if (outputFormat.equalsIgnoreCase("svg"))
770 File imageFile = new File(file);
771 imageName = imageFile.getName();
772 af.createSVG(imageFile);
773 System.out.println("Creating SVG image: " + file);
776 else if (outputFormat.equalsIgnoreCase("html"))
778 File imageFile = new File(file);
779 imageName = imageFile.getName();
780 HtmlSvgOutput htmlSVG = new HtmlSvgOutput(af.alignPanel);
781 htmlSVG.exportHTML(file);
783 System.out.println("Creating HTML image: " + file);
786 else if (outputFormat.equalsIgnoreCase("biojsmsa"))
790 System.err.println("The output html file must not be null");
795 BioJsHTMLOutput.refreshVersionInfo(
796 BioJsHTMLOutput.BJS_TEMPLATES_LOCAL_DIRECTORY);
797 } catch (URISyntaxException e)
801 BioJsHTMLOutput bjs = new BioJsHTMLOutput(af.alignPanel);
802 bjs.exportHTML(file);
804 .println("Creating BioJS MSA Viwer HTML file: " + file);
807 else if (outputFormat.equalsIgnoreCase("imgMap"))
809 af.createImageMap(new File(file), imageName);
810 System.out.println("Creating image map: " + file);
813 else if (outputFormat.equalsIgnoreCase("eps"))
815 File outputFile = new File(file);
817 "Creating EPS file: " + outputFile.getAbsolutePath());
818 af.createEPS(outputFile);
821 FileFormatI outFormat = null;
824 outFormat = FileFormats.getInstance().forName(outputFormat);
825 } catch (Exception formatP)
827 System.out.println("Couldn't parse " + outFormat
828 + " as a valid Jalview format string.");
830 if (outFormat != null)
832 if (!outFormat.isWritable())
835 "This version of Jalview does not support alignment export as "
840 af.saveAlignment(file, outFormat);
841 if (af.isSaveAlignmentSuccessful())
843 System.out.println("Written alignment in "
844 + outFormat.getName() + " format to " + file);
848 System.out.println("Error writing file " + file + " in "
849 + outFormat.getName() + " format!!");
856 while (aparser.getSize() > 0)
858 System.out.println("Unknown arg: " + aparser.nextValue());
863 AlignFrame startUpAlframe = null;
864 // We'll only open the default file if the desktop is visible.
866 // ////////////////////
868 if (!Platform.isJS() && !headless && file == null
869 && Cache.getDefault("SHOW_STARTUP_FILE", true))
876 file = Cache.getDefault("STARTUP_FILE",
877 Cache.getDefault("www.jalview.org", "https://www.jalview.org")
878 + "/examples/exampleFile_2_7.jvp");
879 if (file.equals("http://www.jalview.org/examples/exampleFile_2_3.jar")
881 "http://www.jalview.org/examples/exampleFile_2_7.jar"))
883 file.replace("http:", "https:");
884 // hardwire upgrade of the startup file
885 file.replace("_2_3", "_2_7");
886 file.replace("2_7.jar", "2_7.jvp");
887 // and remove the stale setting
888 Cache.removeProperty("STARTUP_FILE");
891 protocol = AppletFormatAdapter.checkProtocol(file);
893 if (file.endsWith(".jar"))
895 format = FileFormat.Jalview;
901 format = new IdentifyFile().identify(file, protocol);
902 } catch (FileFormatException e)
908 startUpAlframe = fileLoader.LoadFileWaitTillLoaded(file, protocol,
910 // extract groovy arguments before anything else.
913 // Once all other stuff is done, execute any groovy scripts (in order)
914 if (groovyscript != null)
916 if (Cache.groovyJarsPresent())
918 System.out.println("Executing script " + groovyscript);
919 executeGroovyScript(groovyscript, startUpAlframe);
924 "Sorry. Groovy Support is not available, so ignoring the provided groovy script "
928 // and finally, turn off batch mode indicator - if the desktop still exists
933 desktop.setProgressBar(null, progress);
935 desktop.setInBatchMode(false);
939 private static void setLookAndFeel()
941 // property laf = "crossplatform", "system", "gtk", "metal", "nimbus",
943 // If not set (or chosen laf fails), use the normal SystemLaF and if on Mac,
945 String lafProp = System.getProperty("laf");
946 String lafSetting = Cache.getDefault("PREFERRED_LAF", null);
952 else if (lafSetting != null)
956 boolean lafSet = false;
959 case "crossplatform":
960 lafSet = setCrossPlatformLookAndFeel();
963 Console.error("Could not set requested laf=" + laf);
967 lafSet = setSystemLookAndFeel();
970 Console.error("Could not set requested laf=" + laf);
974 lafSet = setGtkLookAndFeel();
977 Console.error("Could not set requested laf=" + laf);
981 lafSet = setMetalLookAndFeel();
984 Console.error("Could not set requested laf=" + laf);
988 lafSet = setNimbusLookAndFeel();
991 Console.error("Could not set requested laf=" + laf);
995 lafSet = setFlatLookAndFeel();
998 Console.error("Could not set requested laf=" + laf);
1002 lafSet = setQuaquaLookAndFeel();
1005 Console.error("Could not set requested laf=" + laf);
1009 lafSet = setVaquaLookAndFeel();
1012 Console.error("Could not set requested laf=" + laf);
1016 lafSet = setMacLookAndFeel();
1019 Console.error("Could not set requested laf=" + laf);
1025 Console.error("Requested laf=" + laf + " not implemented");
1029 setSystemLookAndFeel();
1030 if (Platform.isLinux())
1032 setMetalLookAndFeel();
1034 if (Platform.isMac())
1036 setMacLookAndFeel();
1041 private static boolean setCrossPlatformLookAndFeel()
1043 boolean set = false;
1046 UIManager.setLookAndFeel(
1047 UIManager.getCrossPlatformLookAndFeelClassName());
1049 } catch (Exception ex)
1051 Console.error("Unexpected Look and Feel Exception");
1052 Console.error(ex.getMessage());
1053 Console.debug(Cache.getStackTraceString(ex));
1058 private static boolean setSystemLookAndFeel()
1060 boolean set = false;
1063 UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
1065 } catch (Exception ex)
1067 Console.error("Unexpected Look and Feel Exception");
1068 Console.error(ex.getMessage());
1069 Console.debug(Cache.getStackTraceString(ex));
1074 private static boolean setSpecificLookAndFeel(String name,
1075 String className, boolean nameStartsWith)
1077 boolean set = false;
1080 for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels())
1082 if (info.getName() != null && nameStartsWith
1083 ? info.getName().toLowerCase(Locale.ROOT)
1084 .startsWith(name.toLowerCase(Locale.ROOT))
1085 : info.getName().toLowerCase(Locale.ROOT)
1086 .equals(name.toLowerCase(Locale.ROOT)))
1088 className = info.getClassName();
1092 UIManager.setLookAndFeel(className);
1094 } catch (Exception ex)
1096 Console.error("Unexpected Look and Feel Exception");
1097 Console.error(ex.getMessage());
1098 Console.debug(Cache.getStackTraceString(ex));
1103 private static boolean setGtkLookAndFeel()
1105 return setSpecificLookAndFeel("gtk",
1106 "com.sun.java.swing.plaf.gtk.GTKLookAndFeel", true);
1109 private static boolean setMetalLookAndFeel()
1111 return setSpecificLookAndFeel("metal",
1112 "javax.swing.plaf.metal.MetalLookAndFeel", false);
1115 private static boolean setNimbusLookAndFeel()
1117 return setSpecificLookAndFeel("nimbus",
1118 "javax.swing.plaf.nimbus.NimbusLookAndFeel", false);
1121 private static boolean setFlatLookAndFeel()
1123 boolean set = setSpecificLookAndFeel("flatlaf light",
1124 "com.formdev.flatlaf.FlatLightLaf", false);
1127 if (Platform.isMac())
1129 System.setProperty("apple.laf.useScreenMenuBar", "true");
1130 System.setProperty("apple.awt.application.name",
1131 ChannelProperties.getProperty("app_name"));
1132 System.setProperty("apple.awt.application.appearance", "system");
1133 if (SystemInfo.isMacFullWindowContentSupported
1134 && Desktop.desktop != null)
1136 Desktop.desktop.getRootPane()
1137 .putClientProperty("apple.awt.fullWindowContent", true);
1138 Desktop.desktop.getRootPane()
1139 .putClientProperty("apple.awt.transparentTitleBar", true);
1142 SwingUtilities.invokeLater(() -> {
1143 FlatLightLaf.setup();
1147 UIManager.put("TabbedPane.showTabSeparators", true);
1148 UIManager.put("TabbedPane.tabSeparatorsFullHeight", true);
1149 UIManager.put("TabbedPane.tabsOverlapBorder", true);
1150 // UIManager.put("TabbedPane.hasFullBorder", true);
1151 UIManager.put("TabbedPane.tabLayoutPolicy", "scroll");
1152 UIManager.put("TabbedPane.scrollButtonsPolicy", "asNeeded");
1153 UIManager.put("TabbedPane.smoothScrolling", true);
1154 UIManager.put("TabbedPane.tabWidthMode", "compact");
1155 UIManager.put("TabbedPane.selectedBackground", Color.white);
1160 private static boolean setQuaquaLookAndFeel()
1162 return setSpecificLookAndFeel("quaqua",
1163 ch.randelshofer.quaqua.QuaquaManager.getLookAndFeel().getClass()
1168 private static boolean setVaquaLookAndFeel()
1170 return setSpecificLookAndFeel("vaqua",
1171 "org.violetlib.aqua.AquaLookAndFeel", false);
1174 private static boolean setMacLookAndFeel()
1176 boolean set = false;
1177 System.setProperty("com.apple.mrj.application.apple.menu.about.name",
1178 ChannelProperties.getProperty("app_name"));
1179 System.setProperty("apple.laf.useScreenMenuBar", "true");
1180 set = setQuaquaLookAndFeel();
1181 if ((!set) || !UIManager.getLookAndFeel().getClass().toString()
1182 .toLowerCase(Locale.ROOT).contains("quaqua"))
1184 set = setVaquaLookAndFeel();
1189 private static void showUsage()
1192 "Usage: jalview -open [FILE] [OUTPUT_FORMAT] [OUTPUT_FILE]\n\n"
1193 + "-nodisplay\tRun Jalview without User Interface.\n"
1194 + "-props FILE\tUse the given Jalview properties file instead of users default.\n"
1195 + "-colour COLOURSCHEME\tThe colourscheme to be applied to the alignment\n"
1196 + "-annotations FILE\tAdd precalculated annotations to the alignment.\n"
1197 + "-tree FILE\tLoad the given newick format tree file onto the alignment\n"
1198 + "-features FILE\tUse the given file to mark features on the alignment.\n"
1199 + "-fasta FILE\tCreate alignment file FILE in Fasta format.\n"
1200 + "-clustal FILE\tCreate alignment file FILE in Clustal format.\n"
1201 + "-pfam FILE\tCreate alignment file FILE in PFAM format.\n"
1202 + "-msf FILE\tCreate alignment file FILE in MSF format.\n"
1203 + "-pileup FILE\tCreate alignment file FILE in Pileup format\n"
1204 + "-pir FILE\tCreate alignment file FILE in PIR format.\n"
1205 + "-blc FILE\tCreate alignment file FILE in BLC format.\n"
1206 + "-json FILE\tCreate alignment file FILE in JSON format.\n"
1207 + "-jalview FILE\tCreate alignment file FILE in Jalview format.\n"
1208 + "-png FILE\tCreate PNG image FILE from alignment.\n"
1209 + "-svg FILE\tCreate SVG image FILE from alignment.\n"
1210 + "-html FILE\tCreate HTML file from alignment.\n"
1211 + "-biojsMSA FILE\tCreate BioJS MSA Viewer HTML file from alignment.\n"
1212 + "-imgMap FILE\tCreate HTML file FILE with image map of PNG image.\n"
1213 + "-eps FILE\tCreate EPS file FILE from alignment.\n"
1214 + "-questionnaire URL\tQueries the given URL for information about any Jalview user questionnaires.\n"
1215 + "-noquestionnaire\tTurn off questionnaire check.\n"
1216 + "-nonews\tTurn off check for Jalview news.\n"
1217 + "-nousagestats\tTurn off google analytics tracking for this session.\n"
1218 + "-sortbytree OR -nosortbytree\tEnable or disable sorting of the given alignment by the given tree\n"
1220 // "-setprop PROPERTY=VALUE\tSet the given Jalview property,
1221 // after all other properties files have been read\n\t
1222 // (quote the 'PROPERTY=VALUE' pair to ensure spaces are
1223 // passed in correctly)"
1224 + "-jabaws URL\tSpecify URL for Jabaws services (e.g. for a local installation).\n"
1225 + "-fetchfrom nickname\tQuery nickname for features for the alignments and display them.\n"
1226 + "-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"
1227 + "-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"
1228 + "-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"
1229 + "\n~Read documentation in Application or visit https://www.jalview.org for description of Features and Annotations file~\n\n");
1232 private static void startUsageStats(final Desktop desktop)
1235 * start a User Config prompt asking if we can log usage statistics.
1237 PromptUserConfig prompter = new PromptUserConfig(Desktop.desktop,
1238 "USAGESTATS", "Jalview Usage Statistics",
1239 "Do you want to help make Jalview better by enabling "
1240 + "the collection of usage statistics with Google Analytics ?"
1241 + "\n\n(you can enable or disable usage tracking in the preferences)",
1248 "Initialising googletracker for usage stats.");
1249 Cache.initGoogleTracker();
1250 Console.debug("Tracking enabled.");
1257 Console.debug("Not enabling Google Tracking.");
1260 desktop.addDialogThread(prompter);
1264 * Locate the given string as a file and pass it to the groovy interpreter.
1266 * @param groovyscript
1267 * the script to execute
1268 * @param jalviewContext
1269 * the Jalview Desktop object passed in to the groovy binding as the
1272 private void executeGroovyScript(String groovyscript, AlignFrame af)
1275 * for scripts contained in files
1282 if (groovyscript.trim().equals("STDIN"))
1284 // read from stdin into a tempfile and execute it
1287 tfile = File.createTempFile("jalview", "groovy");
1288 PrintWriter outfile = new PrintWriter(
1289 new OutputStreamWriter(new FileOutputStream(tfile)));
1290 BufferedReader br = new BufferedReader(
1291 new InputStreamReader(System.in));
1293 while ((line = br.readLine()) != null)
1295 outfile.write(line + "\n");
1301 } catch (Exception ex)
1303 System.err.println("Failed to read from STDIN into tempfile "
1304 + ((tfile == null) ? "(tempfile wasn't created)"
1305 : tfile.toString()));
1306 ex.printStackTrace();
1311 sfile = tfile.toURI().toURL();
1312 } catch (Exception x)
1315 "Unexpected Malformed URL Exception for temporary file created from STDIN: "
1317 x.printStackTrace();
1325 sfile = new URI(groovyscript).toURL();
1326 } catch (Exception x)
1328 tfile = new File(groovyscript);
1329 if (!tfile.exists())
1331 System.err.println("File '" + groovyscript + "' does not exist.");
1334 if (!tfile.canRead())
1336 System.err.println("File '" + groovyscript + "' cannot be read.");
1339 if (tfile.length() < 1)
1341 System.err.println("File '" + groovyscript + "' is empty.");
1346 sfile = tfile.getAbsoluteFile().toURI().toURL();
1347 } catch (Exception ex)
1349 System.err.println("Failed to create a file URL for "
1350 + tfile.getAbsoluteFile());
1357 Map<String, java.lang.Object> vbinding = new HashMap<>();
1358 vbinding.put("Jalview", this);
1361 vbinding.put("currentAlFrame", af);
1363 Binding gbinding = new Binding(vbinding);
1364 GroovyScriptEngine gse = new GroovyScriptEngine(new URL[] { sfile });
1365 gse.run(sfile.toString(), gbinding);
1366 if ("STDIN".equals(groovyscript))
1368 // delete temp file that we made -
1369 // only if it was successfully executed
1372 } catch (Exception e)
1374 System.err.println("Exception Whilst trying to execute file " + sfile
1375 + " as a groovy script.");
1376 e.printStackTrace(System.err);
1381 public static boolean isHeadlessMode()
1383 String isheadless = System.getProperty("java.awt.headless");
1384 if (isheadless != null && isheadless.equalsIgnoreCase("true"))
1391 public AlignFrame[] getAlignFrames()
1393 return desktop == null ? new AlignFrame[] { getCurrentAlignFrame() }
1394 : Desktop.getAlignFrames();
1399 * jalview.bin.Jalview.quit() will just run the non-GUI shutdownHook and exit
1403 // System.exit will run the shutdownHook first
1407 public static AlignFrame getCurrentAlignFrame()
1409 return Jalview.currentAlignFrame;
1412 public static void setCurrentAlignFrame(AlignFrame currentAlignFrame)
1414 Jalview.currentAlignFrame = currentAlignFrame;