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.bin.ArgParser.Arg;
61 import jalview.ext.so.SequenceOntology;
62 import jalview.gui.AlignFrame;
63 import jalview.gui.Desktop;
64 import jalview.gui.PromptUserConfig;
65 import jalview.io.AppletFormatAdapter;
66 import jalview.io.BioJsHTMLOutput;
67 import jalview.io.DataSourceType;
68 import jalview.io.FileFormat;
69 import jalview.io.FileFormatException;
70 import jalview.io.FileFormatI;
71 import jalview.io.FileFormats;
72 import jalview.io.FileLoader;
73 import jalview.io.HtmlSvgOutput;
74 import jalview.io.IdentifyFile;
75 import jalview.io.NewickFile;
76 import jalview.io.gff.SequenceOntologyFactory;
77 import jalview.schemes.ColourSchemeI;
78 import jalview.schemes.ColourSchemeProperty;
79 import jalview.util.ChannelProperties;
80 import jalview.util.HttpUtils;
81 import jalview.util.LaunchUtils;
82 import jalview.util.MessageManager;
83 import jalview.util.Platform;
84 import jalview.ws.jws2.Jws2Discoverer;
87 * Main class for Jalview Application <br>
89 * start with: java -classpath "$PATH_TO_LIB$/*:$PATH_TO_CLASSES$" \
92 * or on Windows: java -classpath "$PATH_TO_LIB$/*;$PATH_TO_CLASSES$" \
93 * jalview.bin.Jalview jalview.bin.Jalview
95 * (ensure -classpath arg is quoted to avoid shell expansion of '*' and do not
96 * embellish '*' to e.g. '*.jar')
105 Platform.getURLCommandArguments();
106 Platform.addJ2SDirectDatabaseCall("https://www.jalview.org");
107 Platform.addJ2SDirectDatabaseCall("http://www.jalview.org");
108 Platform.addJ2SDirectDatabaseCall("http://www.compbio.dundee.ac.uk");
109 Platform.addJ2SDirectDatabaseCall("https://www.compbio.dundee.ac.uk");
113 * singleton instance of this class
115 private static Jalview instance;
117 private Desktop desktop;
119 public static AlignFrame currentAlignFrame;
123 if (!Platform.isJS())
130 // grab all the rights we can for the JVM
131 Policy.setPolicy(new Policy()
134 public PermissionCollection getPermissions(CodeSource codesource)
136 Permissions perms = new Permissions();
137 perms.add(new AllPermission());
142 public void refresh()
150 * keep track of feature fetching tasks.
158 * TODO: generalise to track all jalview events to orchestrate batch processing
162 private int queued = 0;
164 private int running = 0;
166 public FeatureFetcher()
171 public void addFetcher(final AlignFrame af,
172 final Vector<String> dasSources)
174 final long id = System.currentTimeMillis();
176 final FeatureFetcher us = this;
177 new Thread(new Runnable()
189 af.setProgressBar(MessageManager
190 .getString("status.das_features_being_retrived"), id);
191 af.featureSettings_actionPerformed(null);
192 af.setProgressBar(null, id);
201 public synchronized boolean allFinished()
203 return queued == 0 && running == 0;
208 public static Jalview getInstance()
214 * main class for Jalview application
217 * open <em>filename</em>
219 public static void main(String[] args)
221 // setLogging(); // BH - for event debugging in JavaScript
222 instance = new Jalview();
223 instance.doMain(args);
226 private static void logClass(String name)
228 // BH - for event debugging in JavaScript
229 ConsoleHandler consoleHandler = new ConsoleHandler();
230 consoleHandler.setLevel(Level.ALL);
231 Logger logger = Logger.getLogger(name);
232 logger.setLevel(Level.ALL);
233 logger.addHandler(consoleHandler);
236 @SuppressWarnings("unused")
237 private static void setLogging()
245 System.out.println("not in js");
248 // BH - for event debugging in JavaScript (Java mode only)
249 if (!Platform.isJS())
256 Logger.getLogger("").setLevel(Level.ALL);
257 logClass("java.awt.EventDispatchThread");
258 logClass("java.awt.EventQueue");
259 logClass("java.awt.Component");
260 logClass("java.awt.focus.Component");
261 logClass("java.awt.focus.DefaultKeyboardFocusManager");
269 void doMain(String[] args)
272 if (!Platform.isJS())
274 System.setSecurityManager(null);
278 .println("Java version: " + System.getProperty("java.version"));
279 System.out.println("Java Home: " + System.getProperty("java.home"));
280 System.out.println(System.getProperty("os.arch") + " "
281 + System.getProperty("os.name") + " "
282 + System.getProperty("os.version"));
283 String val = System.getProperty("sys.install4jVersion");
286 System.out.println("Install4j version: " + val);
288 val = System.getProperty("installer_template_version");
291 System.out.println("Install4j template version: " + val);
293 val = System.getProperty("launcher_version");
296 System.out.println("Launcher version: " + val);
299 // report Jalview version
300 Cache.loadBuildProperties(true);
303 ArgsParser aparser = new ArgsParser(args);
304 boolean headless = false;
308 Console.initLogger();
309 } catch (NoClassDefFoundError error)
311 error.printStackTrace();
312 System.out.println("\nEssential logging libraries not found."
313 + "\nUse: java -classpath \"$PATH_TO_LIB$/*:$PATH_TO_CLASSES$\" jalview.bin.Jalview");
317 String usrPropsFile = aparser.getValue("props");
318 Cache.loadProperties(usrPropsFile); // must do this before
319 if (usrPropsFile != null)
322 "CMD [-props " + usrPropsFile + "] executed successfully!");
325 // set log level from cache properties
326 Console.setLogLevel(Cache.getDefault(Cache.JALVIEWLOGLEVEL, "INFO"));
329 ArgParser argparser = new ArgParser(args); // do this after
330 // Console.initLogger, but TODO
331 // want --props before then
334 if (argparser.isSet(Arg.HEADLESS))
335 headless = argparser.getBool(Arg.HEADLESS);
336 boolean commandsSuccess = Commands.processArgs(argparser, headless);
339 Console.info("Successfully completed commands");
345 Console.warn("Error when running commands");
350 if (!Platform.isJS())
357 if (argparser.isSet(Arg.HEADLESS))
359 headless = argparser.getBool(Arg.HEADLESS);
362 if (aparser.contains("help") || aparser.contains("h"))
367 if (headless || aparser.contains("nodisplay")
368 || aparser.contains("nogui") || aparser.contains("headless"))
370 System.setProperty("java.awt.headless", "true");
375 // allow https handshakes to download intermediate certs if necessary
376 System.setProperty("com.sun.security.enableAIAcaIssuers", "true");
378 final String jabawsUrl = aparser.getValue("jabaws");
379 if (jabawsUrl != null)
383 Jws2Discoverer.getDiscoverer().setPreferredUrl(jabawsUrl);
385 "CMD [-jabaws " + jabawsUrl + "] executed successfully!");
386 } catch (MalformedURLException e)
389 "Invalid jabaws parameter: " + jabawsUrl + " ignored");
394 String defs = aparser.getValue("setprop");
397 int p = defs.indexOf('=');
400 System.err.println("Ignoring invalid setprop argument : " + defs);
404 System.out.println("Executing setprop argument: " + defs);
407 Cache.setProperty(defs.substring(0, p), defs.substring(p + 1));
409 // DISABLED FOR SECURITY REASONS
410 // TODO: add a property to allow properties to be overriden by cli args
411 // Cache.setProperty(defs.substring(0,p), defs.substring(p+1));
413 defs = aparser.getValue("setprop");
415 if (System.getProperty("java.awt.headless") != null
416 && System.getProperty("java.awt.headless").equals("true"))
420 System.setProperty("http.agent",
421 "Jalview Desktop/" + Cache.getDefault("VERSION", "Unknown"));
428 * configure 'full' SO model if preferences say to, else use the default (full SO)
429 * - as JS currently doesn't have OBO parsing, it must use 'Lite' version
431 boolean soDefault = !Platform.isJS();
432 if (Cache.getDefault("USE_FULL_SO", soDefault))
434 SequenceOntologyFactory.setInstance(new SequenceOntology());
439 Desktop.nosplash = aparser.contains("nosplash");
440 desktop = new Desktop();
441 desktop.setInBatchMode(true); // indicate we are starting up
445 JalviewTaskbar.setTaskbar(this);
446 } catch (Exception e)
448 Console.info("Cannot set Taskbar");
449 Console.error(e.getMessage());
450 // e.printStackTrace();
451 } catch (Throwable t)
453 Console.info("Cannot set Taskbar");
454 Console.error(t.getMessage());
455 // t.printStackTrace();
458 // set Proxy settings before all the internet calls
459 Cache.setProxyPropertiesFromPreferences();
461 desktop.setVisible(true);
463 if (!Platform.isJS())
472 * Check to see that the JVM version being run is suitable for the Java
473 * version this Jalview was compiled for. Popup a warning if not.
475 if (!LaunchUtils.checkJavaVersion())
477 Console.warn("The Java version being used (Java "
478 + LaunchUtils.getJavaVersion()
479 + ") may lead to problems. This installation of Jalview should be used with Java "
480 + LaunchUtils.getJavaCompileVersion() + ".");
483 .getBooleanUserPreference("IGNORE_JVM_WARNING_POPUP"))
486 MessageManager.getString("label.continue") };
487 JOptionPane.showOptionDialog(null,
488 MessageManager.formatMessage(
489 "warning.wrong_jvm_version_message",
490 LaunchUtils.getJavaVersion(),
491 LaunchUtils.getJavaCompileVersion()),
493 .getString("warning.wrong_jvm_version_title"),
494 JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE,
495 null, options, options[0]);
499 if (!aparser.contains("nowebservicediscovery"))
501 desktop.startServiceDiscovery();
503 if (!aparser.contains("nousagestats"))
505 startUsageStats(desktop);
509 System.err.println("CMD [-nousagestats] executed successfully!");
512 if (!aparser.contains("noquestionnaire"))
514 String url = aparser.getValue("questionnaire");
517 // Start the desktop questionnaire prompter with the specified
519 Console.debug("Starting questionnaire url at " + url);
520 desktop.checkForQuestionnaire(url);
521 System.out.println("CMD questionnaire[-" + url
522 + "] executed successfully!");
526 if (Cache.getProperty("NOQUESTIONNAIRES") == null)
528 // Start the desktop questionnaire prompter with the specified
531 // "http://anaplog.compbio.dundee.ac.uk/cgi-bin/questionnaire.pl";
533 String defurl = "https://www.jalview.org/cgi-bin/questionnaire.pl";
535 "Starting questionnaire with default url: " + defurl);
536 desktop.checkForQuestionnaire(defurl);
543 .println("CMD [-noquestionnaire] executed successfully!");
546 if (!aparser.contains("nonews")
547 || Cache.getProperty("NONEWS") == null)
549 desktop.checkForNews();
552 if (!aparser.contains("nohtmltemplates")
553 || Cache.getProperty("NOHTMLTEMPLATES") == null)
555 BioJsHTMLOutput.updateBioJS();
560 // Check if JVM and compile version might cause problems and log if it
562 if (headless && !Platform.isJS() && !LaunchUtils.checkJavaVersion())
564 Console.warn("The Java version being used (Java "
565 + LaunchUtils.getJavaVersion()
566 + ") may lead to problems. This installation of Jalview should be used with Java "
567 + LaunchUtils.getJavaCompileVersion() + ".");
570 // Move any new getdown-launcher-new.jar into place over old
571 // getdown-launcher.jar
572 String appdirString = System.getProperty("getdownappdir");
573 if (appdirString != null && appdirString.length() > 0)
575 final File appdir = new File(appdirString);
581 LaunchUtil.upgradeGetdown(
582 new File(appdir, "getdown-launcher-old.jar"),
583 new File(appdir, "getdown-launcher.jar"),
584 new File(appdir, "getdown-launcher-new.jar"));
589 String file = null, data = null;
590 FileFormatI format = null;
591 DataSourceType protocol = null;
592 FileLoader fileLoader = new FileLoader(!headless);
594 String groovyscript = null; // script to execute after all loading is
595 // completed one way or another
596 // extract groovy argument and execute if necessary
597 groovyscript = aparser.getValue("groovy", true);
598 file = aparser.getValue("open", true);
600 if (file == null && desktop == null)
602 System.out.println("No files to open!");
606 // Finally, deal with the remaining input data.
611 desktop.setProgressBar(
613 .getString("status.processing_commandline_args"),
614 progress = System.currentTimeMillis());
616 System.out.println("CMD [-open " + file + "] executed successfully!");
618 if (!Platform.isJS())
620 * ignore in JavaScript -- can't just file existence - could load it?
625 if (!HttpUtils.startsWithHttpOrHttps(file))
627 if (!(new File(file)).exists())
629 System.out.println("Can't find " + file);
638 protocol = AppletFormatAdapter.checkProtocol(file);
642 format = new IdentifyFile().identify(file, protocol);
643 } catch (FileFormatException e1)
648 AlignFrame af = fileLoader.LoadFileWaitTillLoaded(file, protocol,
652 System.out.println("error");
656 setCurrentAlignFrame(af);
657 data = aparser.getValue("colour", true);
660 data.replaceAll("%20", " ");
662 ColourSchemeI cs = ColourSchemeProperty.getColourScheme(
663 af.getViewport(), af.getViewport().getAlignment(), data);
668 "CMD [-color " + data + "] executed successfully!");
673 // Must maintain ability to use the groups flag
674 data = aparser.getValue("groups", true);
677 af.parseFeaturesFile(data,
678 AppletFormatAdapter.checkProtocol(data));
679 // System.out.println("Added " + data);
681 "CMD groups[-" + data + "] executed successfully!");
683 data = aparser.getValue("features", true);
686 af.parseFeaturesFile(data,
687 AppletFormatAdapter.checkProtocol(data));
688 // System.out.println("Added " + data);
690 "CMD [-features " + data + "] executed successfully!");
693 data = aparser.getValue("annotations", true);
696 af.loadJalviewDataFile(data, null, null, null);
697 // System.out.println("Added " + data);
699 "CMD [-annotations " + data + "] executed successfully!");
701 // set or clear the sortbytree flag.
702 if (aparser.contains("sortbytree"))
704 af.getViewport().setSortByTree(true);
705 if (af.getViewport().getSortByTree())
707 System.out.println("CMD [-sortbytree] executed successfully!");
710 if (aparser.contains("no-annotation"))
712 af.getViewport().setShowAnnotation(false);
713 if (!af.getViewport().isShowAnnotation())
715 System.out.println("CMD no-annotation executed successfully!");
718 if (aparser.contains("nosortbytree"))
720 af.getViewport().setSortByTree(false);
721 if (!af.getViewport().getSortByTree())
724 .println("CMD [-nosortbytree] executed successfully!");
727 data = aparser.getValue("tree", true);
733 "CMD [-tree " + data + "] executed successfully!");
734 NewickFile nf = new NewickFile(data,
735 AppletFormatAdapter.checkProtocol(data));
737 .setCurrentTree(af.showNewickTree(nf, data).getTree());
738 } catch (IOException ex)
740 System.err.println("Couldn't add tree " + data);
741 ex.printStackTrace(System.err);
744 // TODO - load PDB structure(s) to alignment JAL-629
745 // (associate with identical sequence in alignment, or a specified
747 if (groovyscript != null)
749 // Execute the groovy script after we've done all the rendering stuff
750 // and before any images or figures are generated.
751 System.out.println("Executing script " + groovyscript);
752 executeGroovyScript(groovyscript, af);
753 System.out.println("CMD groovy[" + groovyscript
754 + "] executed successfully!");
757 String imageName = "unnamed.png";
758 while (aparser.getSize() > 1)
760 String outputFormat = aparser.nextValue();
761 file = aparser.nextValue();
763 if (outputFormat.equalsIgnoreCase("png"))
765 af.createPNG(new File(file));
766 imageName = (new File(file)).getName();
767 System.out.println("Creating PNG image: " + file);
770 else if (outputFormat.equalsIgnoreCase("svg"))
772 File imageFile = new File(file);
773 imageName = imageFile.getName();
774 af.createSVG(imageFile);
775 System.out.println("Creating SVG image: " + file);
778 else if (outputFormat.equalsIgnoreCase("html"))
780 File imageFile = new File(file);
781 imageName = imageFile.getName();
782 HtmlSvgOutput htmlSVG = new HtmlSvgOutput(af.alignPanel);
783 htmlSVG.exportHTML(file);
785 System.out.println("Creating HTML image: " + file);
788 else if (outputFormat.equalsIgnoreCase("biojsmsa"))
792 System.err.println("The output html file must not be null");
797 BioJsHTMLOutput.refreshVersionInfo(
798 BioJsHTMLOutput.BJS_TEMPLATES_LOCAL_DIRECTORY);
799 } catch (URISyntaxException e)
803 BioJsHTMLOutput bjs = new BioJsHTMLOutput(af.alignPanel);
804 bjs.exportHTML(file);
806 .println("Creating BioJS MSA Viwer HTML file: " + file);
809 else if (outputFormat.equalsIgnoreCase("imgMap"))
811 af.createImageMap(new File(file), imageName);
812 System.out.println("Creating image map: " + file);
815 else if (outputFormat.equalsIgnoreCase("eps"))
817 File outputFile = new File(file);
819 "Creating EPS file: " + outputFile.getAbsolutePath());
820 af.createEPS(outputFile);
823 FileFormatI outFormat = null;
826 outFormat = FileFormats.getInstance().forName(outputFormat);
827 } catch (Exception formatP)
829 System.out.println("Couldn't parse " + outFormat
830 + " as a valid Jalview format string.");
832 if (outFormat != null)
834 if (!outFormat.isWritable())
837 "This version of Jalview does not support alignment export as "
842 af.saveAlignment(file, outFormat);
843 if (af.isSaveAlignmentSuccessful())
845 System.out.println("Written alignment in "
846 + outFormat.getName() + " format to " + file);
850 System.out.println("Error writing file " + file + " in "
851 + outFormat.getName() + " format!!");
858 while (aparser.getSize() > 0)
860 System.out.println("Unknown arg: " + aparser.nextValue());
864 AlignFrame startUpAlframe = null;
865 // We'll only open the default file if the desktop is visible.
867 // ////////////////////
869 if (!Platform.isJS() && !headless && file == null
870 && Cache.getDefault("SHOW_STARTUP_FILE", true))
877 file = Cache.getDefault("STARTUP_FILE",
878 Cache.getDefault("www.jalview.org", "https://www.jalview.org")
879 + "/examples/exampleFile_2_7.jvp");
880 if (file.equals("http://www.jalview.org/examples/exampleFile_2_3.jar")
882 "http://www.jalview.org/examples/exampleFile_2_7.jar"))
884 file.replace("http:", "https:");
885 // hardwire upgrade of the startup file
886 file.replace("_2_3", "_2_7");
887 file.replace("2_7.jar", "2_7.jvp");
888 // and remove the stale setting
889 Cache.removeProperty("STARTUP_FILE");
892 protocol = AppletFormatAdapter.checkProtocol(file);
894 if (file.endsWith(".jar"))
896 format = FileFormat.Jalview;
902 format = new IdentifyFile().identify(file, protocol);
903 } catch (FileFormatException e)
909 startUpAlframe = fileLoader.LoadFileWaitTillLoaded(file, protocol,
911 // extract groovy arguments before anything else.
914 // Once all other stuff is done, execute any groovy scripts (in order)
915 if (groovyscript != null)
917 if (Cache.groovyJarsPresent())
919 System.out.println("Executing script " + groovyscript);
920 executeGroovyScript(groovyscript, startUpAlframe);
925 "Sorry. Groovy Support is not available, so ignoring the provided groovy script "
929 // and finally, turn off batch mode indicator - if the desktop still exists
934 desktop.setProgressBar(null, progress);
936 desktop.setInBatchMode(false);
940 private static void setLookAndFeel()
942 // property laf = "crossplatform", "system", "gtk", "metal", "nimbus",
944 // If not set (or chosen laf fails), use the normal SystemLaF and if on Mac,
946 String lafProp = System.getProperty("laf");
947 String lafSetting = Cache.getDefault("PREFERRED_LAF", null);
953 else if (lafSetting != null)
957 boolean lafSet = false;
960 case "crossplatform":
961 lafSet = setCrossPlatformLookAndFeel();
964 Console.error("Could not set requested laf=" + laf);
968 lafSet = setSystemLookAndFeel();
971 Console.error("Could not set requested laf=" + laf);
975 lafSet = setGtkLookAndFeel();
978 Console.error("Could not set requested laf=" + laf);
982 lafSet = setMetalLookAndFeel();
985 Console.error("Could not set requested laf=" + laf);
989 lafSet = setNimbusLookAndFeel();
992 Console.error("Could not set requested laf=" + laf);
996 lafSet = setFlatLookAndFeel();
999 Console.error("Could not set requested laf=" + laf);
1003 lafSet = setQuaquaLookAndFeel();
1006 Console.error("Could not set requested laf=" + laf);
1010 lafSet = setVaquaLookAndFeel();
1013 Console.error("Could not set requested laf=" + laf);
1017 lafSet = setMacLookAndFeel();
1020 Console.error("Could not set requested laf=" + laf);
1026 Console.error("Requested laf=" + laf + " not implemented");
1030 setSystemLookAndFeel();
1031 if (Platform.isLinux())
1033 setMetalLookAndFeel();
1035 if (Platform.isMac())
1037 setMacLookAndFeel();
1042 private static boolean setCrossPlatformLookAndFeel()
1044 boolean set = false;
1047 UIManager.setLookAndFeel(
1048 UIManager.getCrossPlatformLookAndFeelClassName());
1050 } catch (Exception ex)
1052 Console.error("Unexpected Look and Feel Exception");
1053 Console.error(ex.getMessage());
1054 Console.debug(Cache.getStackTraceString(ex));
1059 private static boolean setSystemLookAndFeel()
1061 boolean set = false;
1064 UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
1066 } catch (Exception ex)
1068 Console.error("Unexpected Look and Feel Exception");
1069 Console.error(ex.getMessage());
1070 Console.debug(Cache.getStackTraceString(ex));
1075 private static boolean setSpecificLookAndFeel(String name,
1076 String className, boolean nameStartsWith)
1078 boolean set = false;
1081 for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels())
1083 if (info.getName() != null && nameStartsWith
1084 ? info.getName().toLowerCase(Locale.ROOT)
1085 .startsWith(name.toLowerCase(Locale.ROOT))
1086 : info.getName().toLowerCase(Locale.ROOT)
1087 .equals(name.toLowerCase(Locale.ROOT)))
1089 className = info.getClassName();
1093 UIManager.setLookAndFeel(className);
1095 } catch (Exception ex)
1097 Console.error("Unexpected Look and Feel Exception");
1098 Console.error(ex.getMessage());
1099 Console.debug(Cache.getStackTraceString(ex));
1104 private static boolean setGtkLookAndFeel()
1106 return setSpecificLookAndFeel("gtk",
1107 "com.sun.java.swing.plaf.gtk.GTKLookAndFeel", true);
1110 private static boolean setMetalLookAndFeel()
1112 return setSpecificLookAndFeel("metal",
1113 "javax.swing.plaf.metal.MetalLookAndFeel", false);
1116 private static boolean setNimbusLookAndFeel()
1118 return setSpecificLookAndFeel("nimbus",
1119 "javax.swing.plaf.nimbus.NimbusLookAndFeel", false);
1122 private static boolean setFlatLookAndFeel()
1124 boolean set = setSpecificLookAndFeel("flatlaf light",
1125 "com.formdev.flatlaf.FlatLightLaf", false);
1128 if (Platform.isMac())
1130 System.setProperty("apple.laf.useScreenMenuBar", "true");
1131 System.setProperty("apple.awt.application.name",
1132 ChannelProperties.getProperty("app_name"));
1133 System.setProperty("apple.awt.application.appearance", "system");
1134 if (SystemInfo.isMacFullWindowContentSupported
1135 && Desktop.desktop != null)
1137 Desktop.desktop.getRootPane()
1138 .putClientProperty("apple.awt.fullWindowContent", true);
1139 Desktop.desktop.getRootPane()
1140 .putClientProperty("apple.awt.transparentTitleBar", true);
1143 SwingUtilities.invokeLater(() -> {
1144 FlatLightLaf.setup();
1148 UIManager.put("TabbedPane.showTabSeparators", true);
1149 UIManager.put("TabbedPane.tabSeparatorsFullHeight", true);
1150 UIManager.put("TabbedPane.tabsOverlapBorder", true);
1151 // UIManager.put("TabbedPane.hasFullBorder", true);
1152 UIManager.put("TabbedPane.tabLayoutPolicy", "scroll");
1153 UIManager.put("TabbedPane.scrollButtonsPolicy", "asNeeded");
1154 UIManager.put("TabbedPane.smoothScrolling", true);
1155 UIManager.put("TabbedPane.tabWidthMode", "compact");
1156 UIManager.put("TabbedPane.selectedBackground", Color.white);
1161 private static boolean setQuaquaLookAndFeel()
1163 return setSpecificLookAndFeel("quaqua",
1164 ch.randelshofer.quaqua.QuaquaManager.getLookAndFeel().getClass()
1169 private static boolean setVaquaLookAndFeel()
1171 return setSpecificLookAndFeel("vaqua",
1172 "org.violetlib.aqua.AquaLookAndFeel", false);
1175 private static boolean setMacLookAndFeel()
1177 boolean set = false;
1178 System.setProperty("com.apple.mrj.application.apple.menu.about.name",
1179 ChannelProperties.getProperty("app_name"));
1180 System.setProperty("apple.laf.useScreenMenuBar", "true");
1182 * broken native LAFs on (ARM?) macbooks
1183 set = setQuaquaLookAndFeel();
1184 if ((!set) || !UIManager.getLookAndFeel().getClass().toString()
1185 .toLowerCase(Locale.ROOT).contains("quaqua"))
1187 set = setVaquaLookAndFeel();
1190 set = setFlatLookAndFeel();
1194 private static void showUsage()
1197 "Usage: jalview -open [FILE] [OUTPUT_FORMAT] [OUTPUT_FILE]\n\n"
1198 + "-nodisplay\tRun Jalview without User Interface.\n"
1199 + "-props FILE\tUse the given Jalview properties file instead of users default.\n"
1200 + "-colour COLOURSCHEME\tThe colourscheme to be applied to the alignment\n"
1201 + "-annotations FILE\tAdd precalculated annotations to the alignment.\n"
1202 + "-tree FILE\tLoad the given newick format tree file onto the alignment\n"
1203 + "-features FILE\tUse the given file to mark features on the alignment.\n"
1204 + "-fasta FILE\tCreate alignment file FILE in Fasta format.\n"
1205 + "-clustal FILE\tCreate alignment file FILE in Clustal format.\n"
1206 + "-pfam FILE\tCreate alignment file FILE in PFAM format.\n"
1207 + "-msf FILE\tCreate alignment file FILE in MSF format.\n"
1208 + "-pileup FILE\tCreate alignment file FILE in Pileup format\n"
1209 + "-pir FILE\tCreate alignment file FILE in PIR format.\n"
1210 + "-blc FILE\tCreate alignment file FILE in BLC format.\n"
1211 + "-json FILE\tCreate alignment file FILE in JSON format.\n"
1212 + "-jalview FILE\tCreate alignment file FILE in Jalview format.\n"
1213 + "-png FILE\tCreate PNG image FILE from alignment.\n"
1214 + "-svg FILE\tCreate SVG image FILE from alignment.\n"
1215 + "-html FILE\tCreate HTML file from alignment.\n"
1216 + "-biojsMSA FILE\tCreate BioJS MSA Viewer HTML file from alignment.\n"
1217 + "-imgMap FILE\tCreate HTML file FILE with image map of PNG image.\n"
1218 + "-eps FILE\tCreate EPS file FILE from alignment.\n"
1219 + "-questionnaire URL\tQueries the given URL for information about any Jalview user questionnaires.\n"
1220 + "-noquestionnaire\tTurn off questionnaire check.\n"
1221 + "-nonews\tTurn off check for Jalview news.\n"
1222 + "-nousagestats\tTurn off google analytics tracking for this session.\n"
1223 + "-sortbytree OR -nosortbytree\tEnable or disable sorting of the given alignment by the given tree\n"
1225 // "-setprop PROPERTY=VALUE\tSet the given Jalview property,
1226 // after all other properties files have been read\n\t
1227 // (quote the 'PROPERTY=VALUE' pair to ensure spaces are
1228 // passed in correctly)"
1229 + "-jabaws URL\tSpecify URL for Jabaws services (e.g. for a local installation).\n"
1230 + "-fetchfrom nickname\tQuery nickname for features for the alignments and display them.\n"
1231 + "-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"
1232 + "-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"
1233 + "-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"
1234 + "\n~Read documentation in Application or visit https://www.jalview.org for description of Features and Annotations file~\n\n");
1237 private static void startUsageStats(final Desktop desktop)
1240 * start a User Config prompt asking if we can log usage statistics.
1242 PromptUserConfig prompter = new PromptUserConfig(Desktop.desktop,
1243 "USAGESTATS", "Jalview Usage Statistics",
1244 "Do you want to help make Jalview better by enabling "
1245 + "the collection of usage statistics with Google Analytics ?"
1246 + "\n\n(you can enable or disable usage tracking in the preferences)",
1253 "Initialising googletracker for usage stats.");
1254 Cache.initGoogleTracker();
1255 Console.debug("Tracking enabled.");
1262 Console.debug("Not enabling Google Tracking.");
1265 desktop.addDialogThread(prompter);
1269 * Locate the given string as a file and pass it to the groovy interpreter.
1271 * @param groovyscript
1272 * the script to execute
1273 * @param jalviewContext
1274 * the Jalview Desktop object passed in to the groovy binding as the
1277 private void executeGroovyScript(String groovyscript, AlignFrame af)
1280 * for scripts contained in files
1287 if (groovyscript.trim().equals("STDIN"))
1289 // read from stdin into a tempfile and execute it
1292 tfile = File.createTempFile("jalview", "groovy");
1293 PrintWriter outfile = new PrintWriter(
1294 new OutputStreamWriter(new FileOutputStream(tfile)));
1295 BufferedReader br = new BufferedReader(
1296 new InputStreamReader(System.in));
1298 while ((line = br.readLine()) != null)
1300 outfile.write(line + "\n");
1306 } catch (Exception ex)
1308 System.err.println("Failed to read from STDIN into tempfile "
1309 + ((tfile == null) ? "(tempfile wasn't created)"
1310 : tfile.toString()));
1311 ex.printStackTrace();
1316 sfile = tfile.toURI().toURL();
1317 } catch (Exception x)
1320 "Unexpected Malformed URL Exception for temporary file created from STDIN: "
1322 x.printStackTrace();
1330 sfile = new URI(groovyscript).toURL();
1331 } catch (Exception x)
1333 tfile = new File(groovyscript);
1334 if (!tfile.exists())
1336 System.err.println("File '" + groovyscript + "' does not exist.");
1339 if (!tfile.canRead())
1341 System.err.println("File '" + groovyscript + "' cannot be read.");
1344 if (tfile.length() < 1)
1346 System.err.println("File '" + groovyscript + "' is empty.");
1351 sfile = tfile.getAbsoluteFile().toURI().toURL();
1352 } catch (Exception ex)
1354 System.err.println("Failed to create a file URL for "
1355 + tfile.getAbsoluteFile());
1362 Map<String, java.lang.Object> vbinding = new HashMap<>();
1363 vbinding.put("Jalview", this);
1366 vbinding.put("currentAlFrame", af);
1368 Binding gbinding = new Binding(vbinding);
1369 GroovyScriptEngine gse = new GroovyScriptEngine(new URL[] { sfile });
1370 gse.run(sfile.toString(), gbinding);
1371 if ("STDIN".equals(groovyscript))
1373 // delete temp file that we made -
1374 // only if it was successfully executed
1377 } catch (Exception e)
1379 System.err.println("Exception Whilst trying to execute file " + sfile
1380 + " as a groovy script.");
1381 e.printStackTrace(System.err);
1386 public static boolean isHeadlessMode()
1388 String isheadless = System.getProperty("java.awt.headless");
1389 if (isheadless != null && isheadless.equalsIgnoreCase("true"))
1396 public AlignFrame[] getAlignFrames()
1398 return desktop == null ? new AlignFrame[] { getCurrentAlignFrame() }
1399 : Desktop.getAlignFrames();
1404 * Quit method delegates to Desktop.quit - unless running in headless mode
1405 * when it just ends the JVM
1409 if (desktop != null)
1419 public static AlignFrame getCurrentAlignFrame()
1421 return Jalview.currentAlignFrame;
1424 public static void setCurrentAlignFrame(AlignFrame currentAlignFrame)
1426 Jalview.currentAlignFrame = currentAlignFrame;