Clover icon

Coverage Report

  1. Project Clover database Thu Dec 4 2025 16:11:35 GMT
  2. Package jalview.bin

File Jalview.java

 

Coverage histogram

../../img/srcFileCovDistChart6.png
37% of files have more coverage

Code metrics

384
810
60
3
2,451
1,854
353
0.44
13.5
20
5.88

Classes

Class Line # Actions
Jalview 128 797 349
0.535165753.5%
Jalview.FeatureFetcher 246 13 4
0.00%
Jalview.ExitCode 2199 0 0
-1.0 -
 

Contributing tests

This file is covered by 311 tests. .

Source view

1    /*
2    * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3    * Copyright (C) $$Year-Rel$$ The Jalview Authors
4    *
5    * This file is part of Jalview.
6    *
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.
11    *
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.
16    *
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.
20    */
21   
22    package jalview.bin;
23   
24    import java.awt.Color;
25    import java.awt.GraphicsEnvironment;
26    import java.io.BufferedReader;
27    import java.io.File;
28    import java.io.FileNotFoundException;
29    import java.io.FileOutputStream;
30    import java.io.IOException;
31    import java.io.InputStreamReader;
32    import java.io.OutputStream;
33    import java.io.OutputStreamWriter;
34    import java.io.PrintStream;
35    import java.io.PrintWriter;
36    import java.net.MalformedURLException;
37    import java.net.URI;
38    import java.net.URISyntaxException;
39    import java.net.URL;
40    import java.security.AllPermission;
41    import java.security.CodeSource;
42    import java.security.PermissionCollection;
43    import java.security.Permissions;
44    import java.security.Policy;
45    import java.util.ArrayList;
46    import java.util.HashMap;
47    import java.util.List;
48    import java.util.Locale;
49    import java.util.Map;
50    import java.util.Properties;
51    import java.util.Vector;
52    import java.util.stream.Collectors;
53   
54    import javax.swing.JDialog;
55    import javax.swing.JFrame;
56    import javax.swing.JInternalFrame;
57    import javax.swing.JOptionPane;
58    import javax.swing.SwingUtilities;
59    import javax.swing.UIManager;
60    import javax.swing.UIManager.LookAndFeelInfo;
61    import javax.swing.UnsupportedLookAndFeelException;
62   
63    import com.formdev.flatlaf.FlatLightLaf;
64    import com.formdev.flatlaf.themes.FlatMacLightLaf;
65    import com.formdev.flatlaf.util.SystemInfo;
66    import com.threerings.getdown.util.LaunchUtil;
67   
68    //import edu.stanford.ejalbert.launching.IBrowserLaunching;
69    import groovy.lang.Binding;
70    import groovy.util.GroovyScriptEngine;
71    import jalview.api.AlignCalcWorkerI;
72    import jalview.bin.ApplicationSingletonProvider.ApplicationSingletonI;
73    import jalview.bin.argparser.Arg;
74    import jalview.bin.argparser.Arg.Opt;
75    import jalview.bin.argparser.Arg.Type;
76    import jalview.bin.argparser.ArgParser;
77    import jalview.bin.argparser.BootstrapArgs;
78    import jalview.bin.groovy.JalviewObject;
79    import jalview.bin.groovy.JalviewObjectI;
80    import jalview.ext.so.SequenceOntology;
81    import jalview.gui.AlignFrame;
82    import jalview.gui.AlignViewport;
83    import jalview.gui.Desktop;
84    import jalview.gui.JvOptionPane;
85    import jalview.gui.Preferences;
86    import jalview.gui.PromptUserConfig;
87    import jalview.gui.QuitHandler;
88    import jalview.gui.QuitHandler.QResponse;
89    import jalview.gui.StructureViewerBase;
90    import jalview.io.AppletFormatAdapter;
91    import jalview.io.BioJsHTMLOutput;
92    import jalview.io.DataSourceType;
93    import jalview.io.FileFormat;
94    import jalview.io.FileFormatException;
95    import jalview.io.FileFormatI;
96    import jalview.io.FileFormats;
97    import jalview.io.FileLoader;
98    import jalview.io.HtmlSvgOutput;
99    import jalview.io.IdentifyFile;
100    import jalview.io.NewickFile;
101    import jalview.io.exceptions.ImageOutputException;
102    import jalview.io.gff.SequenceOntologyFactory;
103    import jalview.schemes.ColourSchemeI;
104    import jalview.schemes.ColourSchemeProperty;
105    import jalview.util.ChannelProperties;
106    import jalview.util.HttpUtils;
107    import jalview.util.LaunchUtils;
108    import jalview.util.MessageManager;
109    import jalview.util.Platform;
110    import jalview.util.UserAgent;
111    import jalview.ws.jws2.Jws2Discoverer;
112   
113    /**
114    * Main class for Jalview Application <br>
115    * <br>
116    * start with: java -classpath "$PATH_TO_LIB$/*:$PATH_TO_CLASSES$" \
117    * jalview.bin.Jalview
118    *
119    * or on Windows: java -classpath "$PATH_TO_LIB$/*;$PATH_TO_CLASSES$" \
120    * jalview.bin.Jalview jalview.bin.Jalview
121    *
122    * (ensure -classpath arg is quoted to avoid shell expansion of '*' and do not
123    * embellish '*' to e.g. '*.jar')
124    *
125    * @author $author$
126    * @version $Revision$
127    */
 
128    public class Jalview implements JalviewObjectI, ApplicationSingletonI
129    {
130    // TODO JAL-4107 - does Jalview need to do both objects explicitly
131    // for testing those nasty messages you cannot ever find.
132    // static
133    // {
134    // System.setOut(new PrintStream(new ByteArrayOutputStream())
135    // {
136    // @Override
137    // public void println(Object o)
138    // {
139    // if (o != null)
140    // {
141    // System.err.println(o);
142    // }
143    // }
144    //
145    // });
146    // }
 
147  41917 toggle public static Jalview getInstance()
148    {
149  41917 return ApplicationSingletonProvider.getInstance(Jalview.class);
150    }
151   
 
152  55 toggle private Jalview()
153    {
154  55 Platform.getURLCommandArguments();
155  55 Platform.addJ2SDirectDatabaseCall("https://www.jalview.org");
156  55 Platform.addJ2SDirectDatabaseCall("http://www.jalview.org");
157  55 Platform.addJ2SDirectDatabaseCall("http://www.compbio.dundee.ac.uk");
158  55 Platform.addJ2SDirectDatabaseCall("https://www.compbio.dundee.ac.uk");
159    }
160   
161    private boolean headless;
162   
163    private Desktop desktop;
164   
165    protected Commands cmds;
166   
167    public AlignFrame currentAlignFrame = null;
168   
169    private ArgParser argparser = null;
170   
171    private BootstrapArgs bootstrapArgs = null;
172   
173    private boolean QUIET = false;
174   
 
175  387 toggle public static boolean quiet()
176    {
177  387 return Jalview.getInstance() != null && Jalview.getInstance().QUIET;
178    }
179   
180    public String appletResourcePath;
181   
182    public String j2sAppletID;
183   
184    private boolean noCalculation, noMenuBar, noStatus;
185   
186    private boolean noAnnotation;
187   
 
188  492 toggle public boolean getStartCalculations()
189    {
190  492 return !noCalculation;
191    }
192   
 
193  439 toggle public boolean getAllowMenuBar()
194    {
195  439 return !noMenuBar;
196    }
197   
 
198  439 toggle public boolean getShowStatus()
199    {
200  439 return !noStatus;
201    }
202   
 
203  0 toggle public boolean getShowAnnotation()
204    {
205  0 return !noAnnotation;
206    }
207   
 
208  55 toggle static
209    {
210  55 if (Platform.isJS())
211    {
212  0 Platform.getURLCommandArguments();
213    }
214    else
215    /**
216    * Java only
217    *
218    * @j2sIgnore
219    */
220    {
221    // grab all the rights we can for the JVM
222  55 Policy.setPolicy(new Policy()
223    {
 
224  0 toggle @Override
225    public PermissionCollection getPermissions(CodeSource codesource)
226    {
227  0 Permissions perms = new Permissions();
228  0 perms.add(new AllPermission());
229  0 return (perms);
230    }
231   
 
232  0 toggle @Override
233    public void refresh()
234    {
235    }
236    });
237    }
238    }
239   
240    /**
241    * keep track of feature fetching tasks.
242    *
243    * @author JimP
244    *
245    */
 
246    class FeatureFetcher
247    {
248    /*
249    * TODO: generalise to track all jalview events to orchestrate batch processing
250    * events.
251    */
252   
253    private int queued = 0;
254   
255    private int running = 0;
256   
 
257  0 toggle public FeatureFetcher()
258    {
259   
260    }
261   
 
262  0 toggle public void addFetcher(final AlignFrame af,
263    final Vector<String> dasSources)
264    {
265  0 final long id = System.currentTimeMillis();
266  0 queued++;
267  0 final FeatureFetcher us = this;
268  0 new Thread(new Runnable()
269    {
270   
 
271  0 toggle @Override
272    public void run()
273    {
274  0 synchronized (us)
275    {
276  0 queued--;
277  0 running++;
278    }
279   
280  0 af.setProgressBar(MessageManager
281    .getString("status.das_features_being_retrived"), id);
282  0 af.featureSettings_actionPerformed(null);
283  0 af.setProgressBar(null, id);
284  0 synchronized (us)
285    {
286  0 running--;
287    }
288    }
289    }).start();
290    }
291   
 
292  0 toggle public synchronized boolean allFinished()
293    {
294  0 return queued == 0 && running == 0;
295    }
296   
297    }
298   
299    private final static boolean doPlatformLogging = false;
300   
301    /**
302    * main class for Jalview application
303    *
304    * @param args
305    * open <em>filename</em>
306    */
 
307  87 toggle public static void main(String[] args)
308    {
309  87 if (doPlatformLogging)
310    {
311  0 Platform.startJavaLogging();
312    }
313   
314  87 getInstance().doMain(args);
315   
316    }
317   
318    /**
319    * @param args
320    */
 
321  138 toggle void doMain(String[] args)
322    {
323  138 boolean isJS = Platform.isJS();
324  138 if (!isJS)
325    {
326  138 System.setSecurityManager(null);
327    }
328   
329    /*
330    * @j2sNative J2S.db._DirectDatabaseCalls["compbio.dundee.ac.uk"]=null;
331    * @j2sNative J2S.db._DirectDatabaseCalls["jalview.org"]=null;
332    *
333    */
334  138 if (args == null || args.length == 0 || (args.length == 1
335    && (args[0] == null || args[0].length() == 0)))
336    {
337  9 args = new String[] {};
338    }
339   
340    // get args needed before proper ArgParser
341  138 bootstrapArgs = BootstrapArgs.getBootstrapArgs(args);
342   
343  138 boolean usingLogfile = false;
344  138 if (!Platform.isJS())
345    {
346    // required to ensure log4j doesn't think it's running in a servlet
347  138 System.setProperty("log4j2.isWebapp", "false");
348   
349    // are we using a logfile?
350  138 String logfilename = System.getProperty("installer.logfile");
351  138 boolean append = Boolean
352    .parseBoolean(System.getProperty("installer.logfile_append"));
353   
354  138 usingLogfile = Console.setLogFile(logfilename, append);
355   
356    // are we being --quiet ? (doesn't matter if using a logfile)
357  138 if (!usingLogfile && bootstrapArgs.contains(Arg.QUIET))
358    {
359  0 QUIET = true;
360  0 OutputStream devNull = new OutputStream()
361    {
 
362  0 toggle @Override
363    public void write(int b)
364    {
365    // DO NOTHING
366    }
367    };
368  0 System.setOut(new PrintStream(devNull));
369    // redirecting stderr not working
370  0 if (bootstrapArgs.getList(Arg.QUIET).size() > 1)
371    {
372  0 System.setErr(new PrintStream(devNull));
373    }
374    }
375   
376  138 if (bootstrapArgs.contains(Arg.HELP)
377    || bootstrapArgs.contains(Arg.VERSION))
378    {
379  0 QUIET = true;
380    }
381    }
382   
383    // set individual session preferences
384  138 if (bootstrapArgs.contains(Arg.P))
385    {
386  0 for (String kev : bootstrapArgs.getValueList(Arg.P))
387    {
388  0 if (kev == null)
389    {
390  0 continue;
391    }
392  0 int equalsIndex = kev.indexOf(ArgParser.EQUALS);
393  0 if (equalsIndex > -1)
394    {
395  0 String key = kev.substring(0, equalsIndex);
396  0 String val = kev.substring(equalsIndex + 1);
397  0 Cache.setSessionProperty(key, val);
398    }
399    }
400    }
401   
402    // Move any new getdown-launcher-new.jar into place over old
403    // getdown-launcher.jar
404  138 final String appdirString = System
405    .getProperty("launcher.appdir") != null
406    ? System.getProperty("launcher.appdir")
407    :
408    // maybe an old install4j launch
409    System.getProperty("getdownappdir");
410  138 if (appdirString != null && appdirString.length() > 0)
411    {
412  0 Console.errPrintln("launcher.appdir property: " + appdirString);
413  0 new Thread()
414    {
415   
 
416  0 toggle @Override
417    public void run()
418    {
419  0 GetdownLauncherUpdate.main(new String[] { appdirString });
420    }
421    }.start();
422    }
423    else
424    {
425  138 Console.errPrintln("launcher.appdir property not found");
426    }
427   
428  138 if ((usingLogfile || !quiet()) || !bootstrapArgs.outputToStdout()
429    || bootstrapArgs.contains(Arg.VERSION))
430    {
431  138 if (usingLogfile)
432    {
433  0 Console.outPrintln("-------");
434    }
435  138 Console.outPrint(Cache.getVersionDetailsForConsole());
436  138 if (usingLogfile)
437    {
438  0 Console.outPrintln("-------");
439    }
440    }
441   
442  138 if (Platform.isLinux() && LaunchUtils.getJavaVersion() < 11)
443    {
444  0 System.setProperty("flatlaf.uiScale", "1");
445    }
446   
447    // get bootstrap properties (mainly for the logger level)
448  138 Properties bootstrapProperties = Cache
449    .bootstrapProperties(bootstrapArgs.getValue(Arg.PROPS));
450   
451    // report Jalview version
452  138 Cache.getInstance().loadBuildProperties(
453    !quiet() || bootstrapArgs.contains(Arg.VERSION));
454   
455    // stop now if only after --version
456  138 if (bootstrapArgs.contains(Arg.VERSION))
457    {
458  0 Jalview.exit(null, ExitCode.OK);
459    }
460   
461    // old ArgsParser
462  138 ArgsParser aparser = new ArgsParser(args);
463   
464    // old
465  138 boolean headless = false;
466    // new
467  138 boolean headlessArg = false;
468   
469  138 try
470    {
471  138 String logLevel = null;
472  138 if (bootstrapArgs.contains(Arg.TRACE))
473    {
474  0 logLevel = "TRACE";
475    }
476  138 else if (bootstrapArgs.contains(Arg.DEBUG))
477    {
478  23 logLevel = bootstrapArgs.getBoolean(Arg.DEBUG) ? "DEBUG" : "INFO";
479    }
480  138 if (logLevel == null && !(bootstrapProperties == null))
481    {
482  115 logLevel = bootstrapProperties.getProperty(Cache.JALVIEWLOGLEVEL);
483    }
484  138 Console.initLogger(logLevel);
485    } catch (NoClassDefFoundError error)
486    {
487  0 error.printStackTrace();
488  0 String message = "\nEssential logging libraries not found."
489    + "\nUse: java -classpath \"$PATH_TO_LIB$/*:$PATH_TO_CLASSES$\" jalview.bin.Jalview";
490  0 Jalview.exit(message, ExitCode.OK);
491    }
492   
493  138 if (!Platform.isJS())
494    {
495    // register SIGTERM listener
496  138 Runtime.getRuntime().addShutdownHook(new Thread()
497    {
 
498  85 toggle @Override
499    public void run()
500    {
501  85 Console.debug("Running shutdown hook");
502  85 QuitHandler.startForceQuit();
503  83 boolean closeExternal = Cache
504    .getDefault("DEFAULT_CLOSE_EXTERNAL_VIEWERS", false)
505    || Cache.getDefault("ALWAYS_CLOSE_EXTERNAL_VIEWERS",
506    false);
507  83 StructureViewerBase.setQuitClose(closeExternal);
508  79 if (desktop != null)
509    {
510  47 for (JInternalFrame frame : Desktop.getInstance()
511    .getAllFrames())
512    {
513  39 if (frame instanceof StructureViewerBase)
514    {
515  1 ((StructureViewerBase) frame).closeViewer(closeExternal);
516    }
517    }
518    }
519   
520  78 if (QuitHandler.gotQuitResponse() == QResponse.CANCEL_QUIT)
521    {
522    // Got to here by a SIGTERM signal.
523    // Note we will not actually cancel the quit from here -- it's too
524    // late -- but we can wait for saving files and close external
525    // viewers
526    // if configured.
527    // Close viewers/Leave viewers open
528  0 Console.debug("Checking for saving files");
529  0 QuitHandler.getQuitResponse(false);
530    }
531    else
532    {
533  78 Console.debug("Nothing more to do");
534    }
535  78 Console.debug("Exiting, bye!");
536    // shutdownHook cannot be cancelled, JVM will now halt
537    }
538    });
539    }
540   
541  138 String usrPropsFile = bootstrapArgs.contains(Arg.PROPS)
542    ? bootstrapArgs.getValue(Arg.PROPS)
543    : aparser.getValue("props");
544    // if usrPropsFile == null, loadProperties will use the Channel
545    // preferences.file
546  138 Cache.loadProperties(usrPropsFile);
547  138 if (usrPropsFile != null)
548    {
549  48 Console.outPrintln(
550    "CMD [-props " + usrPropsFile + "] executed successfully!");
551  48 testoutput(bootstrapArgs, Arg.PROPS,
552    "test/jalview/bin/testProps.jvprops", usrPropsFile);
553    }
554   
555    // --argfile=... -- OVERRIDES ALL NON-BOOTSTRAP ARGS
556  138 if (bootstrapArgs.contains(Arg.ARGFILE))
557    {
558  8 argparser = ArgParser.parseArgFiles(
559    bootstrapArgs.getValueList(Arg.ARGFILE),
560    bootstrapArgs.getBoolean(Arg.INITSUBSTITUTIONS),
561    bootstrapArgs);
562    }
563    else
564    {
565  130 argparser = new ArgParser(args,
566    bootstrapArgs.getBoolean(Arg.INITSUBSTITUTIONS),
567    bootstrapArgs);
568    }
569   
570  137 boolean allowServices = true;
571   
572  137 if (isJS)
573    {
574  0 j2sAppletID = Platform.getAppID(null);
575  0 Preferences.setAppletDefaults();
576  0 Cache.loadProperties(usrPropsFile); // again, because we
577    // might be changing defaults here?
578  0 appletResourcePath = (String) aparser.getAppletValue("resourcepath",
579    null, true);
580    }
581    else
582    /**
583    * Java only
584    *
585    * @j2sIgnore
586    */
587    {
588  137 if (bootstrapArgs.contains(Arg.HELP))
589    {
590  0 List<Map.Entry<Type, String>> helpArgs = bootstrapArgs
591    .getList(Arg.HELP);
592  0 Console.outPrintln(Arg.usage(helpArgs.stream().map(e -> e.getKey())
593    .collect(Collectors.toList())));
594  0 Jalview.exit(null, ExitCode.OK);
595    }
596  137 if (aparser.contains("help") || aparser.contains("h"))
597    {
598    /*
599    * Now using new usage statement.
600    showUsage();
601    */
602  0 Console.outPrintln(Arg.usage());
603  0 Jalview.exit(null, ExitCode.OK);
604    }
605   
606    // new CLI
607  137 headlessArg = bootstrapArgs.isHeadless();
608  137 if (headlessArg)
609    {
610  27 System.setProperty("java.awt.headless", "true");
611    }
612    // old CLI
613    // BH note: Only -nodisplay is official; others are deprecated?
614  137 if (aparser.contains("nodisplay") || aparser.contains("nogui")
615    || aparser.contains("headless")
616    || GraphicsEnvironment.isHeadless())
617    {
618  39 if (!isJS)
619    {
620    // BH Definitely not a good idea in JavaScript;
621    // probably should not be here for Java, either.
622  39 System.setProperty("java.awt.headless", "true");
623    }
624  39 headless = true;
625    }
626    // anything else!
627   
628    // allow https handshakes to download intermediate certs if necessary
629  137 System.setProperty("com.sun.security.enableAIAcaIssuers", "true");
630  137 String jabawsUrl = bootstrapArgs.getValue(Arg.JABAWS);
631  137 if (jabawsUrl == null)
632  136 jabawsUrl = aparser.getValue(ArgsParser.JABAWS);
633  137 allowServices = !("none".equals(jabawsUrl));
634  137 if (allowServices && jabawsUrl != null)
635    {
636  2 try
637    {
638  2 Jws2Discoverer.getInstance().setPreferredUrl(jabawsUrl);
639  2 Console.outPrintln(
640    "CMD [-jabaws " + jabawsUrl + "] executed successfully!");
641  2 testoutput(bootstrapArgs, Arg.JABAWS,
642    "http://www.compbio.dundee.ac.uk/jabaws", jabawsUrl);
643    } catch (MalformedURLException e)
644    {
645  0 jalview.bin.Console.errPrintln(
646    "Invalid jabaws parameter: " + jabawsUrl + " ignored");
647    }
648    }
649    }
650   
651  137 List<String> setprops = new ArrayList<>();
652  137 if (bootstrapArgs.contains(Arg.SETPROP))
653    {
654  0 setprops = bootstrapArgs.getValueList(Arg.SETPROP);
655    }
656    else
657    {
658  137 String sp = aparser.getValue("setprop");
659  137 while (sp != null)
660    {
661  0 setprops.add(sp);
662  0 sp = aparser.getValue("setprop");
663    }
664    }
665  137 for (String setprop : setprops)
666    {
667  0 int p = setprop.indexOf('=');
668  0 if (p == -1)
669    {
670  0 jalview.bin.Console.errPrintln(
671    "Ignoring invalid setprop argument : " + setprop);
672    }
673    else
674    {
675  0 jalview.bin.Console
676    .errPrintln("Executing setprop argument: " + setprop);
677  0 if (isJS)
678    {
679  0 Cache.setProperty(setprop.substring(0, p),
680    setprop.substring(p + 1));
681    }
682    }
683    }
684  137 if (System.getProperty("java.awt.headless") != null
685    && System.getProperty("java.awt.headless").equals("true"))
686    {
687  44 headless = true;
688    }
689  137 System.setProperty("http.agent", UserAgent.getUserAgent());
690   
691    // Initialise the logger
692  137 try
693    {
694  137 Console.initLogger();
695    } catch (NoClassDefFoundError error)
696    {
697  0 error.printStackTrace();
698  0 String message = "\nEssential logging libraries not found."
699    + "\nUse: java -classpath \"$PATH_TO_LIB$/*:$PATH_TO_CLASSES$\" jalview.bin.Jalview";
700  0 Jalview.exit(message, ExitCode.NO_LOGGING);
701    }
702  137 desktop = null;
703   
704  137 if (!(headless || headlessArg))
705    {
706  93 setLookAndFeel();
707    }
708   
709    /*
710    * configure 'full' SO model if preferences say to, else use the default (full SO)
711    * - as JS currently doesn't have OBO parsing, it must use 'Lite' version
712    */
713  137 boolean soDefault = !isJS;
714  137 if (Cache.getDefault("USE_FULL_SO", soDefault))
715    {
716  137 SequenceOntologyFactory.setSequenceOntology(new SequenceOntology());
717    }
718   
719  137 if (!(headless || headlessArg))
720    {
721  93 Desktop.nosplash = "false".equals(bootstrapArgs.getValue(Arg.SPLASH))
722    || aparser.contains("nosplash")
723    || Cache.getDefault("SPLASH", "true").equals("false");
724  93 desktop = Desktop.getInstance();
725  93 desktop.setInBatchMode(true); // indicate we are starting up
726   
727  93 mixedCliWarning();
728   
729  93 try
730    {
731  93 JalviewTaskbar.setTaskbar(this);
732    } catch (Exception e)
733    {
734  0 Console.info("Cannot set Taskbar");
735  0 Console.error(e.getMessage());
736    // e.printStackTrace();
737    } catch (Throwable t)
738    {
739  0 Console.info("Cannot set Taskbar");
740  0 Console.error(t.getMessage());
741    // t.printStackTrace();
742    }
743   
744    // set Proxy settings before all the internet calls
745  93 Cache.setProxyPropertiesFromPreferences();
746   
747  93 desktop.setVisible(true);
748   
749  93 if (isJS)
750    {
751  0 Cache.setProperty("SHOW_JWS2_SERVICES", "false");
752    }
753  93 if (allowServices && !aparser.contains("nowebservicediscovery"))
754    {
755  93 desktop.startServiceDiscovery();
756    }
757   
758  93 if (!isJS)
759    /**
760    * Java only
761    *
762    * @j2sIgnore
763    */
764    {
765   
766  93 String appName = ChannelProperties.getProperty("app_name");
767   
768    /**
769    * Check to see that the JVM version being run is suitable for the Java
770    * version this Jalview was compiled for. Popup a warning if not.
771    */
772  93 if (!LaunchUtils.checkJavaVersion())
773    {
774  0 Console.warn("The Java version being used (Java "
775    + LaunchUtils.getJavaVersion()
776    + ") may lead to problems. This installation of "
777    + appName + " should be used with Java "
778    + LaunchUtils.getJavaCompileVersion() + ".");
779   
780  0 if (!LaunchUtils
781    .getBooleanUserPreference("IGNORE_JVM_WARNING_POPUP"))
782    {
783  0 Object[] options = {
784    MessageManager.getString("label.continue") };
785  0 JOptionPane.showOptionDialog(null,
786    MessageManager.formatMessage(
787    "warning.wrong_jvm_version_message",
788    LaunchUtils.getJavaVersion(),
789    LaunchUtils.getJavaCompileVersion()),
790    MessageManager
791    .getString("warning.wrong_jvm_version_title"),
792    JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE,
793    null, options, options[0]);
794    }
795    }
796   
797    /**
798    * Check to see if we've been launched from the installer volume
799    * (macOS).
800    */
801  93 String installerappdirString = System
802    .getProperty("installer.appdir");
803  93 if (Platform.isMac() && installerappdirString != null
804    && installerappdirString.startsWith("/Volumes/"))
805    {
806  0 Console.warn("You appear to be running " + appName
807    + " from the Installer volume. Please drag and drop the "
808    + appName + " icon into the Applications folder.");
809   
810  0 Object[] options = { MessageManager.getString("action.quit") };
811  0 JOptionPane.showOptionDialog(null, MessageManager.formatMessage(
812    "warning.running_from_installer_volume_message", appName),
813    MessageManager.getString(
814    "warning.running_from_installer_volume_title"),
815    JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE,
816    null, options, options[0]);
817  0 quit();
818    }
819   
820  93 boolean webservicediscovery = bootstrapArgs
821    .getBoolean(Arg.WEBSERVICEDISCOVERY);
822  93 if (aparser.contains("nowebservicediscovery"))
823  0 webservicediscovery = false;
824  93 if (webservicediscovery)
825    {
826  73 desktop.startServiceDiscovery();
827    }
828    else
829    {
830  20 testoutput(argparser, Arg.WEBSERVICEDISCOVERY);
831    }
832   
833  93 boolean usagestats = !bootstrapArgs.getBoolean(Arg.NOUSAGESTATS);
834  93 if (aparser.contains("nousagestats"))
835  1 usagestats = false;
836  93 if (usagestats)
837    {
838  87 startUsageStats(desktop);
839  87 testoutput(argparser, Arg.NOUSAGESTATS);
840    }
841    else
842    {
843  6 Console.outPrintln("CMD [-nousagestats] executed successfully!");
844  6 testoutput(argparser, Arg.NOUSAGESTATS);
845    }
846   
847  93 boolean questionnaire = bootstrapArgs.getBoolean(Arg.QUESTIONNAIRE);
848  93 if (aparser.contains("noquestionnaire"))
849  1 questionnaire = false;
850  93 if (questionnaire)
851    {
852  85 String url = aparser.getValue("questionnaire");
853  85 if (url != null)
854    {
855    // Start the desktop questionnaire prompter with the specified
856    // questionnaire
857  0 Console.debug("Starting questionnaire url at " + url);
858  0 desktop.checkForQuestionnaire(url);
859  0 Console.outPrintln("CMD questionnaire[-" + url
860    + "] executed successfully!");
861    }
862    else
863    {
864  85 if (Cache.getProperty("NOQUESTIONNAIRES") == null)
865    {
866    // Start the desktop questionnaire prompter with the specified
867    // questionnaire
868    // String defurl =
869    // "http://anaplog.compbio.dundee.ac.uk/cgi-bin/questionnaire.pl";
870    // //
871  39 String defurl = "https://www.jalview.org/cgi-bin/questionnaire.pl";
872  39 Console.debug(
873    "Starting questionnaire with default url: " + defurl);
874  39 desktop.checkForQuestionnaire(defurl);
875    }
876    }
877    }
878    else
879    {
880  8 Console.outPrintln(
881    "CMD [-noquestionnaire] executed successfully!");
882  8 testoutput(argparser, Arg.QUESTIONNAIRE);
883    }
884   
885  93 if ((!aparser.contains("nonews")
886    && Cache.getProperty("NONEWS") == null
887    && !"false".equals(bootstrapArgs.getValue(Arg.NEWS)))
888    || "true".equals(bootstrapArgs.getValue(Arg.NEWS)))
889    {
890  42 desktop.checkForNews();
891    }
892   
893  93 if (!aparser.contains("nohtmltemplates")
894    && Cache.getProperty("NOHTMLTEMPLATES") == null)
895    {
896  93 BioJsHTMLOutput.updateBioJS();
897    }
898    }
899    }
900    else
901    {
902   
903  44 if (getArgParser().isMixedStyle())
904    {
905  0 String warning = MessageManager.formatMessage(
906    "warning.using_mixed_command_line_arguments",
907    getArgParser().getMixedExamples());
908  0 Console.warn(warning);
909  0 Jalview.exit(
910    "Exiting due to mixed old and new command line arguments",
911    ExitCode.INVALID_ARGUMENT);
912    }
913  44 if (getArgParser().isOldStyle())
914    {
915  17 String warning = MessageManager
916    .getString("warning.using_old_command_line_arguments")
917    .replace("\n", " ")
918    + "https://www.jalview.org/help/html/features/commandline.html";
919  17 Console.warn(warning);
920    }
921   
922    }
923   
924    // Run Commands from cli
925  137 cmds = new Commands(desktop, argparser, headlessArg);
926  137 cmds.processArgs();
927  132 boolean commandsSuccess = cmds.argsWereParsed();
928   
929  132 if (commandsSuccess)
930    {
931  79 if (headlessArg)
932    {
933  27 if (argparser.getBoolean(Arg.NOQUIT))
934    {
935  1 Console.warn(
936    "Completed " + Arg.HEADLESS.getName() + " commands, but "
937    + Arg.NOQUIT + " is set so not quitting!");
938    }
939    else
940    {
941  26 Jalview.exit("Successfully completed commands in headless mode",
942    ExitCode.OK);
943    }
944    }
945  53 Console.info("Successfully completed commands");
946    }
947    else
948    {
949  53 if (headlessArg)
950    {
951  0 Jalview.exit("Error when running Commands in headless mode",
952    ExitCode.ERROR_RUNNING_COMMANDS);
953    }
954  53 Console.warn("Error when running commands");
955    }
956   
957    // Check if JVM and compile version might cause problems and log if it
958    // might.
959  106 if (headless && !Platform.isJS() && !LaunchUtils.checkJavaVersion())
960    {
961  0 Console.warn("The Java version being used (Java "
962    + LaunchUtils.getJavaVersion()
963    + ") may lead to problems. This installation of Jalview should be used with Java "
964    + LaunchUtils.getJavaCompileVersion() + ".");
965    }
966   
967    // TODO JAL-4107 - integrate old-style 2.12 and new style 2.11 args handling
968    // !
969  106 parseArguments(aparser, true, commandsSuccess);
970   
971  87 cliWarning();
972    }
973   
974    /**
975    * Parse all command-line String[] arguments as well as all JavaScript-derived
976    * parameters from Info.
977    *
978    * We allow for this method to be run from JavaScript. Basically allowing
979    * simple scripting.
980    *
981    * @param aparser
982    * @param isStartup
983    */
 
984  0 toggle public void parseArguments(ArgsParser aparser, boolean isStartup)
985    {
986    // TODO: JAL-4107 - @bsoares - need to reconcile JS calling and CLI calling
987    // of --args
988   
989  0 parseArguments(aparser, isStartup, true); // allow call from JS which does
990    // not result in fileloading ops
991    }
992   
 
993  106 toggle public void parseArguments(ArgsParser aparser, boolean isStartup,
994    boolean commandsSuccess)
995    {
996  106 String groovyscript = null; // script to execute after all loading is
997  106 boolean isJS = Platform.isJS();
998  106 if (!isJS)
999    /** @j2sIgnore */
1000    {
1001    // Move any new getdown-launcher-new.jar into place over old
1002    // getdown-launcher.jar
1003  106 String appdirString = System.getProperty("getdownappdir");
1004  106 if (appdirString != null && appdirString.length() > 0)
1005    {
1006  0 final File appdir = new File(appdirString);
1007  0 new Thread()
1008    {
 
1009  0 toggle @Override
1010    public void run()
1011    {
1012  0 LaunchUtil.upgradeGetdown(
1013    new File(appdir, "getdown-launcher-old.jar"),
1014    new File(appdir, "getdown-launcher.jar"),
1015    new File(appdir, "getdown-launcher-new.jar"));
1016    }
1017    }.start();
1018    }
1019    }
1020   
1021  106 String file = null, data = null;
1022   
1023  106 FileFormatI format = null;
1024   
1025  106 DataSourceType protocol = null;
1026   
1027  106 FileLoader fileLoader = new FileLoader(!headless);
1028   
1029  106 groovyscript = aparser.getValue("groovy", true);
1030  106 file = aparser.getValue("open", true);
1031   
1032  106 if (!isJS && file == null && desktop == null && !commandsSuccess)
1033    {
1034  0 Jalview.exit("No files to open!", ExitCode.NO_FILES);
1035    }
1036  106 setDisplayParameters(aparser);
1037   
1038    // time to open a file.
1039  106 long progress = -1;
1040    // Finally, deal with the remaining input data.
1041  106 AlignFrame af = null;
1042   
1043  106 JalviewJSApp jsApp = (isJS ? new JalviewJSApp(this, aparser) : null);
1044   
1045  106 if (file == null)
1046    {
1047  88 if (isJS)
1048    {
1049    // JalviewJS allows sequence1 sequence2 ....
1050   
1051    }
1052    }
1053   
1054  106 if (file != null)
1055    {
1056   
1057  18 if (!(headless || isHeadlessMode()))
1058    {
1059  1 desktop.setProgressBar(
1060    MessageManager
1061    .getString("status.processing_commandline_args"),
1062    progress = System.currentTimeMillis());
1063    }
1064   
1065  18 Console.outPrintln("CMD [-open " + file + "] executed successfully!");
1066   
1067  18 if (!Platform.isJS())
1068    /**
1069    * ignore in JavaScript -- can't just file existence - could load it?
1070    *
1071    * @j2sIgnore
1072    */
1073    {
1074  18 if (!HttpUtils.startsWithHttpOrHttps(file))
1075    {
1076  18 if (!(new File(file)).exists())
1077    {
1078  0 if (headless)
1079    {
1080  0 Jalview.exit(
1081    "Can't find file '" + file + "' in headless mode",
1082    ExitCode.FILE_NOT_FOUND);
1083    }
1084  0 Console.warn("Can't find file'" + file + "'");
1085    }
1086    }
1087    }
1088   
1089    // JS Only argument to provide a format parameter to specify what format
1090    // to use
1091  18 String fileFormat = (isJS
1092    ? (String) aparser.getAppletValue("format", null, true)
1093    : null);
1094   
1095  18 protocol = AppletFormatAdapter.checkProtocol(file);
1096   
1097  18 try
1098    {
1099  18 format = (fileFormat != null
1100    ? FileFormats.getInstance().forName(fileFormat)
1101    : null);
1102  18 if (format == null)
1103    {
1104  18 format = new IdentifyFile().identify(file, protocol);
1105    }
1106    } catch (FileNotFoundException e)
1107    {
1108  0 Console.error("File at '" + file + "' not found", e);
1109    } catch (FileFormatException e)
1110    {
1111  0 Console.error("File '" + file + "' format not recognised", e);
1112    }
1113   
1114  18 af = new FileLoader(!headless).LoadFileWaitTillLoaded(file, protocol,
1115    format);
1116  18 if (af == null)
1117    {
1118  0 Console.outPrintln("jalview error - AlignFrame was not created");
1119    }
1120    else
1121    {
1122   
1123    // JalviewLite interface for JavaScript allows second file open
1124  18 String file2 = aparser.getValue(ArgsParser.OPEN2, true);
1125  18 if (file2 != null)
1126    {
1127  0 protocol = AppletFormatAdapter.checkProtocol(file2);
1128  0 try
1129    {
1130  0 format = new IdentifyFile().identify(file2, protocol);
1131    } catch (FileNotFoundException e)
1132    {
1133  0 Console.error("File at '" + file2 + "' not found", e);
1134    } catch (FileFormatException e)
1135    {
1136  0 Console.error("File '" + file2 + "' format not recognised", e);
1137    }
1138  0 AlignFrame af2 = new FileLoader(!headless)
1139    .LoadFileWaitTillLoaded(file2, protocol, format);
1140  0 if (af2 == null)
1141    {
1142  0 Console.outPrintln("error");
1143    }
1144    else
1145    {
1146  0 AlignViewport.openLinkedAlignmentAs(af,
1147    af.getViewport().getAlignment(),
1148    af2.getViewport().getAlignment(), "",
1149    AlignViewport.SPLIT_FRAME);
1150  0 Console.outPrintln(
1151    "CMD [-open2 " + file2 + "] executed successfully!");
1152    }
1153    }
1154    // af is loaded - so set it as current frame
1155  18 setCurrentAlignFrame(af);
1156   
1157  18 setFrameDependentProperties(aparser, af);
1158   
1159  18 if (isJS)
1160    {
1161  0 jsApp.initFromParams(af);
1162    }
1163    else
1164    /**
1165    * Java only
1166    *
1167    * @j2sIgnore
1168    */
1169    {
1170  18 if (groovyscript != null)
1171    {
1172    // Execute the groovy script after we've done all the rendering
1173    // stuff
1174    // and before any images or figures are generated.
1175  0 Console.outPrintln("Executing script " + groovyscript);
1176  0 executeGroovyScript(groovyscript, af);
1177  0 Console.outPrintln("CMD groovy[" + groovyscript
1178    + "] executed successfully!");
1179  0 groovyscript = null;
1180    }
1181    }
1182  18 if (!isJS || !isStartup)
1183    {
1184  18 createOutputFiles(aparser, format);
1185    }
1186    }
1187    }
1188    // extract groovy arguments before anything else.
1189    // Once all other stuff is done, execute any groovy scripts (in order)
1190  105 if (!isJS && (headless|| isHeadlessMode()))
1191    {
1192    // TODO JAL-4107 - why doesn't Jalview.exit() do this ?
1193  18 if (af!=null) {
1194  17 af.getViewport().getCalcManager().shutdown();
1195    }
1196  18 Jalview.exit("All done.", ExitCode.OK);
1197    }
1198   
1199  87 AlignFrame startUpAlframe = null;
1200    // We'll only open the default file if the desktop is visible.
1201    // And the user
1202    // ////////////////////
1203   
1204  87 if (!Platform.isJS() && !headless && file == null
1205    && Cache.getDefault("SHOW_STARTUP_FILE", true)
1206    && !cmds.commandArgsProvided()
1207    && !bootstrapArgs.getBoolean(Arg.NOSTARTUPFILE))
1208    // don't open the startup file if command line args have been processed
1209    // (&& !Commands.commandArgsProvided())
1210    /**
1211    * Java only
1212    *
1213    * @j2sIgnore
1214    */
1215    {
1216  0 file = Cache.getDefault("STARTUP_FILE",
1217    Cache.getDefault("www.jalview.org", "https://www.jalview.org")
1218    + "/examples/exampleFile_2_7.jvp");
1219  0 if (file.equals("http://www.jalview.org/examples/exampleFile_2_3.jar")
1220    || file.equals(
1221    "http://www.jalview.org/examples/exampleFile_2_7.jar"))
1222    {
1223  0 file.replace("http:", "https:");
1224    // hardwire upgrade of the startup file
1225  0 file.replace("_2_3", "_2_7");
1226  0 file.replace("2_7.jar", "2_7.jvp");
1227    // and remove the stale setting
1228  0 Cache.removeProperty("STARTUP_FILE");
1229    }
1230   
1231  0 protocol = AppletFormatAdapter.checkProtocol(file);
1232   
1233  0 if (file.endsWith(".jar"))
1234    {
1235  0 format = FileFormat.Jalview;
1236    }
1237    else
1238    {
1239  0 try
1240    {
1241  0 format = new IdentifyFile().identify(file, protocol);
1242    } catch (FileNotFoundException e)
1243    {
1244  0 Console.error("File at '" + file + "' not found", e);
1245    } catch (FileFormatException e)
1246    {
1247  0 Console.error("File '" + file + "' format not recognised", e);
1248    }
1249    }
1250   
1251  0 startUpAlframe = fileLoader.LoadFileWaitTillLoaded(file, protocol,
1252    format);
1253    // don't ask to save when quitting if only the startup file has been
1254    // opened
1255  0 Console.debug("Resetting up-to-date flag for startup file");
1256  0 startUpAlframe.getViewport().setSavedUpToDate(true);
1257    // extract groovy arguments before anything else.
1258    }
1259  87 if (!isJS && groovyscript != null)
1260    {
1261  0 if (Cache.groovyJarsPresent())
1262    {
1263    // TODO: DECIDE IF THIS SECOND PASS AT GROOVY EXECUTION IS STILL
1264    // REQUIRED !!
1265  0 Console.outPrintln("Executing script " + groovyscript);
1266  0 executeGroovyScript(groovyscript, af);
1267  0 Console.outPrintln(
1268    "CMD groovy[" + groovyscript + "] executed successfully!");
1269   
1270    }
1271    else
1272    {
1273  0 Console.errPrintln(
1274    "Sorry. Groovy Support is not available, so ignoring the provided groovy script "
1275    + groovyscript);
1276    }
1277    }
1278   
1279    // and finally, turn off batch mode indicator - if the desktop still
1280    // exists
1281  87 if (desktop != null)
1282    {
1283  87 if (progress != -1)
1284    {
1285  0 desktop.setProgressBar(null, progress);
1286    }
1287  87 desktop.setInBatchMode(false);
1288    }
1289   
1290  87 if (jsApp != null)
1291    {
1292  0 jsApp.callInitCallback();
1293    }
1294    }
1295   
1296    /**
1297    * Set general display parameters irrespective of file loading or
1298    * headlessness.
1299    *
1300    * @param aparser
1301    */
 
1302  106 toggle private void setDisplayParameters(ArgsParser aparser)
1303    {
1304  106 if (aparser.contains(ArgsParser.NOMENUBAR))
1305    {
1306  0 noMenuBar = true;
1307  0 Console.outPrintln("CMD [nomenu] executed successfully!");
1308    }
1309   
1310  106 if (aparser.contains(ArgsParser.NOSTATUS))
1311    {
1312  0 noStatus = true;
1313  0 Console.outPrintln("CMD [nostatus] executed successfully!");
1314    }
1315   
1316  106 if (aparser.contains(ArgsParser.NOANNOTATION)
1317    || aparser.contains(ArgsParser.NOANNOTATION2))
1318    {
1319  0 noAnnotation = true;
1320  0 Console.outPrintln("CMD no-annotation executed successfully!");
1321    }
1322  106 if (aparser.contains(ArgsParser.NOCALCULATION))
1323    {
1324  0 noCalculation = true;
1325  0 Console.outPrintln("CMD [nocalculation] executed successfully!");
1326    }
1327    }
1328   
 
1329  18 toggle private void setFrameDependentProperties(ArgsParser aparser,
1330    AlignFrame af)
1331    {
1332  18 String data = aparser.getValue(ArgsParser.COLOUR, true);
1333  18 if (data != null)
1334    {
1335  1 data.replaceAll("%20", " ");
1336   
1337  1 ColourSchemeI cs = ColourSchemeProperty.getColourScheme(
1338    af.getViewport(), af.getViewport().getAlignment(), data);
1339   
1340  1 if (cs != null)
1341    {
1342  1 Console.outPrintln(
1343    "CMD [-colour " + data + "] executed successfully!");
1344    }
1345  1 af.changeColour(cs);
1346    }
1347   
1348    // Must maintain ability to use the groups flag
1349  18 data = aparser.getValue(ArgsParser.GROUPS, true);
1350  18 if (data != null)
1351    {
1352  0 af.parseFeaturesFile(data, AppletFormatAdapter.checkProtocol(data));
1353    // System.out.println("Added " + data);
1354  0 Console.outPrintln(
1355    "CMD groups[-" + data + "] executed successfully!");
1356    }
1357  18 data = aparser.getValue(ArgsParser.FEATURES, true);
1358  18 if (data != null)
1359    {
1360  1 af.parseFeaturesFile(data, AppletFormatAdapter.checkProtocol(data));
1361    // System.out.println("Added " + data);
1362  1 Console.outPrintln(
1363    "CMD [-features " + data + "] executed successfully!");
1364    }
1365  18 data = aparser.getValue(ArgsParser.ANNOTATIONS, true);
1366  18 if (data != null)
1367    {
1368  1 af.loadJalviewDataFile(data, null, null, null);
1369    // System.out.println("Added " + data);
1370  1 Console.outPrintln(
1371    "CMD [-annotations " + data + "] executed successfully!");
1372    }
1373   
1374    // JavaScript feature
1375   
1376  18 if (aparser.contains(ArgsParser.SHOWOVERVIEW))
1377    {
1378  0 af.overviewMenuItem_actionPerformed(null);
1379  0 Console.outPrintln("CMD [showoverview] executed successfully!");
1380    }
1381   
1382    // set or clear the sortbytree flag.
1383  18 if (aparser.contains(ArgsParser.SORTBYTREE))
1384    {
1385  1 af.getViewport().setSortByTree(true);
1386  1 if (af.getViewport().getSortByTree())
1387    {
1388  1 Console.outPrintln("CMD [-sortbytree] executed successfully!");
1389    }
1390    }
1391   
1392  18 boolean doUpdateAnnotation = false;
1393    /**
1394    * we do this earlier in JalviewJS because of a complication with
1395    * SHOWOVERVIEW
1396    *
1397    * For now, just fixing this in JalviewJS.
1398    *
1399    *
1400    * @j2sIgnore
1401    *
1402    */
1403    {
1404  18 if (noAnnotation)
1405    {
1406  0 af.getViewport().setShowAnnotation(false);
1407  0 if (!af.getViewport().isShowAnnotation())
1408    {
1409  0 doUpdateAnnotation = true;
1410    }
1411    }
1412   
1413    }
1414   
1415  18 if (aparser.contains(ArgsParser.NOSORTBYTREE))
1416    {
1417  1 af.getViewport().setSortByTree(false);
1418  1 if (!af.getViewport().getSortByTree())
1419    {
1420  1 doUpdateAnnotation = true;
1421  1 Console.outPrintln("CMD [-nosortbytree] executed successfully!");
1422    }
1423    }
1424  18 if (doUpdateAnnotation)
1425    { // BH 2019.07.24
1426  1 af.setMenusForViewport();
1427  1 af.alignPanel.updateLayout();
1428    }
1429   
1430  18 data = aparser.getValue(ArgsParser.TREE, true);
1431  18 if (data != null)
1432    {
1433  1 try
1434    {
1435  1 NewickFile nf = new NewickFile(data,
1436    AppletFormatAdapter.checkProtocol(data));
1437  1 af.getViewport()
1438    .setCurrentTree(af.showNewickTree(nf, data).getTree());
1439  1 Console.outPrintln(
1440    "CMD [-tree " + data + "] executed successfully!");
1441    } catch (IOException ex)
1442    {
1443  0 Console.errPrintln("Couldn't add tree " + data);
1444  0 ex.printStackTrace(System.err);
1445    }
1446    }
1447    // JAL-4107 - DELETE THIS TODO ??? NO NEED TO LOAD PDB STRUCTURES ANYMORE
1448    // ??? ALL DONE IN NEW Commands ?
1449    // TODO - load PDB structure(s) to alignment JAL-629
1450    // (associate with identical sequence in alignment, or a specified
1451    // sequence)
1452    //
1453   
1454    }
1455   
1456    /**
1457    * Writes an output file for each format (if any) specified in the
1458    * command-line arguments. Supported formats are currently
1459    * <ul>
1460    * <li>png</li>
1461    * <li>svg</li>
1462    * <li>html</li>
1463    * <li>biojsmsa</li>
1464    * <li>imgMap</li>
1465    * <li>eps</li>
1466    * </ul>
1467    * A format parameter should be followed by a parameter specifying the output
1468    * file name. {@code imgMap} parameters should follow those for the
1469    * corresponding alignment image output.
1470    *
1471    * @param aparser
1472    * @param format
1473    */
 
1474  18 toggle private void createOutputFiles(ArgsParser aparser, FileFormatI format)
1475    {
1476    // logic essentially the same as 2.11.2/2.11.3 but uses a switch instead
1477  18 AlignFrame af = currentAlignFrame;
1478  18 String file = null;
1479  34 while (aparser.getSize() >= 2)
1480    {
1481  16 try
1482    {
1483  16 String outputFormat = aparser.nextValue();
1484  16 File imageFile;
1485  16 file = aparser.nextValue();
1486  16 String fname;
1487  16 switch (outputFormat.toLowerCase(Locale.ROOT))
1488    {
1489  1 case "png":
1490  1 imageFile = new File(file);
1491  1 af.createPNG(imageFile);
1492  1 Console.outPrintln(
1493    "Creating PNG image: " + imageFile.getAbsolutePath());
1494  1 continue;
1495  1 case "svg":
1496  1 imageFile = new File(file);
1497  1 af.createSVG(imageFile);
1498  1 Console.outPrintln(
1499    "Creating SVG image: " + imageFile.getAbsolutePath());
1500  1 continue;
1501  5 case "eps":
1502  5 imageFile = new File(file);
1503  5 Console.outPrintln(
1504    "Creating EPS file: " + imageFile.getAbsolutePath());
1505  5 af.createEPS(imageFile);
1506  5 continue;
1507  0 case "biojsmsa":
1508  0 fname = new File(file).getAbsolutePath();
1509  0 try
1510    {
1511  0 BioJsHTMLOutput.refreshVersionInfo(
1512    BioJsHTMLOutput.BJS_TEMPLATES_LOCAL_DIRECTORY);
1513    } catch (URISyntaxException e)
1514    {
1515  0 Console.errPrintln(Cache.getStackTraceString(e));
1516    }
1517  0 BioJsHTMLOutput bjs = new BioJsHTMLOutput(af.alignPanel);
1518  0 bjs.exportHTML(fname);
1519  0 Console.outPrintln(
1520    "Creating BioJS MSA Viwer HTML file: " + fname);
1521  0 continue;
1522  1 case "html":
1523  1 fname = new File(file).getAbsolutePath();
1524  1 HtmlSvgOutput htmlSVG = new HtmlSvgOutput(af.alignPanel);
1525  1 htmlSVG.exportHTML(fname);
1526  1 Console.outPrintln("Creating HTML image: " + fname);
1527  1 continue;
1528  0 case "imgmap":
1529  0 imageFile = new File(file);
1530  0 af.alignPanel.makePNGImageMap(imageFile, "unnamed.png");
1531  0 Console.outPrintln(
1532    "Creating image map: " + imageFile.getAbsolutePath());
1533  0 continue;
1534  8 default:
1535    // fall through - try to parse as an alignment data export format
1536  8 FileFormatI outFormat = null;
1537  8 try
1538    {
1539  8 outFormat = FileFormats.getInstance().forName(outputFormat);
1540    } catch (Exception formatP)
1541    {
1542  0 Console.errPrintln(Cache.getStackTraceString(formatP));
1543    }
1544  8 if (outFormat == null)
1545    {
1546  0 Console.outPrintln("Couldn't parse " + outputFormat
1547    + " as a valid Jalview format string.");
1548  0 continue;
1549    }
1550  8 if (!outFormat.isWritable())
1551    {
1552  0 Console.outPrintln(
1553    "This version of Jalview does not support alignment export as "
1554    + outputFormat);
1555  0 continue;
1556    }
1557    // record file as it was passed to Jalview so it is recognisable to
1558    // the CLI
1559    // caller
1560   
1561  8 fname = new File(file).getAbsolutePath();
1562    // JBPNote - yuck - really wish we did have a bean returned from this
1563    // which gave
1564    // success/fail like before !
1565  8 af.saveAlignment(fname, outFormat);
1566  8 if (af.isSaveAlignmentSuccessful())
1567    {
1568  8 Console.outPrintln("Written alignment in " + outputFormat
1569    + " format to " + file);
1570    }
1571    else
1572    {
1573  0 Console.errPrintln("Error writing file " + file + " in "
1574    + outputFormat + " format!!");
1575    }
1576    }
1577    }
1578   
1579    catch (ImageOutputException ioexc)
1580    {
1581  0 Console.outPrintln(
1582    "Unexpected error whilst exporting image to " + file);
1583  0 ioexc.printStackTrace();
1584    }
1585    }
1586    // ??? Should report - 'ignoring' extra args here...
1587  18 while (aparser.getSize() > 0)
1588    {
1589  0 Console.outPrintln("Ignoring extra argument: " + aparser.nextValue());
1590    }
1591   
1592  18 cliWarning();
1593    }
1594   
 
1595  93 toggle private static void setLookAndFeel()
1596    {
1597  93 if (!Platform.isJS())
1598    /**
1599    * Java only
1600    *
1601    * @j2sIgnore
1602    */
1603    {
1604    // property laf = "crossplatform", "system", "gtk", "metal", "nimbus",
1605    // "mac" or "flat"
1606    // If not set (or chosen laf fails), use the normal SystemLaF and if on
1607    // Mac,
1608    // try Quaqua/Vaqua.
1609  93 String lafProp = System.getProperty("laf");
1610  93 String lafSetting = Cache.getDefault("PREFERRED_LAF", null);
1611  93 String laf = "none";
1612  93 if (lafProp != null)
1613    {
1614  0 laf = lafProp;
1615    }
1616  93 else if (lafSetting != null)
1617    {
1618  0 laf = lafSetting;
1619    }
1620  93 boolean lafSet = false;
1621  93 switch (laf)
1622    {
1623  0 case "crossplatform":
1624  0 lafSet = setCrossPlatformLookAndFeel();
1625  0 if (!lafSet)
1626    {
1627  0 Console.error("Could not set requested laf=" + laf);
1628    }
1629  0 break;
1630  0 case "system":
1631  0 lafSet = setSystemLookAndFeel();
1632  0 if (!lafSet)
1633    {
1634  0 Console.error("Could not set requested laf=" + laf);
1635    }
1636  0 break;
1637  0 case "gtk":
1638  0 lafSet = setGtkLookAndFeel();
1639  0 if (!lafSet)
1640    {
1641  0 Console.error("Could not set requested laf=" + laf);
1642    }
1643  0 break;
1644  0 case "metal":
1645  0 lafSet = setMetalLookAndFeel();
1646  0 if (!lafSet)
1647    {
1648  0 Console.error("Could not set requested laf=" + laf);
1649    }
1650  0 break;
1651  0 case "nimbus":
1652  0 lafSet = setNimbusLookAndFeel();
1653  0 if (!lafSet)
1654    {
1655  0 Console.error("Could not set requested laf=" + laf);
1656    }
1657  0 break;
1658  0 case "flat":
1659  0 lafSet = setFlatLookAndFeel();
1660  0 if (!lafSet)
1661    {
1662  0 Console.error("Could not set requested laf=" + laf);
1663    }
1664  0 break;
1665  0 case "mac":
1666  0 lafSet = setMacLookAndFeel();
1667  0 if (!lafSet)
1668    {
1669  0 Console.error("Could not set requested laf=" + laf);
1670    }
1671  0 break;
1672  93 case "none":
1673  93 break;
1674  0 default:
1675  0 Console.error("Requested laf=" + laf + " not implemented");
1676    }
1677  93 if (!lafSet)
1678    {
1679    // Flatlaf default for everyone!
1680  93 lafSet = setFlatLookAndFeel();
1681  93 if (!lafSet)
1682    {
1683  0 setSystemLookAndFeel();
1684    }
1685  93 if (Platform.isLinux())
1686    {
1687  93 setLinuxLookAndFeel();
1688    }
1689  93 if (Platform.isMac())
1690    {
1691  0 setMacLookAndFeel();
1692    }
1693    }
1694    }
1695    }
1696   
 
1697  0 toggle private static boolean setCrossPlatformLookAndFeel()
1698    {
1699  0 boolean set = false;
1700  0 try
1701    {
1702  0 UIManager.setLookAndFeel(
1703    UIManager.getCrossPlatformLookAndFeelClassName());
1704  0 set = true;
1705    } catch (Exception ex)
1706    {
1707  0 Console.error("Unexpected Look and Feel Exception");
1708  0 Console.error(ex.getMessage());
1709  0 Console.debug(Cache.getStackTraceString(ex));
1710    }
1711  0 return set;
1712    }
1713   
 
1714  0 toggle private static boolean setSystemLookAndFeel()
1715    {
1716  0 boolean set = false;
1717  0 try
1718    {
1719  0 UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
1720  0 set = true;
1721    } catch (Exception ex)
1722    {
1723  0 Console.error("Unexpected Look and Feel Exception");
1724  0 Console.error(ex.getMessage());
1725  0 Console.debug(Cache.getStackTraceString(ex));
1726    }
1727  0 return set;
1728    }
1729   
 
1730  0 toggle private static boolean setSpecificLookAndFeel(String name,
1731    String className, boolean nameStartsWith)
1732    {
1733  0 boolean set = false;
1734  0 try
1735    {
1736  0 for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels())
1737    {
1738  0 if (info.getName() != null && nameStartsWith
1739    ? info.getName().toLowerCase(Locale.ROOT)
1740    .startsWith(name.toLowerCase(Locale.ROOT))
1741    : info.getName().toLowerCase(Locale.ROOT)
1742    .equals(name.toLowerCase(Locale.ROOT)))
1743    {
1744  0 className = info.getClassName();
1745  0 break;
1746    }
1747    }
1748  0 UIManager.setLookAndFeel(className);
1749  0 set = true;
1750    } catch (Exception ex)
1751    {
1752  0 Console.error("Unexpected Look and Feel Exception");
1753  0 Console.error(ex.getMessage());
1754  0 Console.debug(Cache.getStackTraceString(ex));
1755    }
1756  0 return set;
1757    }
1758   
 
1759  0 toggle private static boolean setGtkLookAndFeel()
1760    {
1761  0 return setSpecificLookAndFeel("gtk",
1762    "com.sun.java.swing.plaf.gtk.GTKLookAndFeel", true);
1763    }
1764   
 
1765  0 toggle private static boolean setMetalLookAndFeel()
1766    {
1767  0 return setSpecificLookAndFeel("metal",
1768    "javax.swing.plaf.metal.MetalLookAndFeel", false);
1769    }
1770   
 
1771  0 toggle private static boolean setNimbusLookAndFeel()
1772    {
1773  0 return setSpecificLookAndFeel("nimbus",
1774    "javax.swing.plaf.nimbus.NimbusLookAndFeel", false);
1775    }
1776   
 
1777  186 toggle private static boolean setFlatLookAndFeel()
1778    {
1779  186 boolean set = false;
1780  186 if (SystemInfo.isMacOS)
1781    {
1782  0 try
1783    {
1784  0 UIManager.setLookAndFeel(
1785    "com.formdev.flatlaf.themes.FlatMacLightLaf");
1786  0 set = true;
1787  0 Console.debug("Using FlatMacLightLaf");
1788    } catch (ClassNotFoundException | InstantiationException
1789    | IllegalAccessException | UnsupportedLookAndFeelException e)
1790    {
1791  0 Console.debug("Exception loading FlatLightLaf", e);
1792    }
1793  0 System.setProperty("apple.laf.useScreenMenuBar", "true");
1794  0 System.setProperty("apple.awt.application.name",
1795    ChannelProperties.getProperty("app_name"));
1796  0 System.setProperty("apple.awt.application.appearance", "system");
1797  0 if (SystemInfo.isMacFullWindowContentSupported
1798    && Desktop.getInstance() != null)
1799    {
1800  0 Console.debug("Setting transparent title bar");
1801  0 Desktop.getInstance().getRootPane()
1802    .putClientProperty("apple.awt.fullWindowContent", true);
1803  0 Desktop.getInstance().getRootPane()
1804    .putClientProperty("apple.awt.transparentTitleBar", true);
1805  0 Desktop.getInstance().getRootPane()
1806    .putClientProperty("apple.awt.fullscreenable", true);
1807    }
1808  0 SwingUtilities.invokeLater(() -> {
1809  0 FlatMacLightLaf.setup();
1810    });
1811  0 Console.debug("Using FlatMacLightLaf");
1812  0 set = true;
1813    }
1814  186 if (!set)
1815    {
1816  186 try
1817    {
1818  186 UIManager.setLookAndFeel("com.formdev.flatlaf.FlatLightLaf");
1819  186 set = true;
1820  186 Console.debug("Using FlatLightLaf");
1821    } catch (ClassNotFoundException | InstantiationException
1822    | IllegalAccessException | UnsupportedLookAndFeelException e)
1823    {
1824  0 Console.debug("Exception loading FlatLightLaf", e);
1825    }
1826    // Windows specific properties here
1827  186 SwingUtilities.invokeLater(() -> {
1828  186 FlatLightLaf.setup();
1829    });
1830  186 Console.debug("Using FlatLightLaf");
1831  186 set = true;
1832    }
1833  0 else if (SystemInfo.isLinux)
1834    {
1835  0 try
1836    {
1837  0 UIManager.setLookAndFeel("com.formdev.flatlaf.FlatLightLaf");
1838  0 set = true;
1839  0 Console.debug("Using FlatLightLaf");
1840    } catch (ClassNotFoundException | InstantiationException
1841    | IllegalAccessException | UnsupportedLookAndFeelException e)
1842    {
1843  0 Console.debug("Exception loading FlatLightLaf", e);
1844    }
1845    // enable custom window decorations
1846  0 JFrame.setDefaultLookAndFeelDecorated(true);
1847  0 JDialog.setDefaultLookAndFeelDecorated(true);
1848  0 SwingUtilities.invokeLater(() -> {
1849  0 FlatLightLaf.setup();
1850    });
1851  0 Console.debug("Using FlatLightLaf");
1852  0 set = true;
1853    }
1854   
1855  186 if (!set)
1856    {
1857  0 try
1858    {
1859  0 UIManager.setLookAndFeel("com.formdev.flatlaf.FlatLightLaf");
1860  0 set = true;
1861  0 Console.debug("Using FlatLightLaf");
1862    } catch (ClassNotFoundException | InstantiationException
1863    | IllegalAccessException | UnsupportedLookAndFeelException e)
1864    {
1865  0 Console.debug("Exception loading FlatLightLaf", e);
1866    }
1867    }
1868   
1869  186 if (set)
1870    {
1871  186 UIManager.put("TabbedPane.tabType", "card");
1872  186 UIManager.put("TabbedPane.showTabSeparators", true);
1873  186 UIManager.put("TabbedPane.showContentSeparator", true);
1874    // UIManager.put("TabbedPane.tabSeparatorsFullHeight", true);
1875  186 UIManager.put("TabbedPane.tabsOverlapBorder", true);
1876  186 UIManager.put("TabbedPane.hasFullBorder", true);
1877  186 UIManager.put("TabbedPane.tabLayoutPolicy", "scroll");
1878  186 UIManager.put("TabbedPane.scrollButtonsPolicy", "asNeeded");
1879  186 UIManager.put("TabbedPane.smoothScrolling", true);
1880  186 UIManager.put("TabbedPane.tabWidthMode", "compact");
1881  186 UIManager.put("TabbedPane.selectedBackground", Color.white);
1882  186 UIManager.put("TabbedPane.background", new Color(236, 236, 236));
1883  186 UIManager.put("TabbedPane.hoverColor", Color.lightGray);
1884    }
1885   
1886  186 Desktop.setLiveDragMode(Cache.getDefault("FLAT_LIVE_DRAG_MODE", true));
1887  186 return set;
1888    }
1889   
 
1890  0 toggle private static boolean setMacLookAndFeel()
1891    {
1892  0 boolean set = false;
1893  0 System.setProperty("com.apple.mrj.application.apple.menu.about.name",
1894    ChannelProperties.getProperty("app_name"));
1895  0 System.setProperty("apple.laf.useScreenMenuBar", "true");
1896    /*
1897    * broken native LAFs on (ARM?) macbooks
1898    set = setQuaquaLookAndFeel();
1899    if ((!set) || !UIManager.getLookAndFeel().getClass().toString()
1900    .toLowerCase(Locale.ROOT).contains("quaqua"))
1901    {
1902    set = setVaquaLookAndFeel();
1903    }
1904    */
1905  0 set = setFlatLookAndFeel();
1906  0 return set;
1907    }
1908   
 
1909  93 toggle private static boolean setLinuxLookAndFeel()
1910    {
1911  93 boolean set = false;
1912  93 set = setFlatLookAndFeel();
1913  93 if (!set)
1914  0 set = setMetalLookAndFeel();
1915    // avoid GtkLookAndFeel -- not good results especially on HiDPI
1916  93 if (!set)
1917  0 set = setNimbusLookAndFeel();
1918  93 return set;
1919    }
1920   
1921    /*
1922    private static void showUsage()
1923    {
1924    jalview.bin.Console.outPrintln(
1925    "Usage: jalview -open [FILE] [OUTPUT_FORMAT] [OUTPUT_FILE]\n\n"
1926    + "-nodisplay\tRun Jalview without User Interface.\n"
1927    + "-props FILE\tUse the given Jalview properties file instead of users default.\n"
1928    + "-colour COLOURSCHEME\tThe colourscheme to be applied to the alignment\n"
1929    + "-annotations FILE\tAdd precalculated annotations to the alignment.\n"
1930    + "-tree FILE\tLoad the given newick format tree file onto the alignment\n"
1931    + "-features FILE\tUse the given file to mark features on the alignment.\n"
1932    + "-fasta FILE\tCreate alignment file FILE in Fasta format.\n"
1933    + "-clustal FILE\tCreate alignment file FILE in Clustal format.\n"
1934    + "-pfam FILE\tCreate alignment file FILE in PFAM format.\n"
1935    + "-msf FILE\tCreate alignment file FILE in MSF format.\n"
1936    + "-pileup FILE\tCreate alignment file FILE in Pileup format\n"
1937    + "-pir FILE\tCreate alignment file FILE in PIR format.\n"
1938    + "-blc FILE\tCreate alignment file FILE in BLC format.\n"
1939    + "-json FILE\tCreate alignment file FILE in JSON format.\n"
1940    + "-jalview FILE\tCreate alignment file FILE in Jalview format.\n"
1941    + "-png FILE\tCreate PNG image FILE from alignment.\n"
1942    + "-svg FILE\tCreate SVG image FILE from alignment.\n"
1943    + "-html FILE\tCreate HTML file from alignment.\n"
1944    + "-biojsMSA FILE\tCreate BioJS MSA Viewer HTML file from alignment.\n"
1945    + "-imgMap FILE\tCreate HTML file FILE with image map of PNG image.\n"
1946    + "-eps FILE\tCreate EPS file FILE from alignment.\n"
1947    + "-questionnaire URL\tQueries the given URL for information about any Jalview user questionnaires.\n"
1948    + "-noquestionnaire\tTurn off questionnaire check.\n"
1949    + "-nonews\tTurn off check for Jalview news.\n"
1950    + "-nousagestats\tTurn off analytics tracking for this session.\n"
1951    + "-sortbytree OR -nosortbytree\tEnable or disable sorting of the given alignment by the given tree\n"
1952    // +
1953    // "-setprop PROPERTY=VALUE\tSet the given Jalview property,
1954    // after all other properties files have been read\n\t
1955    // (quote the 'PROPERTY=VALUE' pair to ensure spaces are
1956    // passed in correctly)"
1957    + "-jabaws URL\tSpecify URL for Jabaws services (e.g. for a local installation).\n"
1958    + "-fetchfrom nickname\tQuery nickname for features for the alignments and display them.\n"
1959    + "-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"
1960    + "-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"
1961    + "-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"
1962    + "\n~Read documentation in Application or visit https://www.jalview.org for description of Features and Annotations file~\n\n");
1963    }
1964    */
1965   
 
1966  87 toggle private static void startUsageStats(final Desktop desktop)
1967    {
1968    /**
1969    * start a User Config prompt asking if we can log usage statistics.
1970    */
1971  87 PromptUserConfig prompter = new PromptUserConfig(
1972    desktop, "USAGESTATS",
1973    MessageManager.getString("prompt.analytics_title"),
1974    MessageManager.getString("prompt.analytics"), new Runnable()
1975    {
 
1976  1 toggle @Override
1977    public void run()
1978    {
1979  1 Console.debug("Initialising analytics for usage stats.");
1980  1 Cache.initAnalytics();
1981  1 Console.debug("Tracking enabled.");
1982    }
1983    }, new Runnable()
1984    {
 
1985  0 toggle @Override
1986    public void run()
1987    {
1988  0 Console.debug("Not enabling analytics.");
1989    }
1990    }, null, true);
1991  87 desktop.addDialogThread(prompter);
1992    }
1993   
1994    /**
1995    * Locate the given string as a file and pass it to the groovy interpreter.
1996    *
1997    * @param groovyscript
1998    * the script to execute
1999    * @param jalviewContext
2000    * the Jalview Desktop object passed in to the groovy binding as the
2001    * 'Jalview' object.
2002    */
 
2003  0 toggle protected void executeGroovyScript(String groovyscript, AlignFrame af)
2004    {
2005    /**
2006    * for scripts contained in files
2007    */
2008  0 File tfile = null;
2009    /**
2010    * script's URI
2011    */
2012  0 URL sfile = null;
2013  0 if (groovyscript.trim().equals("STDIN"))
2014    {
2015    // read from stdin into a tempfile and execute it
2016  0 try
2017    {
2018  0 tfile = File.createTempFile("jalview", "groovy");
2019  0 PrintWriter outfile = new PrintWriter(
2020    new OutputStreamWriter(new FileOutputStream(tfile)));
2021  0 BufferedReader br = new BufferedReader(
2022    new InputStreamReader(System.in));
2023  0 String line = null;
2024  0 while ((line = br.readLine()) != null)
2025    {
2026  0 outfile.write(line + "\n");
2027    }
2028  0 br.close();
2029  0 outfile.flush();
2030  0 outfile.close();
2031   
2032    } catch (Exception ex)
2033    {
2034  0 jalview.bin.Console
2035    .errPrintln("Failed to read from STDIN into tempfile "
2036  0 + ((tfile == null) ? "(tempfile wasn't created)"
2037    : tfile.toString()));
2038  0 ex.printStackTrace();
2039  0 return;
2040    }
2041  0 try
2042    {
2043  0 sfile = tfile.toURI().toURL();
2044    } catch (Exception x)
2045    {
2046  0 jalview.bin.Console.errPrintln(
2047    "Unexpected Malformed URL Exception for temporary file created from STDIN: "
2048    + tfile.toURI());
2049  0 x.printStackTrace();
2050  0 return;
2051    }
2052    }
2053    else
2054    {
2055  0 try
2056    {
2057  0 sfile = new URI(groovyscript).toURL();
2058    } catch (Exception x)
2059    {
2060  0 tfile = new File(groovyscript);
2061  0 if (!tfile.exists())
2062    {
2063  0 jalview.bin.Console.errPrintln(
2064    "File '" + groovyscript + "' does not exist.");
2065  0 return;
2066    }
2067  0 if (!tfile.canRead())
2068    {
2069  0 jalview.bin.Console.errPrintln(
2070    "File '" + groovyscript + "' cannot be read.");
2071  0 return;
2072    }
2073  0 if (tfile.length() < 1)
2074    {
2075  0 jalview.bin.Console
2076    .errPrintln("File '" + groovyscript + "' is empty.");
2077  0 return;
2078    }
2079  0 try
2080    {
2081  0 sfile = tfile.getAbsoluteFile().toURI().toURL();
2082    } catch (Exception ex)
2083    {
2084  0 jalview.bin.Console.errPrintln("Failed to create a file URL for "
2085    + tfile.getAbsoluteFile());
2086  0 return;
2087    }
2088    }
2089    }
2090  0 try
2091    {
2092  0 JalviewObjectI j = new JalviewObject(this);
2093  0 Map<String, java.lang.Object> vbinding = new HashMap<>();
2094  0 vbinding.put(JalviewObjectI.jalviewObjectName, j);
2095  0 vbinding.put(JalviewObjectI.currentAlFrameName,
2096  0 af != null ? af : getCurrentAlignFrame());
2097  0 Binding gbinding = new Binding(vbinding);
2098  0 GroovyScriptEngine gse = new GroovyScriptEngine(new URL[] { sfile });
2099  0 gse.run(sfile.toString(), gbinding);
2100  0 if ("STDIN".equals(groovyscript))
2101    {
2102    // delete temp file that we made -
2103    // only if it was successfully executed
2104  0 tfile.delete();
2105    }
2106    } catch (Exception e)
2107    {
2108  0 jalview.bin.Console
2109    .errPrintln("Exception Whilst trying to execute file " + sfile
2110    + " as a groovy script.");
2111  0 e.printStackTrace(System.err);
2112    }
2113    }
2114   
 
2115  36954 toggle public static boolean isHeadlessMode()
2116    {
2117  36954 String isheadless = System.getProperty("java.awt.headless");
2118  36954 if (isheadless != null && isheadless.equalsIgnoreCase("true"))
2119    {
2120  862 return true;
2121    }
2122  36092 return false;
2123    }
2124   
 
2125  0 toggle @Override
2126    public AlignFrame[] getAlignFrames()
2127    {
2128  0 return desktop == null
2129  0 ? getCurrentAlignFrame() != null ? new AlignFrame[]
2130    { getCurrentAlignFrame() } : null
2131    : Desktop.getDesktopAlignFrames();
2132    }
2133   
2134    /**
2135    * jalview.bin.Jalview.quit() will just run the non-GUI shutdownHook and exit
2136    */
 
2137  0 toggle @Override
2138    public void quit()
2139    {
2140    // System.exit will run the shutdownHook first
2141  0 Jalview.exit("Quitting now. Bye!", ExitCode.OK);
2142    }
2143   
 
2144  0 toggle @Override
2145    public AlignFrame getCurrentAlignFrame()
2146    {
2147  0 return currentAlignFrame;
2148    }
2149   
 
2150  1165 toggle public void setCurrentAlignFrame(AlignFrame af)
2151    {
2152  1165 this.currentAlignFrame = af;
2153    }
2154   
 
2155  341 toggle public Commands getCommands()
2156    {
2157  341 return cmds;
2158    }
2159   
 
2160  45 toggle public static void exit(String message, ExitCode ec)
2161    {
2162  45 int exitcode = ec == ExitCode.OK ? 0 : ec.ordinal() + 1;
2163  45 if (Console.log == null)
2164    {
2165    // Don't start the logger just to exit!
2166  0 if (message != null)
2167    {
2168  0 if (exitcode == 0)
2169    {
2170  0 Console.outPrintln(message);
2171    }
2172    else
2173    {
2174  0 jalview.bin.Console.errPrintln(message);
2175    }
2176    }
2177    }
2178    else
2179    {
2180  45 Console.debug("Using Jalview.exit");
2181  45 if (message != null)
2182    {
2183  45 if (exitcode == 0)
2184    {
2185  45 Console.info(message);
2186    }
2187    else
2188    {
2189  0 Console.error(message);
2190    }
2191    }
2192    }
2193  45 if (exitcode > -1)
2194    {
2195  45 System.exit(exitcode);
2196    }
2197    }
2198   
 
2199    public enum ExitCode
2200    {
2201    // only add new ones to the end of the list (to preserve ordinal values)
2202    OK, FILE_NOT_FOUND, FILE_NOT_READABLE, NO_FILES, INVALID_FORMAT,
2203    INVALID_ARGUMENT, INVALID_VALUE, MIXED_CLI_ARGUMENTS,
2204    ERROR_RUNNING_COMMANDS, NO_LOGGING, GROOVY_ERROR;
2205    }
2206   
2207    /******************************
2208    *
2209    * TEST OUTPUT METHODS
2210    *
2211    * these operate only when Arg.TESTOUTPUT has been passed, and variously check
2212    * if an expected value / arg was set and report it to the test framework.
2213    *
2214    ******************************/
2215    /**
2216    * report string values parsed/processed during tests When the Bootstrap
2217    * argument Arg.TESTOUTPUT is present - reports on debug if given s1 is not
2218    * null and not equals s2, warns if given argument is not set, and calls
2219    * testoutput(true,a,s1,s2) to report processing progress.
2220    *
2221    * @param ap
2222    * - ArgParser handling parsing
2223    * @param a
2224    * - Arg currently being processed
2225    * @param s1
2226    * - expected
2227    * @param s2
2228    */
 
2229  153 toggle protected static void testoutput(ArgParser ap, Arg a, String s1,
2230    String s2)
2231    {
2232  153 BootstrapArgs bsa = ap.getBootstrapArgs();
2233  153 if (!bsa.getBoolean(Arg.TESTOUTPUT))
2234  131 return;
2235  22 if (!((s1 == null && s2 == null) || (s1 != null && s1.equals(s2))))
2236    {
2237  0 Console.debug("testoutput with unmatching values '" + s1 + "' and '"
2238    + s2 + "' for arg " + a.argString());
2239  0 return;
2240    }
2241  22 boolean isset = a.hasOption(Opt.BOOTSTRAP) ? bsa.contains(a)
2242    : ap.isSet(a);
2243  22 if (!isset)
2244    {
2245  0 Console.warn("Arg '" + a.getName() + "' not set at all");
2246  0 return;
2247    }
2248  22 testoutput(true, a, s1, s2);
2249    }
2250   
2251    /**
2252    * report values passed via bootstrap arguments
2253    *
2254    * TODO: significant code duplication with testouput(Argparser...) - move it
2255    */
2256   
 
2257  50 toggle protected static void testoutput(BootstrapArgs bsa, Arg a, String s1,
2258    String s2)
2259    {
2260  50 if (!bsa.getBoolean(Arg.TESTOUTPUT))
2261  48 return;
2262  2 if (!((s1 == null && s2 == null) || (s1 != null && s1.equals(s2))))
2263    {
2264  0 Console.debug("testoutput with unmatching values '" + s1 + "' and '"
2265    + s2 + "' for arg " + a.argString());
2266  0 return;
2267    }
2268  2 if (!a.hasOption(Opt.BOOTSTRAP))
2269    {
2270  0 Console.error("Non-bootstrap Arg '" + a.getName()
2271    + "' given to testoutput(BootstrapArgs bsa, Arg a, String s1, String s2) with only BootstrapArgs");
2272    }
2273  2 if (!bsa.contains(a))
2274    {
2275  0 Console.warn("Arg '" + a.getName() + "' not set at all");
2276  0 return;
2277    }
2278  2 testoutput(true, a, s1, s2);
2279    }
2280   
2281    /**
2282    * conditionally (on @param yes) report that expected value s1 was set during
2283    * CommandsTest tests
2284    */
 
2285  24 toggle private static void testoutput(boolean yes, Arg a, String s1, String s2)
2286    {
2287  24 if (yes && ((s1 == null && s2 == null)
2288    || (s1 != null && s1.equals(s2))))
2289    {
2290  24 Console.outPrintln("[TESTOUTPUT] arg " + a.argString() + "='" + s1
2291    + "' was set");
2292    }
2293    }
2294   
2295    /*
2296    * testoutput for boolean and unary values
2297    */
 
2298  122 toggle protected static void testoutput(ArgParser ap, Arg a)
2299    {
2300  122 if (ap == null)
2301  0 return;
2302  122 BootstrapArgs bsa = ap.getBootstrapArgs();
2303  122 if (bsa == null)
2304  2 return;
2305  120 if (!bsa.getBoolean(Arg.TESTOUTPUT))
2306  117 return;
2307  3 boolean val = a.hasOption(Opt.BOOTSTRAP) ? bsa.getBoolean(a)
2308    : ap.getBoolean(a);
2309  3 boolean isset = a.hasOption(Opt.BOOTSTRAP) ? bsa.contains(a)
2310    : ap.isSet(a);
2311  3 if (!isset)
2312    {
2313  0 Console.warn("Arg '" + a.getName() + "' not set at all");
2314  0 return;
2315    }
2316  3 testoutput(val, a);
2317    }
2318   
 
2319  0 toggle protected static void testoutput(BootstrapArgs bsa, Arg a)
2320    {
2321  0 if (!bsa.getBoolean(Arg.TESTOUTPUT))
2322  0 return;
2323  0 if (!a.hasOption(Opt.BOOTSTRAP))
2324    {
2325  0 Console.warn("Non-bootstrap Arg '" + a.getName()
2326    + "' given to testoutput(BootstrapArgs bsa, Arg a) with only BootstrapArgs");
2327   
2328    }
2329  0 if (!bsa.contains(a))
2330    {
2331  0 Console.warn("Arg '" + a.getName() + "' not set at all");
2332  0 return;
2333    }
2334  0 testoutput(bsa.getBoolean(a), a);
2335    }
2336   
 
2337  3 toggle private static void testoutput(boolean yes, Arg a)
2338    {
2339  3 String message = null;
2340  3 if (a.hasOption(Opt.BOOLEAN))
2341    {
2342  2 message = (yes ? a.argString() : a.negateArgString()) + " was set";
2343    }
2344  1 else if (a.hasOption(Opt.UNARY))
2345    {
2346  1 message = a.argString() + (yes ? " was set" : " was not set");
2347    }
2348  3 Console.outPrintln("[TESTOUTPUT] arg " + message);
2349    }
2350   
 
2351  495 toggle public ArgParser getArgParser()
2352    {
2353  495 return argparser;
2354    }
2355   
 
2356  1402 toggle public BootstrapArgs getBootstrapArgs()
2357    {
2358  1402 return bootstrapArgs;
2359    }
2360   
 
2361  56 toggle public static boolean isBatchMode()
2362    {
2363  56 return getInstance() != null && (getInstance().desktop == null
2364    || getInstance().desktop.isInBatchMode());
2365    }
2366   
2367    /**
2368    * Warning about old or mixed command line arguments
2369    */
 
2370  93 toggle private void mixedCliWarning()
2371    {
2372  93 Jalview j = Jalview.getInstance();
2373  93 boolean mixedStyle = j.getArgParser() != null
2374    && j.getArgParser().isMixedStyle();
2375  93 String title = MessageManager.getString("label.command_line_arguments");
2376  93 if (mixedStyle)
2377    {
2378  0 String warning = MessageManager.formatMessage(
2379    "warning.using_mixed_command_line_arguments",
2380    j.getArgParser().getMixedExamples());
2381  0 String quit = MessageManager.getString("action.quit");
2382   
2383  0 Desktop.getInstance().nonBlockingDialog(title, warning, null, quit,
2384    JvOptionPane.WARNING_MESSAGE, false, false, true, 30000);
2385   
2386  0 Jalview.exit(
2387    "Exiting due to mixed old and new command line arguments.",
2388    ExitCode.MIXED_CLI_ARGUMENTS);
2389    }
2390    }
2391   
 
2392  105 toggle private void cliWarning()
2393    {
2394  105 Jalview j = Jalview.getInstance();
2395  105 Commands c = j.getCommands();
2396  105 boolean oldStyle = j.getArgParser() != null
2397    && j.getArgParser().isOldStyle();
2398  105 String title = MessageManager.getString("label.command_line_arguments");
2399  105 if (oldStyle)
2400    {
2401  18 String warning = MessageManager
2402    .getString("warning.using_old_command_line_arguments");
2403  18 String url = "<a href=\"https://www.jalview.org/help/html/features/commandline.html\">https://www.jalview.org/help/html/features/commandline.html</a>";
2404  18 if (Desktop.getInstance() != null)
2405    {
2406  1 String cont = MessageManager.getString("label.continue");
2407   
2408  1 Desktop.getInstance().nonBlockingDialog(title, warning, url, cont,
2409    JvOptionPane.WARNING_MESSAGE, false, true, true, 30000);
2410    }
2411    }
2412  104 if (j.getCommands() != null && j.getCommands().getErrors().size() > 0)
2413    {
2414  0 if (Desktop.getInstance() != null)
2415    {
2416  0 String message = MessageManager
2417    .getString("warning.the_following_errors");
2418  0 String ok = MessageManager.getString("action.ok");
2419  0 int shortest = 60;
2420  0 List<String> errors = j.getCommands().getErrors();
2421  0 for (int i = 0; i < errors.size(); i++)
2422    {
2423  0 shortest = Math.min(shortest, errors.get(i).length());
2424    }
2425  0 Desktop.getInstance().nonBlockingDialog(
2426    Math.max(message.length(), Math.min(60, shortest)),
2427    Math.min(errors.size(), 20), title, message,
2428    j.getCommands().errorsToString(), ok,
2429    JvOptionPane.WARNING_MESSAGE, true, false, true, -1);
2430    }
2431    }
2432    }
2433   
 
2434  0 toggle public void notifyWorker(AlignCalcWorkerI worker, String status)
2435    {
2436    // System.out.println("Jalview worker " + worker.getClass().getSimpleName()
2437    // + " " + status);
2438    }
2439   
2440    private static boolean isInteractive = true;
2441   
 
2442  11 toggle public static boolean isInteractive()
2443    {
2444  11 return isInteractive;
2445    }
2446   
 
2447  0 toggle public static void setInteractive(boolean tf)
2448    {
2449  0 isInteractive = tf;
2450    }
2451    }