Clover icon

Coverage Report

  1. Project Clover database Tue Mar 10 2026 14:58:44 GMT
  2. Package jalview.bin

File Jalview.java

 

Coverage histogram

../../img/srcFileCovDistChart0.png
0% of files have more coverage

Code metrics

384
811
61
3
2,456
1,858
354
0.44
13.3
20.33
5.8

Classes

Class Line # Actions
Jalview 128 798 350
0.00%
Jalview.FeatureFetcher 251 13 4
0.00%
Jalview.ExitCode 2204 0 0
-1.0 -
 

Contributing tests

No tests hitting this source file were found.

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