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.GraphicsEnvironment;
25 import java.io.BufferedReader;
27 import java.io.FileOutputStream;
28 import java.io.IOException;
29 import java.io.InputStreamReader;
30 import java.io.OutputStreamWriter;
31 import java.io.PrintWriter;
32 import java.net.MalformedURLException;
34 import java.net.URISyntaxException;
36 import java.security.AllPermission;
37 import java.security.CodeSource;
38 import java.security.PermissionCollection;
39 import java.security.Permissions;
40 import java.security.Policy;
41 import java.util.HashMap;
42 import java.util.Locale;
44 import java.util.Vector;
45 import java.util.logging.ConsoleHandler;
46 import java.util.logging.Level;
47 import java.util.logging.Logger;
49 import javax.swing.UIManager;
50 import javax.swing.UIManager.LookAndFeelInfo;
52 import com.threerings.getdown.util.LaunchUtil;
54 import groovy.lang.Binding;
55 import groovy.util.GroovyScriptEngine;
56 import jalview.api.AlignCalcWorkerI;
57 import jalview.bin.ApplicationSingletonProvider.ApplicationSingletonI;
58 import jalview.ext.so.SequenceOntology;
59 import jalview.gui.AlignFrame;
60 import jalview.gui.AlignViewport;
61 import jalview.gui.Desktop;
62 import jalview.gui.Preferences;
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.schemes.ColourSchemeI;
77 import jalview.schemes.ColourSchemeProperty;
78 import jalview.util.ChannelProperties;
79 import jalview.util.HttpUtils;
80 import jalview.util.MessageManager;
81 import jalview.util.Platform;
82 import jalview.ws.jws2.Jws2Discoverer;
85 * Main class for Jalview Application <br>
87 * start with: java -classpath "$PATH_TO_LIB$/*:$PATH_TO_CLASSES$" \
90 * or on Windows: java -classpath "$PATH_TO_LIB$/*;$PATH_TO_CLASSES$" \
91 * jalview.bin.Jalview jalview.bin.Jalview
93 * (ensure -classpath arg is quoted to avoid shell expansion of '*' and do not
94 * embellish '*' to e.g. '*.jar')
99 public class Jalview implements ApplicationSingletonI
101 // for testing those nasty messages you cannot ever find.
104 // System.setOut(new PrintStream(new ByteArrayOutputStream())
107 // public void println(Object o)
111 // System.err.println(o);
117 public static Jalview getInstance()
119 return (Jalview) ApplicationSingletonProvider
120 .getInstance(Jalview.class);
125 Platform.getURLCommandArguments();
129 private Desktop desktop;
131 public AlignFrame currentAlignFrame;
133 public String appletResourcePath;
135 public String j2sAppletID;
137 private boolean noCalculation, noMenuBar, noStatus;
139 private boolean noAnnotation;
141 public boolean getStartCalculations()
143 return !noCalculation;
146 public boolean getAllowMenuBar()
151 public boolean getShowStatus()
156 public boolean getShowAnnotation()
158 return !noAnnotation;
163 if (!Platform.isJS())
170 // grab all the rights we can for the JVM
171 Policy.setPolicy(new Policy()
174 public PermissionCollection getPermissions(CodeSource codesource)
176 Permissions perms = new Permissions();
177 perms.add(new AllPermission());
182 public void refresh()
190 * keep track of feature fetching tasks.
198 * TODO: generalise to track all jalview events to orchestrate batch processing
202 private int queued = 0;
204 private int running = 0;
206 public FeatureFetcher()
211 public void addFetcher(final AlignFrame af,
212 final Vector<String> dasSources)
214 final long id = System.currentTimeMillis();
216 final FeatureFetcher us = this;
217 new Thread(new Runnable()
229 af.setProgressBar(MessageManager
230 .getString("status.das_features_being_retrived"), id);
231 af.featureSettings_actionPerformed(null);
232 af.setProgressBar(null, id);
241 public synchronized boolean allFinished()
243 return queued == 0 && running == 0;
248 private final static boolean doPlatformLogging = false;
251 * main class for Jalview application
254 * open <em>filename</em>
256 public static void main(String[] args)
258 if (doPlatformLogging)
260 Platform.startJavaLogging();
263 getInstance().doMain(args);
273 void doMain(String[] args)
276 boolean isJS = Platform.isJS();
279 System.setSecurityManager(null);
283 .println("Java version: " + System.getProperty("java.version"));
284 System.out.println("Java Home: " + System.getProperty("java.home"));
285 System.out.println(System.getProperty("os.arch") + " "
286 + System.getProperty("os.name") + " "
287 + System.getProperty("os.version"));
288 String val = System.getProperty("sys.install4jVersion");
291 System.out.println("Install4j version: " + val);
293 val = System.getProperty("installer_template_version");
296 System.out.println("Install4j template version: " + val);
298 val = System.getProperty("launcher_version");
301 System.out.println("Launcher version: " + val);
304 // report Jalview version
305 Cache.getInstance().loadBuildProperties(true);
307 ArgsParser aparser = new ArgsParser(args);
308 boolean headless = false;
310 String usrPropsFile = aparser.getValue("props");
311 Cache.loadProperties(usrPropsFile); // must do this before
312 boolean allowServices = true;
316 j2sAppletID = Platform.getAppID(null);
317 Preferences.setAppletDefaults();
318 Cache.loadProperties(usrPropsFile); // again, because we
319 // might be changing defaults here?
320 appletResourcePath = (String) aparser.getAppletValue("resourcepath",
331 if (usrPropsFile != null)
334 "CMD [-props " + usrPropsFile + "] executed successfully!");
336 if (aparser.contains("help") || aparser.contains("h"))
341 // BH note: Only -nodisplay is official; others are deprecated?
342 if (aparser.contains("nodisplay") || aparser.contains("nogui")
343 || aparser.contains("headless")
344 || GraphicsEnvironment.isHeadless())
347 // BH Definitely not a good idea in JavaScript;
348 // probably should not be here for Java, either.
349 System.setProperty("java.awt.headless", "true");
355 final String jabawsUrl = aparser.getValue(ArgsParser.JABAWS);
356 allowServices = !("none".equals(jabawsUrl));
357 if (allowServices && jabawsUrl != null)
361 Jws2Discoverer.getInstance().setPreferredUrl(jabawsUrl);
363 "CMD [-jabaws " + jabawsUrl + "] executed successfully!");
364 } catch (MalformedURLException e)
367 "Invalid jabaws parameter: " + jabawsUrl + " ignored");
372 String defs = aparser.getValue(ArgsParser.SETPROP);
375 int p = defs.indexOf('=');
378 System.err.println("Ignoring invalid setprop argument : " + defs);
382 System.out.println("Executing setprop argument: " + defs);
385 Cache.setProperty(defs.substring(0, p), defs.substring(p + 1));
388 defs = aparser.getValue("setprop");
390 if (System.getProperty("java.awt.headless") != null
391 && System.getProperty("java.awt.headless").equals("true"))
395 System.setProperty("http.agent",
396 "Jalview Desktop/" + Cache.getDefault("VERSION", "Unknown"));
400 } catch (NoClassDefFoundError error)
402 error.printStackTrace();
403 System.out.println("\nEssential logging libraries not found."
404 + "\nUse: java -classpath \"$PATH_TO_LIB$/*:$PATH_TO_CLASSES$\" jalview.bin.Jalview");
413 * configure 'full' SO model if preferences say to, else use the default (full SO)
414 * - as JS currently doesn't have OBO parsing, it must use 'Lite' version
416 boolean soDefault = !isJS;
417 if (Cache.getDefault("USE_FULL_SO", soDefault))
419 SequenceOntologyFactory.setInstance(new SequenceOntology());
424 Desktop.nosplash = aparser.contains("nosplash");
425 desktop = Desktop.getInstance();
426 desktop.setInBatchMode(true); // indicate we are starting up
430 JalviewTaskbar.setTaskbar(this);
431 } catch (Exception e)
433 Cache.log.info("Cannot set Taskbar");
434 Cache.log.error(e.getMessage());
435 // e.printStackTrace();
436 } catch (Throwable t)
438 Cache.log.info("Cannot set Taskbar");
439 Cache.log.error(t.getMessage());
440 // t.printStackTrace();
442 // set Proxy settings before all the internet calls
443 Cache.setProxyPropertiesFromPreferences();
445 desktop.setVisible(true);
449 Cache.setProperty("SHOW_JWS2_SERVICES", "false");
451 if (allowServices && !aparser.contains("nowebservicediscovery"))
453 desktop.startServiceDiscovery();
463 if (!aparser.contains("nousagestats"))
465 startUsageStats(desktop);
469 System.err.println("CMD [-nousagestats] executed successfully!");
472 if (!aparser.contains("noquestionnaire"))
474 String url = aparser.getValue("questionnaire");
477 // Start the desktop questionnaire prompter with the specified
479 Cache.log.debug("Starting questionnaire url at " + url);
480 desktop.checkForQuestionnaire(url);
481 System.out.println("CMD questionnaire[-" + url
482 + "] executed successfully!");
486 if (Cache.getProperty("NOQUESTIONNAIRES") == null)
488 // Start the desktop questionnaire prompter with the specified
491 // "http://anaplog.compbio.dundee.ac.uk/cgi-bin/questionnaire.pl";
493 String defurl = "https://www.jalview.org/cgi-bin/questionnaire.pl";
495 "Starting questionnaire with default url: " + defurl);
496 desktop.checkForQuestionnaire(defurl);
503 .println("CMD [-noquestionnaire] executed successfully!");
506 if (!aparser.contains("nonews"))
508 desktop.checkForNews();
511 BioJsHTMLOutput.updateBioJS();
514 parseArguments(aparser, true);
518 * Parse all command-line String[] arguments as well as all JavaScript-derived
519 * parameters from Info.
521 * We allow for this method to be run from JavaScript. Basically allowing
527 public void parseArguments(ArgsParser aparser, boolean isStartup)
530 String groovyscript = null; // script to execute after all loading is
531 boolean isJS = Platform.isJS();
535 // Move any new getdown-launcher-new.jar into place over old
536 // getdown-launcher.jar
537 String appdirString = System.getProperty("getdownappdir");
538 if (appdirString != null && appdirString.length() > 0)
540 final File appdir = new File(appdirString);
546 LaunchUtil.upgradeGetdown(
547 new File(appdir, "getdown-launcher-old.jar"),
548 new File(appdir, "getdown-launcher.jar"),
549 new File(appdir, "getdown-launcher-new.jar"));
554 // completed one way or another
555 // extract groovy argument and execute if necessary
556 groovyscript = aparser.getValue("groovy", true);
559 String file = aparser.getValue("open", true);
561 if (!isJS && file == null && desktop == null)
563 System.out.println("No files to open!");
566 setDisplayParameters(aparser);
568 // time to open a file.
570 DataSourceType protocol = null;
571 FileLoader fileLoader = new FileLoader(!headless);
572 FileFormatI format = null;
573 // Finally, deal with the remaining input data.
574 AlignFrame af = null;
576 JalviewJSApp jsApp = (isJS ? new JalviewJSApp(this, aparser) : null);
582 // JalviewJS allows sequence1 sequence2 ....
585 else if (!headless && Cache.getDefault("SHOW_STARTUP_FILE", true))
593 // We'll only open the default file if the desktop is visible.
595 // ////////////////////
597 file = Cache.getDefault("STARTUP_FILE",
598 Cache.getDefault("www.jalview.org",
599 "http://www.jalview.org")
600 + "/examples/exampleFile_2_7.jar");
602 "http://www.jalview.org/examples/exampleFile_2_3.jar"))
604 // hardwire upgrade of the startup file
605 file.replace("_2_3.jar", "_2_7.jar");
606 // and remove the stale setting
607 Cache.removeProperty("STARTUP_FILE");
610 protocol = DataSourceType.FILE;
612 if (file.indexOf("http:") > -1)
614 protocol = DataSourceType.URL;
617 if (file.endsWith(".jar"))
619 format = FileFormat.Jalview;
625 format = new IdentifyFile().identify(file, protocol);
626 } catch (FileFormatException e)
631 af = fileLoader.LoadFileWaitTillLoaded(file, protocol, format);
638 desktop.setProgressBar(
640 .getString("status.processing_commandline_args"),
641 progress = System.currentTimeMillis());
643 System.out.println("CMD [-open " + file + "] executed successfully!");
645 if (!Platform.isJS())
647 * ignore in JavaScript -- can't just file existence - could load it?
652 if (!HttpUtils.startsWithHttpOrHttps(file))
654 if (!(new File(file)).exists())
656 System.out.println("Can't find " + file);
665 // JS Only argument to provide a format parameter to specify what format to use
666 String fileFormat = (isJS
667 ? (String) aparser.getAppletValue("format", null, true)
669 protocol = AppletFormatAdapter.checkProtocol(file);
673 format = (fileFormat != null
674 ? FileFormats.getInstance().forName(fileFormat)
678 format = new IdentifyFile().identify(file, protocol);
680 } catch (FileFormatException e1)
685 af = new FileLoader(!headless).LoadFileWaitTillLoaded(file, protocol,
689 System.out.println("jalview error - AlignFrame was not created");
694 // JalviewLite interface for JavaScript allows second file open
695 String file2 = aparser.getValue(ArgsParser.OPEN2, true);
698 protocol = AppletFormatAdapter.checkProtocol(file2);
701 format = new IdentifyFile().identify(file2, protocol);
702 } catch (FileFormatException e1)
706 AlignFrame af2 = new FileLoader(!headless)
707 .LoadFileWaitTillLoaded(file2, protocol, format);
710 System.out.println("error");
714 AlignViewport.openLinkedAlignmentAs(af,
715 af.getViewport().getAlignment(),
716 af2.getViewport().getAlignment(), "",
717 AlignViewport.SPLIT_FRAME);
719 "CMD [-open2 " + file2 + "] executed successfully!");
722 // af is loaded - so set it as current frame
723 setCurrentAlignFrame(af);
725 setFrameDependentProperties(aparser, af);
729 jsApp.initFromParams(af);
738 if (groovyscript != null)
740 // Execute the groovy script after we've done all the rendering
742 // and before any images or figures are generated.
743 System.out.println("Executing script " + groovyscript);
744 executeGroovyScript(groovyscript, af);
745 System.out.println("CMD groovy[" + groovyscript
746 + "] executed successfully!");
750 if (!isJS || !isStartup) {
751 createOutputFiles(aparser, format);
756 af.getViewport().getCalcManager().shutdown();
759 // extract groovy arguments before anything else.
760 // Once all other stuff is done, execute any groovy scripts (in order)
761 if (!isJS && groovyscript != null)
763 if (Cache.groovyJarsPresent())
765 // TODO: DECIDE IF THIS SECOND PASS AT GROOVY EXECUTION IS STILL REQUIRED !!
766 System.out.println("Executing script " + groovyscript);
767 executeGroovyScript(groovyscript, af);
768 System.out.println("CMD groovy[" + groovyscript
769 + "] executed successfully!");
775 "Sorry. Groovy Support is not available, so ignoring the provided groovy script "
780 // and finally, turn off batch mode indicator - if the desktop still exists
785 desktop.setProgressBar(null, progress);
787 desktop.setInBatchMode(false);
791 jsApp.callInitCallback();
796 * Set general display parameters irrespective of file loading or headlessness.
800 private void setDisplayParameters(ArgsParser aparser)
802 if (aparser.contains(ArgsParser.NOMENUBAR))
805 System.out.println("CMD [nomenu] executed successfully!");
808 if (aparser.contains(ArgsParser.NOSTATUS))
811 System.out.println("CMD [nostatus] executed successfully!");
814 if (aparser.contains(ArgsParser.NOANNOTATION)
815 || aparser.contains(ArgsParser.NOANNOTATION2))
818 System.out.println("CMD no-annotation executed successfully!");
820 if (aparser.contains(ArgsParser.NOCALCULATION))
822 noCalculation = true;
823 System.out.println("CMD [nocalculation] executed successfully!");
828 private void setFrameDependentProperties(ArgsParser aparser,
831 String data = aparser.getValue(ArgsParser.COLOUR, true);
834 data.replaceAll("%20", " ");
836 ColourSchemeI cs = ColourSchemeProperty.getColourScheme(
837 af.getViewport(), af.getViewport().getAlignment(), data);
842 "CMD [-color " + data + "] executed successfully!");
847 // Must maintain ability to use the groups flag
848 data = aparser.getValue(ArgsParser.GROUPS, true);
851 af.parseFeaturesFile(data,
852 AppletFormatAdapter.checkProtocol(data));
853 // System.out.println("Added " + data);
855 "CMD groups[-" + data + "] executed successfully!");
857 data = aparser.getValue(ArgsParser.FEATURES, true);
860 af.parseFeaturesFile(data,
861 AppletFormatAdapter.checkProtocol(data));
862 // System.out.println("Added " + data);
864 "CMD [-features " + data + "] executed successfully!");
866 data = aparser.getValue(ArgsParser.ANNOTATIONS, true);
869 af.loadJalviewDataFile(data, null, null, null);
870 // System.out.println("Added " + data);
872 "CMD [-annotations " + data + "] executed successfully!");
875 // JavaScript feature
877 if (aparser.contains(ArgsParser.SHOWOVERVIEW))
879 af.overviewMenuItem_actionPerformed(null);
880 System.out.println("CMD [showoverview] executed successfully!");
883 // set or clear the sortbytree flag.
884 if (aparser.contains(ArgsParser.SORTBYTREE))
886 af.getViewport().setSortByTree(true);
887 if (af.getViewport().getSortByTree())
889 System.out.println("CMD [-sortbytree] executed successfully!");
893 boolean doUpdateAnnotation = false;
895 * we do this earlier in JalviewJS because of a complication with
898 * For now, just fixing this in JalviewJS.
907 af.getViewport().setShowAnnotation(false);
908 if (!af.getViewport().isShowAnnotation())
910 doUpdateAnnotation = true;
915 if (aparser.contains(ArgsParser.NOSORTBYTREE))
917 af.getViewport().setSortByTree(false);
918 if (!af.getViewport().getSortByTree())
920 doUpdateAnnotation = true;
922 .println("CMD [-nosortbytree] executed successfully!");
925 if (doUpdateAnnotation)
927 af.setMenusForViewport();
928 af.alignPanel.updateLayout();
931 data = aparser.getValue(ArgsParser.TREE, true);
936 NewickFile nf = new NewickFile(data,
937 AppletFormatAdapter.checkProtocol(data));
939 .setCurrentTree(af.showNewickTree(nf, data).getTree());
941 "CMD [-tree " + data + "] executed successfully!");
942 } catch (IOException ex)
944 System.err.println("Couldn't add tree " + data);
945 ex.printStackTrace(System.err);
948 // TODO - load PDB structure(s) to alignment JAL-629
949 // (associate with identical sequence in alignment, or a specified
955 * Writes an output file for each format (if any) specified in the
956 * command-line arguments. Supported formats are currently
965 * A format parameter should be followed by a parameter specifying the output
966 * file name. {@code imgMap} parameters should follow those for the
967 * corresponding alignment image output.
972 private void createOutputFiles(ArgsParser aparser, FileFormatI format)
974 // logic essentially the same as 2.11.2/2.11.3 but uses a switch instead
975 AlignFrame af = currentAlignFrame;
976 while (aparser.getSize() >= 2)
978 String outputFormat = aparser.nextValue();
981 switch (outputFormat.toLowerCase(Locale.ROOT))
984 imageFile = new File(aparser.nextValue());
985 af.createPNG(imageFile);
987 "Creating PNG image: " + imageFile.getAbsolutePath());
990 imageFile = new File(aparser.nextValue());
991 af.createSVG(imageFile);
993 "Creating SVG image: " + imageFile.getAbsolutePath());
996 imageFile = new File(aparser.nextValue());
998 "Creating EPS file: " + imageFile.getAbsolutePath());
999 af.createEPS(imageFile);
1002 fname = new File(aparser.nextValue()).getAbsolutePath();
1005 BioJsHTMLOutput.refreshVersionInfo(
1006 BioJsHTMLOutput.BJS_TEMPLATES_LOCAL_DIRECTORY);
1007 } catch (URISyntaxException e)
1009 e.printStackTrace();
1011 BioJsHTMLOutput bjs = new BioJsHTMLOutput(af.alignPanel);
1012 bjs.exportHTML(fname);
1013 System.out.println("Creating BioJS MSA Viwer HTML file: " + fname);
1016 fname = new File(aparser.nextValue()).getAbsolutePath();
1017 HtmlSvgOutput htmlSVG = new HtmlSvgOutput(af.alignPanel);
1018 htmlSVG.exportHTML(fname);
1019 System.out.println("Creating HTML image: " + fname);
1022 imageFile = new File(aparser.nextValue());
1023 af.alignPanel.makePNGImageMap(imageFile, "unnamed.png");
1025 "Creating image map: " + imageFile.getAbsolutePath());
1028 // fall through - try to parse as an alignment data export format
1029 FileFormatI outFormat = null;
1032 outFormat = FileFormats.getInstance().forName(outputFormat);
1033 } catch (Exception formatP)
1036 if (outFormat == null)
1038 System.out.println("Couldn't parse " + outputFormat
1039 + " as a valid Jalview format string.");
1042 if (!outFormat.isWritable())
1045 "This version of Jalview does not support alignment export as "
1049 // record file as it was passed to Jalview so it is recognisable to the CLI
1052 fname = new File(file = aparser.nextValue()).getAbsolutePath();
1053 // JBPNote - yuck - really wish we did have a bean returned from this which gave
1054 // success/fail like before !
1055 af.saveAlignment(fname, outFormat);
1056 if (!af.isSaveAlignmentSuccessful())
1058 System.out.println("Written alignment in " + outputFormat
1059 + " format to " + file);
1064 System.out.println("Error writing file " + file + " in "
1065 + outputFormat + " format!!");
1069 // ??? Should report - 'ignoring' extra args here...
1070 while (aparser.getSize() > 0)
1072 System.out.println("Ignoring extra argument: " + aparser.nextValue());
1076 private static void setLookAndFeel()
1078 // property laf = "crossplatform", "system", "gtk", "metal", "nimbus" or
1080 // If not set (or chosen laf fails), use the normal SystemLaF and if on Mac,
1081 // try Quaqua/Vaqua.
1082 String lafProp = System.getProperty("laf");
1083 String lafSetting = Cache.getDefault("PREFERRED_LAF", null);
1084 String laf = "none";
1085 if (lafProp != null)
1089 else if (lafSetting != null)
1093 boolean lafSet = false;
1096 case "crossplatform":
1097 lafSet = setCrossPlatformLookAndFeel();
1100 Cache.log.error("Could not set requested laf=" + laf);
1104 lafSet = setSystemLookAndFeel();
1107 Cache.log.error("Could not set requested laf=" + laf);
1111 lafSet = setGtkLookAndFeel();
1114 Cache.log.error("Could not set requested laf=" + laf);
1118 lafSet = setMetalLookAndFeel();
1121 Cache.log.error("Could not set requested laf=" + laf);
1125 lafSet = setNimbusLookAndFeel();
1128 Cache.log.error("Could not set requested laf=" + laf);
1132 lafSet = setQuaquaLookAndFeel();
1135 Cache.log.error("Could not set requested laf=" + laf);
1139 lafSet = setVaquaLookAndFeel();
1142 Cache.log.error("Could not set requested laf=" + laf);
1146 lafSet = setMacLookAndFeel();
1149 Cache.log.error("Could not set requested laf=" + laf);
1155 Cache.log.error("Requested laf=" + laf + " not implemented");
1159 setSystemLookAndFeel();
1160 if (Platform.isLinux())
1162 setMetalLookAndFeel();
1164 if (Platform.isMac())
1166 setMacLookAndFeel();
1171 private static boolean setCrossPlatformLookAndFeel()
1173 boolean set = false;
1176 UIManager.setLookAndFeel(
1177 UIManager.getCrossPlatformLookAndFeelClassName());
1179 } catch (Exception ex)
1181 Cache.log.error("Unexpected Look and Feel Exception");
1182 Cache.log.error(ex.getMessage());
1183 Cache.log.debug(Cache.getStackTraceString(ex));
1188 private static boolean setSystemLookAndFeel()
1190 boolean set = false;
1193 UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
1195 } catch (Exception ex)
1197 Cache.log.error("Unexpected Look and Feel Exception");
1198 Cache.log.error(ex.getMessage());
1199 Cache.log.debug(Cache.getStackTraceString(ex));
1204 private static boolean setSpecificLookAndFeel(String name,
1205 String className, boolean nameStartsWith)
1207 boolean set = false;
1210 for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels())
1212 if (info.getName() != null && nameStartsWith
1213 ? info.getName().toLowerCase(Locale.ROOT)
1214 .startsWith(name.toLowerCase(Locale.ROOT))
1215 : info.getName().toLowerCase(Locale.ROOT).equals(name.toLowerCase(Locale.ROOT)))
1217 className = info.getClassName();
1221 UIManager.setLookAndFeel(className);
1223 } catch (Exception ex)
1225 Cache.log.error("Unexpected Look and Feel Exception");
1226 Cache.log.error(ex.getMessage());
1227 Cache.log.debug(Cache.getStackTraceString(ex));
1232 private static boolean setGtkLookAndFeel()
1234 return setSpecificLookAndFeel("gtk",
1235 "com.sun.java.swing.plaf.gtk.GTKLookAndFeel", true);
1238 private static boolean setMetalLookAndFeel()
1240 return setSpecificLookAndFeel("metal",
1241 "javax.swing.plaf.metal.MetalLookAndFeel", false);
1244 private static boolean setNimbusLookAndFeel()
1246 return setSpecificLookAndFeel("nimbus",
1247 "javax.swing.plaf.nimbus.NimbusLookAndFeel", false);
1250 private static boolean setQuaquaLookAndFeel()
1252 return setSpecificLookAndFeel("quaqua",
1253 ch.randelshofer.quaqua.QuaquaManager.getLookAndFeel().getClass()
1258 private static boolean setVaquaLookAndFeel()
1260 return setSpecificLookAndFeel("vaqua",
1261 "org.violetlib.aqua.AquaLookAndFeel", false);
1264 private static boolean setMacLookAndFeel()
1266 boolean set = false;
1267 System.setProperty("com.apple.mrj.application.apple.menu.about.name",
1268 ChannelProperties.getProperty("app_name"));
1269 System.setProperty("apple.laf.useScreenMenuBar", "true");
1270 set = setQuaquaLookAndFeel();
1271 if ((!set) || !UIManager.getLookAndFeel().getClass().toString()
1272 .toLowerCase(Locale.ROOT).contains("quaqua"))
1274 set = setVaquaLookAndFeel();
1278 private static void showUsage()
1281 "Usage: jalview -open [FILE] [OUTPUT_FORMAT] [OUTPUT_FILE]\n\n"
1282 + "-nodisplay\tRun Jalview without User Interface.\n"
1283 + "-props FILE\tUse the given Jalview properties file instead of users default.\n"
1284 + "-colour COLOURSCHEME\tThe colourscheme to be applied to the alignment\n"
1285 + "-annotations FILE\tAdd precalculated annotations to the alignment.\n"
1286 + "-tree FILE\tLoad the given newick format tree file onto the alignment\n"
1287 + "-features FILE\tUse the given file to mark features on the alignment.\n"
1288 + "-fasta FILE\tCreate alignment file FILE in Fasta format.\n"
1289 + "-clustal FILE\tCreate alignment file FILE in Clustal format.\n"
1290 + "-pfam FILE\tCreate alignment file FILE in PFAM format.\n"
1291 + "-msf FILE\tCreate alignment file FILE in MSF format.\n"
1292 + "-pileup FILE\tCreate alignment file FILE in Pileup format\n"
1293 + "-pir FILE\tCreate alignment file FILE in PIR format.\n"
1294 + "-blc FILE\tCreate alignment file FILE in BLC format.\n"
1295 + "-json FILE\tCreate alignment file FILE in JSON format.\n"
1296 + "-jalview FILE\tCreate alignment file FILE in Jalview format.\n"
1297 + "-png FILE\tCreate PNG image FILE from alignment.\n"
1298 + "-svg FILE\tCreate SVG image FILE from alignment.\n"
1299 + "-html FILE\tCreate HTML file from alignment.\n"
1300 + "-biojsMSA FILE\tCreate BioJS MSA Viewer HTML file from alignment.\n"
1301 + "-imgMap FILE\tCreate HTML file FILE with image map of PNG image.\n"
1302 + "-eps FILE\tCreate EPS file FILE from alignment.\n"
1303 + "-questionnaire URL\tQueries the given URL for information about any Jalview user questionnaires.\n"
1304 + "-noquestionnaire\tTurn off questionnaire check.\n"
1305 + "-nonews\tTurn off check for Jalview news.\n"
1306 + "-nousagestats\tTurn off google analytics tracking for this session.\n"
1307 + "-sortbytree OR -nosortbytree\tEnable or disable sorting of the given alignment by the given tree\n"
1309 // "-setprop PROPERTY=VALUE\tSet the given Jalview property,
1310 // after all other properties files have been read\n\t
1311 // (quote the 'PROPERTY=VALUE' pair to ensure spaces are
1312 // passed in correctly)"
1313 + "-jabaws URL\tSpecify URL for Jabaws services (e.g. for a local installation).\n"
1314 + "-fetchfrom nickname\tQuery nickname for features for the alignments and display them.\n"
1315 + "-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"
1316 + "-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"
1317 + "-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"
1318 + "\n~Read documentation in Application or visit https://www.jalview.org for description of Features and Annotations file~\n\n");
1321 private static void startUsageStats(final Desktop desktop)
1324 * start a User Config prompt asking if we can log usage statistics.
1326 PromptUserConfig prompter = new PromptUserConfig(Desktop.getDesktopPane(),
1327 "USAGESTATS", "Jalview Usage Statistics",
1328 "Do you want to help make Jalview better by enabling "
1329 + "the collection of usage statistics with Google Analytics ?"
1330 + "\n\n(you can enable or disable usage tracking in the preferences)",
1337 "Initialising googletracker for usage stats.");
1338 Cache.initGoogleTracker();
1339 Cache.log.debug("Tracking enabled.");
1346 Cache.log.debug("Not enabling Google Tracking.");
1349 desktop.addDialogThread(prompter);
1353 * Locate the given string as a file and pass it to the groovy interpreter.
1355 * @param groovyscript
1356 * the script to execute
1357 * @param jalviewContext
1358 * the Jalview Desktop object passed in to the groovy binding as the
1361 private void executeGroovyScript(String groovyscript, AlignFrame af)
1364 * for scripts contained in files
1371 if (groovyscript.trim().equals("STDIN"))
1373 // read from stdin into a tempfile and execute it
1376 tfile = File.createTempFile("jalview", "groovy");
1377 PrintWriter outfile = new PrintWriter(
1378 new OutputStreamWriter(new FileOutputStream(tfile)));
1379 BufferedReader br = new BufferedReader(
1380 new InputStreamReader(System.in));
1382 while ((line = br.readLine()) != null)
1384 outfile.write(line + "\n");
1390 } catch (Exception ex)
1392 System.err.println("Failed to read from STDIN into tempfile "
1393 + ((tfile == null) ? "(tempfile wasn't created)"
1394 : tfile.toString()));
1395 ex.printStackTrace();
1400 sfile = tfile.toURI().toURL();
1401 } catch (Exception x)
1404 "Unexpected Malformed URL Exception for temporary file created from STDIN: "
1406 x.printStackTrace();
1414 sfile = new URI(groovyscript).toURL();
1415 } catch (Exception x)
1417 tfile = new File(groovyscript);
1418 if (!tfile.exists())
1420 System.err.println("File '" + groovyscript + "' does not exist.");
1423 if (!tfile.canRead())
1425 System.err.println("File '" + groovyscript + "' cannot be read.");
1428 if (tfile.length() < 1)
1430 System.err.println("File '" + groovyscript + "' is empty.");
1435 sfile = tfile.getAbsoluteFile().toURI().toURL();
1436 } catch (Exception ex)
1438 System.err.println("Failed to create a file URL for "
1439 + tfile.getAbsoluteFile());
1446 Map<String, java.lang.Object> vbinding = new HashMap<>();
1447 vbinding.put("Jalview", this);
1450 vbinding.put("currentAlFrame", af);
1452 Binding gbinding = new Binding(vbinding);
1453 GroovyScriptEngine gse = new GroovyScriptEngine(new URL[] { sfile });
1454 gse.run(sfile.toString(), gbinding);
1455 if ("STDIN".equals(groovyscript))
1457 // delete temp file that we made -
1458 // only if it was successfully executed
1461 } catch (Exception e)
1463 System.err.println("Exception Whilst trying to execute file " + sfile
1464 + " as a groovy script.");
1465 e.printStackTrace(System.err);
1470 public static boolean isHeadlessMode()
1472 String isheadless = System.getProperty("java.awt.headless");
1473 if (isheadless != null && isheadless.equalsIgnoreCase("true"))
1480 public AlignFrame[] getAlignFrames()
1482 return desktop == null ? new AlignFrame[] { getCurrentAlignFrame() }
1483 : Desktop.getAlignFrames();
1488 * Quit method delegates to Desktop.quit - unless running in headless mode when
1489 * it just ends the JVM
1493 if (desktop != null)
1503 public static AlignFrame getCurrentAlignFrame()
1505 return Jalview.getInstance().currentAlignFrame;
1508 public static void setCurrentAlignFrame(AlignFrame currentAlignFrame)
1510 Jalview.getInstance().currentAlignFrame = currentAlignFrame;
1513 public void notifyWorker(AlignCalcWorkerI worker, String status)
1515 // System.out.println("Jalview worker " + worker.getClass().getSimpleName()
1520 private static boolean isInteractive = true;
1522 public static boolean isInteractive()
1524 return isInteractive;
1527 public static void setInteractive(boolean tf)