2 * Jalview - A Sequence Alignment Editor and Viewer (Development Version 2.4.1)
3 * Copyright (C) 2009 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
21 import java.io.BufferedReader;
23 import java.io.FileOutputStream;
24 import java.io.IOException;
25 import java.io.OutputStreamWriter;
26 import java.io.PrintWriter;
27 import java.lang.reflect.Constructor;
29 import java.security.AllPermission;
30 import java.security.CodeSource;
31 import java.security.PermissionCollection;
32 import java.security.Permissions;
33 import java.security.Policy;
39 import jalview.io.AppletFormatAdapter;
42 * Main class for Jalview Application <br>
44 * start with java -Djava.ext.dirs=$PATH_TO_LIB$ jalview.bin.Jalview
52 // grab all the rights we can the JVM
53 Policy.setPolicy( new Policy() {
54 public PermissionCollection
55 getPermissions(CodeSource codesource) {
56 Permissions perms = new Permissions();
57 perms.add(new AllPermission());
60 public void refresh(){
65 * main class for Jalview application
68 * open <em>filename</em>
70 public static void main(String[] args)
72 System.out.println("Java version: "
73 + System.getProperty("java.version"));
74 System.out.println(System.getProperty("os.arch") + " "
75 + System.getProperty("os.name") + " "
76 + System.getProperty("os.version"));
78 ArgsParser aparser = new ArgsParser(args);
79 boolean headless = false;
81 if (aparser.contains("help") || aparser.contains("h"))
84 .println("Usage: jalview -open [FILE] [OUTPUT_FORMAT] [OUTPUT_FILE]\n\n"
85 + "-nodisplay\tRun Jalview without User Interface.\n"
86 + "-props FILE\tUse the given Jalview properties file instead of users default.\n"
87 + "-annotations FILE\tAdd precalculated annotations to the alignment.\n"
88 + "-tree FILE\tLoad the given newick format tree file onto the alignment\n"
89 + "-features FILE\tUse the given file to mark features on the alignment.\n"
90 + "-fasta FILE\tCreate alignment file FILE in Fasta format.\n"
91 + "-clustal FILE\tCreate alignment file FILE in Clustal format.\n"
92 + "-pfam FILE\tCreate alignment file FILE in PFAM format.\n"
93 + "-msf FILE\tCreate alignment file FILE in MSF format.\n"
94 + "-pileup FILE\tCreate alignment file FILE in Pileup format\n"
95 + "-pir FILE\tCreate alignment file FILE in PIR format.\n"
96 + "-blc FILE\tCreate alignment file FILE in BLC format.\n"
97 + "-jalview FILE\tCreate alignment file FILE in Jalview format.\n"
98 + "-png FILE\tCreate PNG image FILE from alignment.\n"
99 + "-imgMap FILE\tCreate HTML file FILE with image map of PNG image.\n"
100 + "-eps FILE\tCreate EPS file FILE from alignment.\n"
101 + "-questionnaire URL\tQueries the given URL for information about any Jalview user questionnaires.\n"
102 + "-noquestionnaire\tTurn off questionnaire check.\n"
103 + "-nousagestats\tTurn off google analytics tracking for this session.\n"
104 + "-sortbytree OR -nosortbytree\tEnable or disable sorting of the given alignment by the given tree\n"
105 // + "-setprop PROPERTY=VALUE\tSet the given Jalview property, after all other properties files have been read\n\t (quote the 'PROPERTY=VALUE' pair to ensure spaces are passed in correctly)"
106 + "-dasserver nickname=URL\tAdd and enable a das server with given nickname\n\t\t\t(alphanumeric or underscores only) for retrieval of features for all alignments.\n"
107 +"\t\t\tSources that also support the sequence command may be specified by prepending the URL with sequence:\n"
108 +"\t\t\t e.g. sequence:http://localdas.somewhere.org/das/source)\n"
109 + "-fetchfrom nickname\tQuery nickname for features for the alignments and display them.\n"
110 // + "-vdoc vamsas-document\tImport vamsas document into new session or join existing session with same URN\n"
111 // + "-vses vamsas-session\tJoin session with given URN\n"
112 + "-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"
113 + "\n~Read documentation in Application or visit http://www.jalview.org for description of Features and Annotations file~\n\n");
116 Cache.loadProperties(aparser.getValue("props")); // must do this before
118 String defs = aparser.getValue("setprop");
121 int p = defs.indexOf('=');
124 System.err.println("Ignoring invalid setprop argument : "+defs);
126 System.out.println("Executing setprop argument: "+defs);
127 // DISABLED FOR SECURITY REASONS
128 // TODO: add a property to allow properties to be overriden by cli args
129 // Cache.setProperty(defs.substring(0,p), defs.substring(p+1));
131 defs = aparser.getValue("setprop");
133 if (aparser.contains("nodisplay"))
135 System.setProperty("java.awt.headless", "true");
137 if (System.getProperty("java.awt.headless") != null
138 && System.getProperty("java.awt.headless").equals("true"))
146 } catch (java.lang.NoClassDefFoundError error)
148 error.printStackTrace();
150 .println("\nEssential logging libraries not found."
151 + "\nUse: java -Djava.ext.dirs=$PATH_TO_LIB$ jalview.bin.Jalview");
155 Desktop desktop = null;
159 UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()
160 // UIManager.getCrossPlatformLookAndFeelClassName()
161 // "com.sun.java.swing.plaf.gtk.GTKLookAndFeel"
162 // "javax.swing.plaf.metal.MetalLookAndFeel"
163 // "com.sun.java.swing.plaf.windows.WindowsLookAndFeel"
164 // "com.sun.java.swing.plaf.motif.MotifLookAndFeel"
168 } catch (Exception ex)
173 desktop = new Desktop();
174 desktop.setVisible(true);
175 desktop.discoverer.start();
176 if (!aparser.contains("nousagestats")) {
177 startUsageStats(desktop);
179 if (!aparser.contains("noquestionnaire"))
181 String url = aparser.getValue("questionnaire");
184 // Start the desktop questionnaire prompter with the specified
186 Cache.log.debug("Starting questionnaire url at " + url);
187 desktop.checkForQuestionnaire(url);
191 if (Cache.getProperty("NOQUESTIONNAIRES") == null)
193 // Start the desktop questionnaire prompter with the specified
196 // "http://anaplog.compbio.dundee.ac.uk/cgi-bin/questionnaire.pl";
198 String defurl = "http://www.jalview.org/cgi-bin/questionnaire.pl";
199 Cache.log.debug("Starting questionnaire with default url: "
201 desktop.checkForQuestionnaire(defurl);
208 String file = null, protocol = null, format = null, data = null;
209 jalview.io.FileLoader fileLoader = new jalview.io.FileLoader();
210 Vector getFeatures = null; // vector of das source nicknames to fetch
213 String groovyscript = null; // script to execute after all loading is
214 // completed one way or another
215 // extract groovy argument and execute if necessary
216 groovyscript = aparser.getValue("groovy");
217 file = aparser.getValue("open");
219 if (file == null && desktop == null)
221 System.out.println("No files to open!");
224 String vamsasImport=aparser.getValue("vdoc"),vamsasSession=aparser.getValue("vsess");
225 if (vamsasImport!=null || vamsasSession!=null)
227 if (desktop==null || headless)
229 System.out.println("Headless vamsas sessions not yet supported. Sorry.");
232 // if we have a file, start a new session and import it.
233 boolean inSession = false;
234 if (vamsasImport!=null)
237 String viprotocol = Jalview.checkProtocol(vamsasImport);
238 if (viprotocol == jalview.io.FormatAdapter.FILE) {
239 inSession = desktop.vamsasImport(new File(vamsasImport));
240 } else if (viprotocol == jalview.io.FormatAdapter.URL) {
241 inSession = desktop.vamsasImport(new URL(vamsasImport));
244 } catch (Exception e)
246 System.err.println("Exeption when importing "+vamsasImport+" as a vamsas document.");
250 System.err.println("Failed to import "+vamsasImport+" as a vamsas document.");
252 System.out.println("Imported Successfully into new session "+desktop.getVamsasApplication().getCurrentSession());
255 if (vamsasSession!=null) {
256 if (vamsasImport!=null) {
257 // close the newly imported session and import the Jalview specific remnants into the new session later on.
258 desktop.vamsasStop_actionPerformed(null);
260 // now join the new session
262 if (desktop.joinVamsasSession(vamsasSession)) {
263 System.out.println("Successfully joined vamsas session "+vamsasSession);
265 System.err.println("WARNING: Failed to join vamsas session "+vamsasSession);
267 } catch (Exception e)
269 System.err.println("ERROR: Failed to join vamsas session "+vamsasSession);
272 if (vamsasImport!=null) {
273 // the Jalview specific remnants can now be imported into the new session at the user's leisure.
274 Cache.log.info("Skipping Push for import of data into existing vamsas session."); // TODO: enable this when debugged
275 // desktop.getVamsasApplication().push_update();
279 // Finally, deal with the remaining input data.
282 System.out.println("Opening file: " + file);
284 if (!file.startsWith("http://"))
286 if (!(new java.io.File(file)).exists())
288 System.out.println("Can't find " + file);
296 protocol = checkProtocol(file);
298 format = new jalview.io.IdentifyFile().Identify(file, protocol);
300 AlignFrame af = fileLoader.LoadFileWaitTillLoaded(file, protocol,
304 System.out.println("error");
308 data = aparser.getValue("colour");
311 data.replaceAll("%20", " ");
313 jalview.schemes.ColourSchemeI cs = jalview.schemes.ColourSchemeProperty
314 .getColour(af.getViewport().getAlignment(), data);
318 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
320 ucs.parseAppletParameter(data);
324 System.out.println("colour is " + data);
328 // Must maintain ability to use the groups flag
329 data = aparser.getValue("groups");
332 af.parseFeaturesFile(data, checkProtocol(data));
333 System.out.println("Added " + data);
335 data = aparser.getValue("features");
338 af.parseFeaturesFile(data, checkProtocol(data));
339 System.out.println("Added " + data);
342 data = aparser.getValue("annotations");
345 af.loadJalviewDataFile(data);
346 System.out.println("Added " + data);
348 // set or clear the sortbytree flag.
349 if (aparser.contains("sortbytree"))
351 af.getViewport().setSortByTree(true);
353 if (aparser.contains("nosortbytree"))
355 af.getViewport().setSortByTree(false);
357 data = aparser.getValue("tree");
360 jalview.io.NewickFile fin = null;
363 fin = new jalview.io.NewickFile(data, checkProtocol(data));
366 af.getViewport().setCurrentTree(
367 af.ShowNewickTree(fin, data).getTree());
368 System.out.println("Added tree " + data);
370 } catch (IOException ex)
372 System.err.println("Couldn't add tree " + data);
373 ex.printStackTrace(System.err);
376 getFeatures = checkDasArguments(aparser);
377 if (af != null && getFeatures != null)
379 startFeatureFetching(getFeatures);
380 // need to block until fetching is complete.
381 while (af.operationInProgress())
383 // wait around until fetching is finished.
387 } catch (Exception e)
393 if (groovyscript != null)
395 // Execute the groovy script after we've done all the rendering stuff
396 // and before any images or figures are generated.
397 if (jalview.bin.Cache.groovyJarsPresent())
399 System.out.println("Executing script " + groovyscript);
400 executeGroovyScript(groovyscript, desktop);
405 .println("Sorry. Groovy Support is not available, so ignoring the provided groovy script "
410 String imageName = "unnamed.png";
411 while (aparser.getSize() > 1)
413 format = aparser.nextValue();
414 file = aparser.nextValue();
416 if (format.equalsIgnoreCase("png"))
418 af.createPNG(new java.io.File(file));
419 imageName = (new java.io.File(file)).getName();
420 System.out.println("Creating PNG image: " + file);
423 else if (format.equalsIgnoreCase("imgMap"))
425 af.createImageMap(new java.io.File(file), imageName);
426 System.out.println("Creating image map: " + file);
429 else if (format.equalsIgnoreCase("eps"))
431 System.out.println("Creating EPS file: " + file);
432 af.createEPS(new java.io.File(file));
436 if (af.saveAlignment(file, format))
438 System.out.println("Written alignment in " + format
439 + " format to " + file);
443 System.out.println("Error writing file " + file + " in " + format
449 while (aparser.getSize() > 0)
451 System.out.println("Unknown arg: " + aparser.nextValue());
454 AlignFrame startUpAlframe = null;
455 // We'll only open the default file if the desktop is visible.
457 // ////////////////////
458 if (!headless && file == null && vamsasImport==null
459 && jalview.bin.Cache.getDefault("SHOW_STARTUP_FILE", true))
461 file = jalview.bin.Cache.getDefault("STARTUP_FILE",
462 "http://www.jalview.org/examples/exampleFile_2_3.jar");
466 if (file.indexOf("http:") > -1)
471 if (file.endsWith(".jar"))
477 format = new jalview.io.IdentifyFile().Identify(file, protocol);
480 startUpAlframe = fileLoader.LoadFileWaitTillLoaded(file, protocol,
482 getFeatures = checkDasArguments(aparser);
483 // extract groovy arguments before anything else.
485 // Once all loading is done. Retrieve features.
486 if (getFeatures != null)
488 if (startUpAlframe != null)
490 startFeatureFetching(getFeatures);
493 if (groovyscript != null)
495 if (jalview.bin.Cache.groovyJarsPresent())
497 System.out.println("Executing script " + groovyscript);
498 executeGroovyScript(groovyscript, desktop);
503 .println("Sorry. Groovy Support is not available, so ignoring the provided groovy script "
508 // Once all other stuff is done, execute any groovy scripts (in order)
511 private static void startUsageStats(final Desktop desktop)
514 * start a User Config prompt asking if we can log usage statistics.
516 jalview.gui.PromptUserConfig prompter = new jalview.gui.PromptUserConfig(desktop.desktop,"USAGESTATS", "Jalview Usage Statistics", "Jalview uses Google Analytics to report usage statistics.\nDo you want to enable this ?\n\n(if you press cancel, you will be asked again next time)",
520 Cache.log.info("Initialising googletracker for usage stats.");
521 Cache.initGoogleTracker();
522 Cache.log.debug("Tracking enabled.");
527 Cache.log.info("Not enabling Google Tracking.");
530 SwingUtilities.invokeLater(prompter);
534 * Locate the given string as a file and pass it to the groovy interpreter.
536 * @param groovyscript
537 * the script to execute
538 * @param jalviewContext
539 * the Jalview Desktop object passed in to the groovy binding
540 * as the 'Jalview' object.
542 private static void executeGroovyScript(String groovyscript,
543 Object jalviewContext)
545 if (jalviewContext == null)
548 .println("Sorry. Groovy support is currently only available when running with the Jalview GUI enabled.");
551 if (groovyscript.trim().equals("STDIN"))
553 // read from stdin into a tempfile and execute it
556 sfile = File.createTempFile("jalview", "groovy");
557 PrintWriter outfile = new PrintWriter(new OutputStreamWriter(
558 new FileOutputStream(sfile)));
559 BufferedReader br = new BufferedReader(
560 new java.io.InputStreamReader(System.in));
562 while ((line = br.readLine()) != null)
564 outfile.write(line + "\n");
570 } catch (Exception ex)
572 System.err.println("Failed to read from STDIN into tempfile "
573 + ((sfile == null) ? "(tempfile wasn't created)" : sfile
575 ex.printStackTrace();
581 sfile = new File(groovyscript);
585 System.err.println("File '" + groovyscript + "' does not exist.");
588 if (!sfile.canRead())
590 System.err.println("File '" + groovyscript + "' cannot be read.");
593 if (sfile.length() < 1)
595 System.err.println("File '" + groovyscript + "' is empty.");
598 boolean success = false;
602 * The following code performs the GroovyScriptEngine invocation using
603 * reflection, and is equivalent to this fragment from the embedding
604 * groovy documentation on the groovy site: <code> import
605 * groovy.lang.Binding; import groovy.util.GroovyScriptEngine;
607 * String[] roots = new String[] { "/my/groovy/script/path" };
608 * GroovyScriptEngine gse = new GroovyScriptEngine(roots); Binding binding =
609 * new Binding(); binding.setVariable("input", "world");
610 * gse.run("hello.groovy", binding); </code>
612 ClassLoader cl = jalviewContext.getClass().getClassLoader();
613 Class gbindingc = cl.loadClass("groovy.lang.Binding");
614 Constructor gbcons = gbindingc.getConstructor(null);
615 Object gbinding = gbcons.newInstance(null);
616 java.lang.reflect.Method setvar = gbindingc.getMethod("setVariable",
618 { String.class, Object.class });
619 setvar.invoke(gbinding, new Object[]
620 { "Jalview", jalviewContext });
621 Class gsec = cl.loadClass("groovy.util.GroovyScriptEngine");
622 Constructor gseccons = gsec.getConstructor(new Class[]
623 { URL[].class }); // String[].class });
624 Object gse = gseccons.newInstance(new Object[]
626 { sfile.toURL() } }); // .toString() } });
627 java.lang.reflect.Method run = gsec.getMethod("run", new Class[]
628 { String.class, gbindingc });
629 run.invoke(gse, new Object[]
630 { sfile.getName(), gbinding });
632 } catch (Exception e)
634 System.err.println("Exception Whilst trying to execute file " + sfile
635 + " as a groovy script.");
636 e.printStackTrace(System.err);
639 if (success && groovyscript.equals("STDIN"))
641 // delete temp file that we made - but only if it was successfully
648 * Check commandline for any das server definitions or any fetchfrom switches
650 * @return vector of DAS source nicknames to retrieve from
652 private static Vector checkDasArguments(ArgsParser aparser)
654 Vector source = null;
656 String locsources = Cache.getProperty(Cache.DAS_LOCAL_SOURCE);
657 while ((data = aparser.getValue("dasserver")) != null)
659 String nickname = null;
661 boolean seq=false,feat=true;
662 int pos = data.indexOf('=');
663 // determine capabilities
666 nickname = data.substring(0, pos);
668 url = data.substring(pos + 1);
669 if (url != null && (url.startsWith("http:") || url.startsWith("sequence:http:")))
671 if (nickname == null)
675 if (locsources == null)
683 locsources = locsources + nickname + "|" + url;
685 .println("NOTE! dasserver parameter not yet really supported (got args of "
686 + nickname + "|" + url);
689 source = new Vector();
691 source.addElement(nickname);
693 } // loop until no more server entries are found.
694 if (locsources != null && locsources.indexOf('|') > -1)
696 Cache.log.debug("Setting local source list in properties file to:\n"
698 Cache.setProperty(Cache.DAS_LOCAL_SOURCE, locsources);
700 while ((data = aparser.getValue("fetchfrom")) != null)
702 System.out.println("adding source '" + data + "'");
705 source = new Vector();
707 source.addElement(data);
713 * start a feature fetcher for every alignment frame
717 private static void startFeatureFetching(final Vector dasSources)
719 AlignFrame afs[] = Desktop.getAlignframes();
720 if (afs == null || afs.length == 0)
724 for (int i = 0; i < afs.length; i++)
726 final AlignFrame af = afs[i];
727 SwingUtilities.invokeLater(new Runnable()
732 af.featureSettings_actionPerformed(null);
733 af.featureSettings.fetchDasFeatures(dasSources);
739 private static String checkProtocol(String file)
741 String protocol = jalview.io.FormatAdapter.FILE;
743 if (file.indexOf("http:") > -1 || file.indexOf("file:") > -1)
745 protocol = jalview.io.FormatAdapter.URL;
752 * Notes: this argParser does not distinguish between parameter switches,
753 * parameter values and argument text. If an argument happens to be identical to
754 * a parameter, it will be taken as such (even though it didn't have a '-'
757 * @author Andrew Waterhouse and JBP documented.
764 public ArgsParser(String[] args)
766 vargs = new Vector();
767 for (int i = 0; i < args.length; i++)
769 String arg = args[i].trim();
770 if (arg.charAt(0) == '-')
772 arg = arg.substring(1);
774 vargs.addElement(arg);
779 * check for and remove first occurence of arg+parameter in arglist.
782 * @return return the argument following the given arg if arg was in list.
784 public String getValue(String arg)
786 int index = vargs.indexOf(arg);
790 ret = vargs.elementAt(index + 1).toString();
791 vargs.removeElementAt(index);
792 vargs.removeElementAt(index);
798 * check for and remove first occurence of arg in arglist.
801 * @return true if arg was present in argslist.
803 public boolean contains(String arg)
805 if (vargs.contains(arg))
807 vargs.removeElement(arg);
816 public String nextValue()
818 return vargs.remove(0).toString();