Clover icon

Coverage Report

  1. Project Clover database Thu Dec 11 2025 10:57:44 GMT
  2. Package jalview.bin

File Jalview.java

 

Coverage histogram

../../img/srcFileCovDistChart6.png
37% 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.535916153.6%
Jalview.FeatureFetcher 251 13 4
0.00%
Jalview.ExitCode 2204 0 0
-1.0 -
 

Contributing tests

This file is covered by 302 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  40624 toggle public static Jalview getInstance()
148    {
149  40624 return ApplicationSingletonProvider.getInstance(Jalview.class);
150    }
151   
 
152  1208 toggle public static boolean instanceExists()
153    {
154  1208 return ApplicationSingletonProvider.instanceExists(Jalview.class);
155    }
156   
 
157  55 toggle private Jalview()
158    {
159  55 Platform.getURLCommandArguments();
160  55 Platform.addJ2SDirectDatabaseCall("https://www.jalview.org");
161  55 Platform.addJ2SDirectDatabaseCall("http://www.jalview.org");
162  55 Platform.addJ2SDirectDatabaseCall("http://www.compbio.dundee.ac.uk");
163  55 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  387 toggle public static boolean quiet()
181    {
182  387 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  492 toggle public boolean getStartCalculations()
194    {
195  492 return !noCalculation;
196    }
197   
 
198  439 toggle public boolean getAllowMenuBar()
199    {
200  439 return !noMenuBar;
201    }
202   
 
203  439 toggle public boolean getShowStatus()
204    {
205  439 return !noStatus;
206    }
207   
 
208  0 toggle public boolean getShowAnnotation()
209    {
210  0 return !noAnnotation;
211    }
212   
 
213  55 toggle static
214    {
215  55 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  55 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  87 toggle public static void main(String[] args)
313    {
314  87 if (doPlatformLogging)
315    {
316  0 Platform.startJavaLogging();
317    }
318   
319  87 getInstance().doMain(args);
320   
321    }
322   
323    /**
324    * @param args
325    */
 
326  138 toggle void doMain(String[] args)
327    {
328  138 boolean isJS = Platform.isJS();
329  138 if (!isJS)
330    {
331  138 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  138 if (args == null || args.length == 0 || (args.length == 1
340    && (args[0] == null || args[0].length() == 0)))
341    {
342  9 args = new String[] {};
343    }
344   
345    // get args needed before proper ArgParser
346  138 bootstrapArgs = BootstrapArgs.getBootstrapArgs(args);
347   
348  138 boolean usingLogfile = false;
349  138 if (!Platform.isJS())
350    {
351    // required to ensure log4j doesn't think it's running in a servlet
352  138 System.setProperty("log4j2.isWebapp", "false");
353   
354    // are we using a logfile?
355  138 String logfilename = System.getProperty("installer.logfile");
356  138 boolean append = Boolean
357    .parseBoolean(System.getProperty("installer.logfile_append"));
358   
359  138 usingLogfile = Console.setLogFile(logfilename, append);
360   
361    // are we being --quiet ? (doesn't matter if using a logfile)
362  138 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  138 if (bootstrapArgs.contains(Arg.HELP)
382    || bootstrapArgs.contains(Arg.VERSION))
383    {
384  0 QUIET = true;
385    }
386    }
387   
388    // set individual session preferences
389  138 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  138 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  138 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  138 Console.errPrintln("launcher.appdir property not found");
431    }
432   
433  138 if ((usingLogfile || !quiet()) || !bootstrapArgs.outputToStdout()
434    || bootstrapArgs.contains(Arg.VERSION))
435    {
436  138 if (usingLogfile)
437    {
438  0 Console.outPrintln("-------");
439    }
440  138 Console.outPrint(Cache.getVersionDetailsForConsole());
441  138 if (usingLogfile)
442    {
443  0 Console.outPrintln("-------");
444    }
445    }
446   
447  138 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  138 Properties bootstrapProperties = Cache
454    .bootstrapProperties(bootstrapArgs.getValue(Arg.PROPS));
455   
456    // report Jalview version
457  138 Cache.getInstance().loadBuildProperties(
458    !quiet() || bootstrapArgs.contains(Arg.VERSION));
459   
460    // stop now if only after --version
461  138 if (bootstrapArgs.contains(Arg.VERSION))
462    {
463  0 Jalview.exit(null, ExitCode.OK);
464    }
465   
466    // old ArgsParser
467  138 ArgsParser aparser = new ArgsParser(args);
468   
469    // old
470  138 boolean headless = false;
471    // new
472  138 boolean headlessArg = false;
473   
474  138 try
475    {
476  138 String logLevel = null;
477  138 if (bootstrapArgs.contains(Arg.TRACE))
478    {
479  0 logLevel = "TRACE";
480    }
481  138 else if (bootstrapArgs.contains(Arg.DEBUG))
482    {
483  23 logLevel = bootstrapArgs.getBoolean(Arg.DEBUG) ? "DEBUG" : "INFO";
484    }
485  138 if (logLevel == null && !(bootstrapProperties == null))
486    {
487  115 logLevel = bootstrapProperties.getProperty(Cache.JALVIEWLOGLEVEL);
488    }
489  138 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  138 if (!Platform.isJS())
499    {
500    // register SIGTERM listener
501  138 Runtime.getRuntime().addShutdownHook(new Thread()
502    {
 
503  106 toggle @Override
504    public void run()
505    {
506  106 Console.debug("Running shutdown hook");
507  105 QuitHandler.startForceQuit();
508  105 boolean closeExternal = Cache
509    .getDefault("DEFAULT_CLOSE_EXTERNAL_VIEWERS", false)
510    || Cache.getDefault("ALWAYS_CLOSE_EXTERNAL_VIEWERS",
511    false);
512  105 StructureViewerBase.setQuitClose(closeExternal);
513  95 if (desktop != null)
514    {
515  65 for (JInternalFrame frame : Desktop.getInstance()
516    .getAllFrames())
517    {
518  61 if (frame instanceof StructureViewerBase)
519    {
520  1 ((StructureViewerBase) frame).closeViewer(closeExternal);
521    }
522    }
523    }
524   
525  94 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  94 Console.debug("Nothing more to do");
539    }
540  94 Console.debug("Exiting, bye!");
541    // shutdownHook cannot be cancelled, JVM will now halt
542    }
543    });
544    }
545   
546  138 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  138 Cache.loadProperties(usrPropsFile);
552  137 if (usrPropsFile != null)
553    {
554  47 Console.outPrintln(
555    "CMD [-props " + usrPropsFile + "] executed successfully!");
556  47 testoutput(bootstrapArgs, Arg.PROPS,
557    "test/jalview/bin/testProps.jvprops", usrPropsFile);
558    }
559   
560    // --argfile=... -- OVERRIDES ALL NON-BOOTSTRAP ARGS
561  137 if (bootstrapArgs.contains(Arg.ARGFILE))
562    {
563  8 argparser = ArgParser.parseArgFiles(
564    bootstrapArgs.getValueList(Arg.ARGFILE),
565    bootstrapArgs.getBoolean(Arg.INITSUBSTITUTIONS),
566    bootstrapArgs);
567    }
568    else
569    {
570  129 argparser = new ArgParser(args,
571    bootstrapArgs.getBoolean(Arg.INITSUBSTITUTIONS),
572    bootstrapArgs);
573    }
574   
575  137 boolean allowServices = true;
576   
577  137 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  137 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  137 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  137 headlessArg = bootstrapArgs.isHeadless();
613  137 if (headlessArg)
614    {
615  27 System.setProperty("java.awt.headless", "true");
616    }
617    // old CLI
618    // BH note: Only -nodisplay is official; others are deprecated?
619  137 if (aparser.contains("nodisplay") || aparser.contains("nogui")
620    || aparser.contains("headless")
621    || GraphicsEnvironment.isHeadless())
622    {
623  39 if (!isJS)
624    {
625    // BH Definitely not a good idea in JavaScript;
626    // probably should not be here for Java, either.
627  39 System.setProperty("java.awt.headless", "true");
628    }
629  39 headless = true;
630    }
631    // anything else!
632   
633    // allow https handshakes to download intermediate certs if necessary
634  137 System.setProperty("com.sun.security.enableAIAcaIssuers", "true");
635  137 String jabawsUrl = bootstrapArgs.getValue(Arg.JABAWS);
636  137 if (jabawsUrl == null)
637  136 jabawsUrl = aparser.getValue(ArgsParser.JABAWS);
638  137 allowServices = !("none".equals(jabawsUrl));
639  137 if (allowServices && jabawsUrl != null)
640    {
641  2 try
642    {
643  2 Jws2Discoverer.getInstance().setPreferredUrl(jabawsUrl);
644  2 Console.outPrintln(
645    "CMD [-jabaws " + jabawsUrl + "] executed successfully!");
646  2 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  137 List<String> setprops = new ArrayList<>();
657  137 if (bootstrapArgs.contains(Arg.SETPROP))
658    {
659  0 setprops = bootstrapArgs.getValueList(Arg.SETPROP);
660    }
661    else
662    {
663  137 String sp = aparser.getValue("setprop");
664  137 while (sp != null)
665    {
666  0 setprops.add(sp);
667  0 sp = aparser.getValue("setprop");
668    }
669    }
670  137 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  137 if (System.getProperty("java.awt.headless") != null
690    && System.getProperty("java.awt.headless").equals("true"))
691    {
692  44 headless = true;
693    }
694  137 System.setProperty("http.agent", UserAgent.getUserAgent());
695   
696    // Initialise the logger
697  137 try
698    {
699  137 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  137 desktop = null;
708   
709  137 if (!(headless || headlessArg))
710    {
711  93 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  137 boolean soDefault = !isJS;
719  137 if (Cache.getDefault("USE_FULL_SO", soDefault))
720    {
721  137 SequenceOntologyFactory.setSequenceOntology(new SequenceOntology());
722    }
723   
724  137 if (!(headless || headlessArg))
725    {
726  93 Desktop.nosplash = "false".equals(bootstrapArgs.getValue(Arg.SPLASH))
727    || aparser.contains("nosplash")
728    || Cache.getDefault("SPLASH", "true").equals("false");
729  93 desktop = Desktop.getInstance();
730  93 desktop.setInBatchMode(true); // indicate we are starting up
731   
732  93 mixedCliWarning();
733   
734  93 try
735    {
736  93 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  93 Cache.setProxyPropertiesFromPreferences();
751   
752  93 desktop.setVisible(true);
753   
754  93 if (isJS)
755    {
756  0 Cache.setProperty("SHOW_JWS2_SERVICES", "false");
757    }
758  93 if (allowServices && !aparser.contains("nowebservicediscovery"))
759    {
760  93 desktop.startServiceDiscovery();
761    }
762   
763  93 if (!isJS)
764    /**
765    * Java only
766    *
767    * @j2sIgnore
768    */
769    {
770   
771  93 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  93 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  93 String installerappdirString = System
807    .getProperty("installer.appdir");
808  93 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  93 boolean webservicediscovery = bootstrapArgs
826    .getBoolean(Arg.WEBSERVICEDISCOVERY);
827  93 if (aparser.contains("nowebservicediscovery"))
828  0 webservicediscovery = false;
829  93 if (webservicediscovery)
830    {
831  73 desktop.startServiceDiscovery();
832    }
833    else
834    {
835  20 testoutput(argparser, Arg.WEBSERVICEDISCOVERY);
836    }
837   
838  93 boolean usagestats = !bootstrapArgs.getBoolean(Arg.NOUSAGESTATS);
839  93 if (aparser.contains("nousagestats"))
840  1 usagestats = false;
841  93 if (usagestats)
842    {
843  87 startUsageStats(desktop);
844  87 testoutput(argparser, Arg.NOUSAGESTATS);
845    }
846    else
847    {
848  6 Console.outPrintln("CMD [-nousagestats] executed successfully!");
849  6 testoutput(argparser, Arg.NOUSAGESTATS);
850    }
851   
852  93 boolean questionnaire = bootstrapArgs.getBoolean(Arg.QUESTIONNAIRE);
853  93 if (aparser.contains("noquestionnaire"))
854  1 questionnaire = false;
855  93 if (questionnaire)
856    {
857  85 String url = aparser.getValue("questionnaire");
858  85 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  85 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  39 String defurl = "https://www.jalview.org/cgi-bin/questionnaire.pl";
877  39 Console.debug(
878    "Starting questionnaire with default url: " + defurl);
879  39 desktop.checkForQuestionnaire(defurl);
880    }
881    }
882    }
883    else
884    {
885  8 Console.outPrintln(
886    "CMD [-noquestionnaire] executed successfully!");
887  8 testoutput(argparser, Arg.QUESTIONNAIRE);
888    }
889   
890  93 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  42 desktop.checkForNews();
896    }
897   
898  93 if (!aparser.contains("nohtmltemplates")
899    && Cache.getProperty("NOHTMLTEMPLATES") == null)
900    {
901  93 BioJsHTMLOutput.updateBioJS();
902    }
903    }
904    }
905    else
906    {
907   
908  44 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  44 if (getArgParser().isOldStyle())
919    {
920  17 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  17 Console.warn(warning);
925    }
926   
927    }
928   
929    // Run Commands from cli
930  137 cmds = new Commands(desktop, argparser, headlessArg);
931  137 cmds.processArgs();
932  132 boolean commandsSuccess = cmds.argsWereParsed();
933   
934  132 if (commandsSuccess)
935    {
936  79 if (headlessArg)
937    {
938  27 if (argparser.getBoolean(Arg.NOQUIT))
939    {
940  1 Console.warn(
941    "Completed " + Arg.HEADLESS.getName() + " commands, but "
942    + Arg.NOQUIT + " is set so not quitting!");
943    }
944    else
945    {
946  26 Jalview.exit("Successfully completed commands in headless mode",
947    ExitCode.OK);
948    }
949    }
950  53 Console.info("Successfully completed commands");
951    }
952    else
953    {
954  53 if (headlessArg)
955    {
956  0 Jalview.exit("Error when running Commands in headless mode",
957    ExitCode.ERROR_RUNNING_COMMANDS);
958    }
959  53 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  106 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  106 parseArguments(aparser, true, commandsSuccess);
975   
976  87 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  106 toggle public void parseArguments(ArgsParser aparser, boolean isStartup,
999    boolean commandsSuccess)
1000    {
1001  106 String groovyscript = null; // script to execute after all loading is
1002  106 boolean isJS = Platform.isJS();
1003  106 if (!isJS)
1004    /** @j2sIgnore */
1005    {
1006    // Move any new getdown-launcher-new.jar into place over old
1007    // getdown-launcher.jar
1008  106 String appdirString = System.getProperty("getdownappdir");
1009  106 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  106 String file = null, data = null;
1027   
1028  106 FileFormatI format = null;
1029   
1030  106 DataSourceType protocol = null;
1031   
1032  106 FileLoader fileLoader = new FileLoader(!headless);
1033   
1034  106 groovyscript = aparser.getValue("groovy", true);
1035  106 file = aparser.getValue("open", true);
1036   
1037  106 if (!isJS && file == null && desktop == null && !commandsSuccess)
1038    {
1039  0 Jalview.exit("No files to open!", ExitCode.NO_FILES);
1040    }
1041  106 setDisplayParameters(aparser);
1042   
1043    // time to open a file.
1044  106 long progress = -1;
1045    // Finally, deal with the remaining input data.
1046  106 AlignFrame af = null;
1047   
1048  106 JalviewJSApp jsApp = (isJS ? new JalviewJSApp(this, aparser) : null);
1049   
1050  106 if (file == null)
1051    {
1052  88 if (isJS)
1053    {
1054    // JalviewJS allows sequence1 sequence2 ....
1055   
1056    }
1057    }
1058   
1059  106 if (file != null)
1060    {
1061   
1062  18 if (!(headless || isHeadlessMode()))
1063    {
1064  1 desktop.setProgressBar(
1065    MessageManager
1066    .getString("status.processing_commandline_args"),
1067    progress = System.currentTimeMillis());
1068    }
1069   
1070  18 Console.outPrintln("CMD [-open " + file + "] executed successfully!");
1071   
1072  18 if (!Platform.isJS())
1073    /**
1074    * ignore in JavaScript -- can't just file existence - could load it?
1075    *
1076    * @j2sIgnore
1077    */
1078    {
1079  18 if (!HttpUtils.startsWithHttpOrHttps(file))
1080    {
1081  18 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  18 String fileFormat = (isJS
1097    ? (String) aparser.getAppletValue("format", null, true)
1098    : null);
1099   
1100  18 protocol = AppletFormatAdapter.checkProtocol(file);
1101   
1102  18 try
1103    {
1104  18 format = (fileFormat != null
1105    ? FileFormats.getInstance().forName(fileFormat)
1106    : null);
1107  18 if (format == null)
1108    {
1109  18 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  18 af = new FileLoader(!headless).LoadFileWaitTillLoaded(file, protocol,
1120    format);
1121  18 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  18 String file2 = aparser.getValue(ArgsParser.OPEN2, true);
1130  18 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  18 setCurrentAlignFrame(af);
1161   
1162  18 setFrameDependentProperties(aparser, af);
1163   
1164  18 if (isJS)
1165    {
1166  0 jsApp.initFromParams(af);
1167    }
1168    else
1169    /**
1170    * Java only
1171    *
1172    * @j2sIgnore
1173    */
1174    {
1175  18 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  18 if (!isJS || !isStartup)
1188    {
1189  18 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  105 if (!isJS && (headless || isHeadlessMode()))
1196    {
1197    // TODO JAL-4107 - why doesn't Jalview.exit() do this ?
1198  18 if (af != null)
1199    {
1200  17 af.getViewport().getCalcManager().shutdown();
1201    }
1202  18 Jalview.exit("All done.", ExitCode.OK);
1203    }
1204   
1205  87 AlignFrame startUpAlframe = null;
1206    // We'll only open the default file if the desktop is visible.
1207    // And the user
1208    // ////////////////////
1209   
1210  87 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  87 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  87 if (desktop != null)
1288    {
1289  87 if (progress != -1)
1290    {
1291  0 desktop.setProgressBar(null, progress);
1292    }
1293  87 desktop.setInBatchMode(false);
1294    }
1295   
1296  87 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  106 toggle private void setDisplayParameters(ArgsParser aparser)
1309    {
1310  106 if (aparser.contains(ArgsParser.NOMENUBAR))
1311    {
1312  0 noMenuBar = true;
1313  0 Console.outPrintln("CMD [nomenu] executed successfully!");
1314    }
1315   
1316  106 if (aparser.contains(ArgsParser.NOSTATUS))
1317    {
1318  0 noStatus = true;
1319  0 Console.outPrintln("CMD [nostatus] executed successfully!");
1320    }
1321   
1322  106 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  106 if (aparser.contains(ArgsParser.NOCALCULATION))
1329    {
1330  0 noCalculation = true;
1331  0 Console.outPrintln("CMD [nocalculation] executed successfully!");
1332    }
1333    }
1334   
 
1335  18 toggle private void setFrameDependentProperties(ArgsParser aparser,
1336    AlignFrame af)
1337    {
1338  18 String data = aparser.getValue(ArgsParser.COLOUR, true);
1339  18 if (data != null)
1340    {
1341  1 data.replaceAll("%20", " ");
1342   
1343  1 ColourSchemeI cs = ColourSchemeProperty.getColourScheme(
1344    af.getViewport(), af.getViewport().getAlignment(), data);
1345   
1346  1 if (cs != null)
1347    {
1348  1 Console.outPrintln(
1349    "CMD [-colour " + data + "] executed successfully!");
1350    }
1351  1 af.changeColour(cs);
1352    }
1353   
1354    // Must maintain ability to use the groups flag
1355  18 data = aparser.getValue(ArgsParser.GROUPS, true);
1356  18 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  18 data = aparser.getValue(ArgsParser.FEATURES, true);
1364  18 if (data != null)
1365    {
1366  1 af.parseFeaturesFile(data, AppletFormatAdapter.checkProtocol(data));
1367    // System.out.println("Added " + data);
1368  1 Console.outPrintln(
1369    "CMD [-features " + data + "] executed successfully!");
1370    }
1371  18 data = aparser.getValue(ArgsParser.ANNOTATIONS, true);
1372  18 if (data != null)
1373    {
1374  1 af.loadJalviewDataFile(data, null, null, null);
1375    // System.out.println("Added " + data);
1376  1 Console.outPrintln(
1377    "CMD [-annotations " + data + "] executed successfully!");
1378    }
1379   
1380    // JavaScript feature
1381   
1382  18 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  18 if (aparser.contains(ArgsParser.SORTBYTREE))
1390    {
1391  1 af.getViewport().setSortByTree(true);
1392  1 if (af.getViewport().getSortByTree())
1393    {
1394  1 Console.outPrintln("CMD [-sortbytree] executed successfully!");
1395    }
1396    }
1397   
1398  18 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  18 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  18 if (aparser.contains(ArgsParser.NOSORTBYTREE))
1422    {
1423  1 af.getViewport().setSortByTree(false);
1424  1 if (!af.getViewport().getSortByTree())
1425    {
1426  1 doUpdateAnnotation = true;
1427  1 Console.outPrintln("CMD [-nosortbytree] executed successfully!");
1428    }
1429    }
1430  18 if (doUpdateAnnotation)
1431    { // BH 2019.07.24
1432  1 af.setMenusForViewport();
1433  1 af.alignPanel.updateLayout();
1434    }
1435   
1436  18 data = aparser.getValue(ArgsParser.TREE, true);
1437  18 if (data != null)
1438    {
1439  1 try
1440    {
1441  1 NewickFile nf = new NewickFile(data,
1442    AppletFormatAdapter.checkProtocol(data));
1443  1 af.getViewport()
1444    .setCurrentTree(af.showNewickTree(nf, data).getTree());
1445  1 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  18 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  18 AlignFrame af = currentAlignFrame;
1484  18 String file = null;
1485  34 while (aparser.getSize() >= 2)
1486    {
1487  16 try
1488    {
1489  16 String outputFormat = aparser.nextValue();
1490  16 File imageFile;
1491  16 file = aparser.nextValue();
1492  16 String fname;
1493  16 switch (outputFormat.toLowerCase(Locale.ROOT))
1494    {
1495  1 case "png":
1496  1 imageFile = new File(file);
1497  1 af.createPNG(imageFile);
1498  1 Console.outPrintln(
1499    "Creating PNG image: " + imageFile.getAbsolutePath());
1500  1 continue;
1501  1 case "svg":
1502  1 imageFile = new File(file);
1503  1 af.createSVG(imageFile);
1504  1 Console.outPrintln(
1505    "Creating SVG image: " + imageFile.getAbsolutePath());
1506  1 continue;
1507  5 case "eps":
1508  5 imageFile = new File(file);
1509  5 Console.outPrintln(
1510    "Creating EPS file: " + imageFile.getAbsolutePath());
1511  5 af.createEPS(imageFile);
1512  5 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  1 case "html":
1529  1 fname = new File(file).getAbsolutePath();
1530  1 HtmlSvgOutput htmlSVG = new HtmlSvgOutput(af.alignPanel);
1531  1 htmlSVG.exportHTML(fname);
1532  1 Console.outPrintln("Creating HTML image: " + fname);
1533  1 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  8 default:
1541    // fall through - try to parse as an alignment data export format
1542  8 FileFormatI outFormat = null;
1543  8 try
1544    {
1545  8 outFormat = FileFormats.getInstance().forName(outputFormat);
1546    } catch (Exception formatP)
1547    {
1548  0 Console.errPrintln(Cache.getStackTraceString(formatP));
1549    }
1550  8 if (outFormat == null)
1551    {
1552  0 Console.outPrintln("Couldn't parse " + outputFormat
1553    + " as a valid Jalview format string.");
1554  0 continue;
1555    }
1556  8 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  8 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  8 af.saveAlignment(fname, outFormat);
1572  8 if (af.isSaveAlignmentSuccessful())
1573    {
1574  8 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  18 while (aparser.getSize() > 0)
1594    {
1595  0 Console.outPrintln("Ignoring extra argument: " + aparser.nextValue());
1596    }
1597   
1598  18 cliWarning();
1599    }
1600   
 
1601  93 toggle private static void setLookAndFeel()
1602    {
1603  93 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  93 String lafProp = System.getProperty("laf");
1616  93 String lafSetting = Cache.getDefault("PREFERRED_LAF", null);
1617  93 String laf = "none";
1618  93 if (lafProp != null)
1619    {
1620  0 laf = lafProp;
1621    }
1622  93 else if (lafSetting != null)
1623    {
1624  0 laf = lafSetting;
1625    }
1626  93 boolean lafSet = false;
1627  93 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  93 case "none":
1679  93 break;
1680  0 default:
1681  0 Console.error("Requested laf=" + laf + " not implemented");
1682    }
1683  93 if (!lafSet)
1684    {
1685    // Flatlaf default for everyone!
1686  93 lafSet = setFlatLookAndFeel();
1687  93 if (!lafSet)
1688    {
1689  0 setSystemLookAndFeel();
1690    }
1691  93 if (Platform.isLinux())
1692    {
1693  93 setLinuxLookAndFeel();
1694    }
1695  93 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  186 toggle private static boolean setFlatLookAndFeel()
1784    {
1785  186 boolean set = false;
1786  186 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  186 if (!set)
1821    {
1822  186 try
1823    {
1824  186 UIManager.setLookAndFeel("com.formdev.flatlaf.FlatLightLaf");
1825  186 set = true;
1826  186 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  186 SwingUtilities.invokeLater(() -> {
1834  186 FlatLightLaf.setup();
1835    });
1836  186 Console.debug("Using FlatLightLaf");
1837  186 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  186 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  186 if (set)
1876    {
1877  186 UIManager.put("TabbedPane.tabType", "card");
1878  186 UIManager.put("TabbedPane.showTabSeparators", true);
1879  186 UIManager.put("TabbedPane.showContentSeparator", true);
1880    // UIManager.put("TabbedPane.tabSeparatorsFullHeight", true);
1881  186 UIManager.put("TabbedPane.tabsOverlapBorder", true);
1882  186 UIManager.put("TabbedPane.hasFullBorder", true);
1883  186 UIManager.put("TabbedPane.tabLayoutPolicy", "scroll");
1884  186 UIManager.put("TabbedPane.scrollButtonsPolicy", "asNeeded");
1885  186 UIManager.put("TabbedPane.smoothScrolling", true);
1886  186 UIManager.put("TabbedPane.tabWidthMode", "compact");
1887  186 UIManager.put("TabbedPane.selectedBackground", Color.white);
1888  186 UIManager.put("TabbedPane.background", new Color(236, 236, 236));
1889  186 UIManager.put("TabbedPane.hoverColor", Color.lightGray);
1890    }
1891   
1892  186 Desktop.setLiveDragMode(Cache.getDefault("FLAT_LIVE_DRAG_MODE", true));
1893  186 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  93 toggle private static boolean setLinuxLookAndFeel()
1916    {
1917  93 boolean set = false;
1918  93 set = setFlatLookAndFeel();
1919  93 if (!set)
1920  0 set = setMetalLookAndFeel();
1921    // avoid GtkLookAndFeel -- not good results especially on HiDPI
1922  93 if (!set)
1923  0 set = setNimbusLookAndFeel();
1924  93 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  87 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  87 PromptUserConfig prompter = new PromptUserConfig(desktop, "USAGESTATS",
1978    MessageManager.getString("prompt.analytics_title"),
1979    MessageManager.getString("prompt.analytics"), new Runnable()
1980    {
 
1981  1 toggle @Override
1982    public void run()
1983    {
1984  1 Console.debug("Initialising analytics for usage stats.");
1985  1 Cache.initAnalytics();
1986  1 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  87 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  36989 toggle public static boolean isHeadlessMode()
2121    {
2122  36989 String isheadless = System.getProperty("java.awt.headless");
2123  36990 if (isheadless != null && isheadless.equalsIgnoreCase("true"))
2124    {
2125  866 return true;
2126    }
2127  36124 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  1156 toggle public void setCurrentAlignFrame(AlignFrame af)
2156    {
2157  1156 this.currentAlignFrame = af;
2158    }
2159   
 
2160  341 toggle public Commands getCommands()
2161    {
2162  341 return cmds;
2163    }
2164   
 
2165  45 toggle public static void exit(String message, ExitCode ec)
2166    {
2167  45 int exitcode = ec == ExitCode.OK ? 0 : ec.ordinal() + 1;
2168  45 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  45 Console.debug("Using Jalview.exit");
2186  45 if (message != null)
2187    {
2188  45 if (exitcode == 0)
2189    {
2190  45 Console.info(message);
2191    }
2192    else
2193    {
2194  0 Console.error(message);
2195    }
2196    }
2197    }
2198  45 if (exitcode > -1)
2199    {
2200  45 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  153 toggle protected static void testoutput(ArgParser ap, Arg a, String s1,
2235    String s2)
2236    {
2237  153 BootstrapArgs bsa = ap.getBootstrapArgs();
2238  153 if (!bsa.getBoolean(Arg.TESTOUTPUT))
2239  131 return;
2240  22 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  22 boolean isset = a.hasOption(Opt.BOOTSTRAP) ? bsa.contains(a)
2247    : ap.isSet(a);
2248  22 if (!isset)
2249    {
2250  0 Console.warn("Arg '" + a.getName() + "' not set at all");
2251  0 return;
2252    }
2253  22 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  49 toggle protected static void testoutput(BootstrapArgs bsa, Arg a, String s1,
2263    String s2)
2264    {
2265  49 if (!bsa.getBoolean(Arg.TESTOUTPUT))
2266  47 return;
2267  2 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  2 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  2 if (!bsa.contains(a))
2279    {
2280  0 Console.warn("Arg '" + a.getName() + "' not set at all");
2281  0 return;
2282    }
2283  2 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  24 toggle private static void testoutput(boolean yes, Arg a, String s1, String s2)
2291    {
2292  24 if (yes && ((s1 == null && s2 == null)
2293    || (s1 != null && s1.equals(s2))))
2294    {
2295  24 Console.outPrintln("[TESTOUTPUT] arg " + a.argString() + "='" + s1
2296    + "' was set");
2297    }
2298    }
2299   
2300    /*
2301    * testoutput for boolean and unary values
2302    */
 
2303  122 toggle protected static void testoutput(ArgParser ap, Arg a)
2304    {
2305  122 if (ap == null)
2306  0 return;
2307  122 BootstrapArgs bsa = ap.getBootstrapArgs();
2308  122 if (bsa == null)
2309  2 return;
2310  120 if (!bsa.getBoolean(Arg.TESTOUTPUT))
2311  117 return;
2312  3 boolean val = a.hasOption(Opt.BOOTSTRAP) ? bsa.getBoolean(a)
2313    : ap.getBoolean(a);
2314  3 boolean isset = a.hasOption(Opt.BOOTSTRAP) ? bsa.contains(a)
2315    : ap.isSet(a);
2316  3 if (!isset)
2317    {
2318  0 Console.warn("Arg '" + a.getName() + "' not set at all");
2319  0 return;
2320    }
2321  3 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  3 toggle private static void testoutput(boolean yes, Arg a)
2343    {
2344  3 String message = null;
2345  3 if (a.hasOption(Opt.BOOLEAN))
2346    {
2347  2 message = (yes ? a.argString() : a.negateArgString()) + " was set";
2348    }
2349  1 else if (a.hasOption(Opt.UNARY))
2350    {
2351  1 message = a.argString() + (yes ? " was set" : " was not set");
2352    }
2353  3 Console.outPrintln("[TESTOUTPUT] arg " + message);
2354    }
2355   
 
2356  495 toggle public ArgParser getArgParser()
2357    {
2358  495 return argparser;
2359    }
2360   
 
2361  1408 toggle public BootstrapArgs getBootstrapArgs()
2362    {
2363  1408 return bootstrapArgs;
2364    }
2365   
 
2366  56 toggle public static boolean isBatchMode()
2367    {
2368  56 return instanceExists() && (getInstance().desktop == null
2369    || getInstance().desktop.isInBatchMode());
2370    }
2371   
2372    /**
2373    * Warning about old or mixed command line arguments
2374    */
 
2375  93 toggle private void mixedCliWarning()
2376    {
2377  93 Jalview j = Jalview.getInstance();
2378  93 boolean mixedStyle = j.getArgParser() != null
2379    && j.getArgParser().isMixedStyle();
2380  93 String title = MessageManager.getString("label.command_line_arguments");
2381  93 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  105 toggle private void cliWarning()
2398    {
2399  105 Jalview j = Jalview.getInstance();
2400  105 Commands c = j.getCommands();
2401  105 boolean oldStyle = j.getArgParser() != null
2402    && j.getArgParser().isOldStyle();
2403  105 String title = MessageManager.getString("label.command_line_arguments");
2404  105 if (oldStyle)
2405    {
2406  18 String warning = MessageManager
2407    .getString("warning.using_old_command_line_arguments");
2408  18 String url = "<a href=\"https://www.jalview.org/help/html/features/commandline.html\">https://www.jalview.org/help/html/features/commandline.html</a>";
2409  18 if (Desktop.getInstance() != null)
2410    {
2411  1 String cont = MessageManager.getString("label.continue");
2412   
2413  1 Desktop.getInstance().nonBlockingDialog(title, warning, url, cont,
2414    JvOptionPane.WARNING_MESSAGE, false, true, true, 30000);
2415    }
2416    }
2417  104 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  11 toggle public static boolean isInteractive()
2448    {
2449  11 return isInteractive;
2450    }
2451   
 
2452  0 toggle public static void setInteractive(boolean tf)
2453    {
2454  0 isInteractive = tf;
2455    }
2456    }