/* * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) * Copyright (C) $$Year-Rel$$ The Jalview Authors * * This file is part of Jalview. * * Jalview is free software: you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation, either version 3 * of the License, or (at your option) any later version. * * Jalview is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Jalview. If not, see . * The Jalview Authors are detailed in the 'AUTHORS' file. */ package jalview.bin; import jalview.api.AlignCalcWorkerI; import jalview.api.AlignFrameI; import jalview.api.AlignViewportI; import jalview.api.JalviewApp; import jalview.api.StructureSelectionManagerProvider; import jalview.bin.ApplicationSingletonProvider.ApplicationSingletonI; import jalview.datamodel.ColumnSelection; import jalview.datamodel.HiddenColumns; import jalview.datamodel.PDBEntry; import jalview.datamodel.SequenceGroup; import jalview.datamodel.SequenceI; import jalview.ext.so.SequenceOntology; import jalview.gui.AlignFrame; import jalview.gui.AlignViewport; import jalview.gui.AlignmentPanel; import jalview.gui.CalculationChooser; import jalview.gui.Desktop; import jalview.gui.Preferences; import jalview.gui.PromptUserConfig; import jalview.gui.StructureViewer; import jalview.io.AppletFormatAdapter; import jalview.io.BioJsHTMLOutput; import jalview.io.DataSourceType; import jalview.io.FileFormat; import jalview.io.FileFormatException; import jalview.io.FileFormatI; import jalview.io.FileFormats; import jalview.io.FileLoader; import jalview.io.HtmlSvgOutput; import jalview.io.IdentifyFile; import jalview.io.NewickFile; import jalview.io.gff.SequenceOntologyFactory; import jalview.javascript.JSFunctionExec; import jalview.javascript.MouseOverStructureListener; import jalview.renderer.seqfeatures.FeatureRenderer; import jalview.schemes.ColourSchemeI; import jalview.schemes.ColourSchemeProperty; import jalview.structure.SelectionSource; import jalview.structure.VamsasSource; import jalview.util.MessageManager; import jalview.util.Platform; import jalview.ws.jws2.Jws2Discoverer; import java.applet.AppletContext; import java.io.BufferedReader; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.security.AllPermission; import java.security.CodeSource; import java.security.PermissionCollection; import java.security.Permissions; import java.security.Policy; import java.util.HashMap; import java.util.Hashtable; import java.util.Map; import java.util.Vector; import javax.swing.LookAndFeel; import javax.swing.SwingUtilities; import javax.swing.UIManager; import groovy.lang.Binding; import groovy.util.GroovyScriptEngine; import netscape.javascript.JSObject; /** * Main class for Jalview Application
*
* start with: java -classpath "$PATH_TO_LIB$/*:$PATH_TO_CLASSES$" \ * jalview.bin.Jalview * * or on Windows: java -classpath "$PATH_TO_LIB$/*;$PATH_TO_CLASSES$" \ * jalview.bin.Jalview jalview.bin.Jalview * * (ensure -classpath arg is quoted to avoid shell expansion of '*' and do not * embellish '*' to e.g. '*.jar') * * @author $author$ * @version $Revision$ */ public class Jalview implements ApplicationSingletonI, JalviewJSApi { public static Jalview getInstance() { return (Jalview) ApplicationSingletonProvider .getInstance(Jalview.class); } private Jalview() { } static { Platform.getURLCommandArguments(); } private boolean headless; public static boolean isHeadlessMode() { return getInstance().headless; } private Desktop desktop; private AlignFrame currentAlignFrame; public boolean isJavaAppletTag; public String appletResourcePath; JalviewAppLoader appLoader; protected JSFunctionExec jsFunctionExec; private boolean noCalculation, noMenuBar, noStatus; private boolean noAnnotation; public static final String TERMINATOR_LINE = "Jalview argument parsing complete."; public boolean getStartCalculations() { return !noCalculation; } public boolean getAllowMenuBar() { return !noMenuBar; } public boolean getShowStatus() { return !noStatus; } public boolean getShowAnnotation() { return !noAnnotation; } public static AlignFrame getCurrentAlignFrame() { return getInstance().currentAlignFrame; } public static void setCurrentAlignFrame(AlignFrame currentAlignFrame) { getInstance().currentAlignFrame = currentAlignFrame; } static { if (!Platform.isJS()) /** * Java only * * @j2sIgnore */ { // grab all the rights we can for the JVM Policy.setPolicy(new Policy() { @Override public PermissionCollection getPermissions(CodeSource codesource) { Permissions perms = new Permissions(); perms.add(new AllPermission()); return (perms); } @Override public void refresh() { } }); } } /** * keep track of feature fetching tasks. * * @author JimP * */ class FeatureFetcher { /* * TODO: generalise to track all jalview events to orchestrate batch * processing events. */ private int queued = 0; private int running = 0; public FeatureFetcher() { } public void addFetcher(final AlignFrame af, final Vector dasSources) { final long id = System.currentTimeMillis(); queued++; final FeatureFetcher us = this; new Thread(new Runnable() { @Override public void run() { synchronized (us) { queued--; running++; } af.setProgressBar(MessageManager .getString("status.das_features_being_retrived"), id); af.featureSettings_actionPerformed(null); af.setProgressBar(null, id); synchronized (us) { running--; } } }).start(); } public synchronized boolean allFinished() { return queued == 0 && running == 0; } } /** * main class for Jalview application * * @param args * open filename */ public static void main(String[] args) { // Platform.startJavaLogging(); getInstance().doMain(args); } @SuppressWarnings("unused") /** * @param args */ void doMain(String[] args) { boolean isJS = Platform.isJS(); if (isJS) { Platform.setAppClass(this); } else { System.setSecurityManager(null); } System.out .println("Java version: " + System.getProperty("java.version")); System.out.println(System.getProperty("os.arch") + " " + System.getProperty("os.name") + " " + System.getProperty("os.version")); ArgsParser aparser = new ArgsParser(args); String usrPropsFile = aparser.getValue(ArgsParser.PROPS); Cache.loadProperties(usrPropsFile); if (aparser.contains(ArgsParser.NODISPLAY) || aparser.contains(ArgsParser.NOGUI) || aparser.contains(ArgsParser.HEADLESS) || "true".equals(System.getProperty("java.awt.headless"))) { headless = true; setSynchronous(true); } if (isJS) { isJavaAppletTag = aparser.isApplet(); if (isJavaAppletTag) { Preferences.setAppletDefaults(); Cache.loadProperties(usrPropsFile); // again, because we // might be changing defaults here? } System.out.println( " found: " + aparser.getValue("Info.j2sAppletID")); appletResourcePath = aparser.getValue("Info.resourcePath"); } else /** * Java only * * @j2sIgnore */ { if (usrPropsFile != null) { System.out.println( "CMD [-props " + usrPropsFile + "] executed successfully!"); } if (aparser.contains("help") || aparser.contains("h")) { showUsage(); System.exit(0); } // anything else! final String jabawsUrl = aparser.getValue(ArgsParser.JABAWS); if (jabawsUrl != null) { try { Jws2Discoverer.getInstance().setPreferredUrl(jabawsUrl); System.out.println( "CMD [-jabaws " + jabawsUrl + "] executed successfully!"); } catch (MalformedURLException e) { System.err.println( "Invalid jabaws parameter: " + jabawsUrl + " ignored"); } } } // check for property setting String defs = aparser.getValue(ArgsParser.SETPROP); while (defs != null) { int p = defs.indexOf('='); if (p == -1) { System.err.println("Ignoring invalid setprop argument : " + defs); } else { System.out.println("Executing setprop argument: " + defs); if (isJS) { Cache.setProperty(defs.substring(0, p), defs.substring(p + 1)); } } defs = aparser.getValue(ArgsParser.SETPROP); } System.setProperty("http.agent", "Jalview Desktop/" + Cache.getDefault("VERSION", "Unknown")); try { Cache.initLogger(); } catch (NoClassDefFoundError error) { error.printStackTrace(); System.out.println("\nEssential logging libraries not found." + "\nUse: java -classpath \"$PATH_TO_LIB$/*:$PATH_TO_CLASSES$\" jalview.bin.Jalview"); System.exit(0); } desktop = null; try { if (!isJS && Platform.isWin()) { UIManager.setLookAndFeel( headless ? "javax.swing.plaf.metal.MetalLookAndFeel" : UIManager.getSystemLookAndFeelClassName()); // UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } } catch (Exception ex) { System.err.println("Unexpected Look and Feel Exception"); ex.printStackTrace(); } if (Platform.isAMacAndNotJS()) { LookAndFeel lookAndFeel = ch.randelshofer.quaqua.QuaquaManager .getLookAndFeel(); System.setProperty("com.apple.mrj.application.apple.menu.about.name", "Jalview"); System.setProperty("apple.laf.useScreenMenuBar", "true"); if (lookAndFeel != null) { try { UIManager.setLookAndFeel(lookAndFeel); } catch (Throwable e) { System.err.println( "Failed to set QuaQua look and feel: " + e.toString()); } } if (lookAndFeel == null || !(lookAndFeel.getClass().isAssignableFrom( UIManager.getLookAndFeel().getClass())) || !UIManager.getLookAndFeel().getClass().toString() .toLowerCase().contains("quaqua")) { try { System.err.println( "Quaqua LaF not available on this plaform. Using VAqua(4).\nSee https://issues.jalview.org/browse/JAL-2976"); UIManager.setLookAndFeel("org.violetlib.aqua.AquaLookAndFeel"); } catch (Throwable e) { System.err.println( "Failed to reset look and feel: " + e.toString()); } } } /* * configure 'full' SO model if preferences say to, * else use the default (SO Lite) */ if (Cache.getDefault(Preferences.USE_FULL_SO, false)) { SequenceOntologyFactory.setSequenceOntology(new SequenceOntology()); } if (headless) { // If this is not tested, then if (aparser.contains(ArgsParser.NOUSAGESTATS)) { System.err.println("CMD [-nousagestats] executed successfully!"); } if (aparser.contains(ArgsParser.NOQUESTIONNAIRE)) { System.err.println("CMD [-noquestionnaire] executed successfully!"); } } else { desktop = Desktop.getInstance(); desktop.setInBatchMode(true); // indicate we are starting up desktop.setVisible(true); if (!isJS) /** * Java only * * @j2sIgnore */ { desktop.startServiceDiscovery(); if (!aparser.contains(ArgsParser.NOUSAGESTATS)) { startUsageStats(desktop); } else { System.err.println("CMD [-nousagestats] executed successfully!"); } if (!aparser.contains(ArgsParser.NOQUESTIONNAIRE)) { String url = aparser.getValue(ArgsParser.QUESTIONNAIRE); if (url != null) { // Start the desktop questionnaire prompter with the specified // questionnaire Cache.log.debug("Starting questionnaire url at " + url); desktop.checkForQuestionnaire(url); System.out.println("CMD questionnaire[-" + url + "] executed successfully!"); } else { if (Cache.getProperty(Preferences.NOQUESTIONNAIRES) == null) { // Start the desktop questionnaire prompter with the specified // questionnaire // String defurl = // "http://anaplog.compbio.dundee.ac.uk/cgi-bin/questionnaire.pl"; // // String defurl = "http://www.jalview.org/cgi-bin/questionnaire.pl"; Cache.log.debug( "Starting questionnaire with default url: " + defurl); desktop.checkForQuestionnaire(defurl); } } } else { System.err .println("CMD [-noquestionnaire] executed successfully!"); } if (!aparser.contains(ArgsParser.NONEWS)) { desktop.checkForNews(); } BioJsHTMLOutput.updateBioJS(); } } parseArguments(aparser, true); System.err.println(TERMINATOR_LINE); } /** * Allow an outside entity to initiate the second half of argument parsing * (only). * * @param args * @return null is good */ @Override public Object parseArguments(String[] args) { try { ArgsParser aparser = new ArgsParser(args); return parseArguments(aparser, false); } catch (Throwable t) { return t; } } /** * * @param aparser * @param isStartup * @return */ private Object parseArguments(ArgsParser aparser, boolean isStartup) { boolean isJS = Platform.isJS(); Desktop desktop = (headless ? null : Desktop.getInstance()); // script to execute after all loading is // completed one way or another // extract groovy argument and execute if necessary String groovyscript = (isJS ? null : aparser.getValue(ArgsParser.GROOVY, true)); String file = aparser.getValue(ArgsParser.OPEN, true); // BH this here to allow split frame; not working as of 5/17/2019 String file2 = aparser.getValue(ArgsParser.OPEN2, true); String fileFormat = (isJavaAppletTag ? aparser.getAppletValue("format", null) : null); FileFormatI format = null; DataSourceType protocol = null; if (file == null && desktop == null) { System.out.println("No files to open!"); System.exit(1); } boolean haveImport = false;// checkStartVamas(aparser); // Finally, deal with the remaining input data. long progress = -1; if (file == null && isJavaAppletTag) { // Maybe the sequences are added as parameters StringBuffer data = new StringBuffer("PASTE"); int i = 1; while ((file = aparser.getAppletValue("sequence" + i, null)) != null) { data.append(file.toString() + "\n"); i++; } if (data.length() > 5) { file = data.toString(); } } String data; if (file != null) { if (!headless) { desktop.setProgressBar( MessageManager .getString("status.processing_commandline_args"), progress = System.currentTimeMillis()); } if (!isJS) /** * ignore in JavaScript -- can't just check file existence - could load * it? * * @j2sIgnore */ { if (!file.startsWith("http://") && !file.startsWith("https://")) // BH 2019 added https check for Java { if (!(new File(file)).exists()) { System.out.println("Can't find " + file); if (headless) { System.exit(1); } } } } protocol = AppletFormatAdapter.checkProtocol(file); try { format = (isJavaAppletTag && fileFormat != null ? FileFormats.getInstance().forName(fileFormat) : null); if (format == null) { format = new IdentifyFile().identify(file, protocol); } } catch (FileFormatException e1) { // TODO ? } if (aparser.contains(ArgsParser.NOMENUBAR)) { noMenuBar = true; System.out.println("CMD [nomenu] executed successfully!"); } if (aparser.contains(ArgsParser.NOSTATUS)) { noStatus = true; System.out.println("CMD [nostatus] executed successfully!"); } if (aparser.contains(ArgsParser.NOANNOTATION) || aparser.contains(ArgsParser.NOANNOTATION2)) { noAnnotation = true; System.out.println("CMD no-annotation executed successfully!"); } if (aparser.contains(ArgsParser.NOCALCULATION)) { noCalculation = true; System.out.println("CMD [nocalculation] executed successfully!"); } AlignFrame af = new FileLoader(!headless).LoadFileWaitTillLoaded(file, protocol, format); if (af == null) { System.out.println("error"); } else { System.out .println("CMD [-open " + file + "] executed successfully!"); if (file2 != null) { protocol = AppletFormatAdapter.checkProtocol(file2); try { format = new IdentifyFile().identify(file2, protocol); } catch (FileFormatException e1) { // TODO ? } AlignFrame af2 = new FileLoader(!headless) .LoadFileWaitTillLoaded(file2, protocol, format); if (af2 == null) { System.out.println("error"); } else { AlignViewport.openLinkedAlignmentAs(af, af.getViewport().getAlignment(), af2.getViewport().getAlignment(), "", AlignViewport.SPLIT_FRAME); System.out.println( "CMD [-open2 " + file2 + "] executed successfully!"); } } setCurrentAlignFrame(af); // TODO: file2 How to implement file2 for the applet spit screen? data = aparser.getValue(ArgsParser.COLOUR, true); if (data != null) { data.replaceAll("%20", " "); ColourSchemeI cs = ColourSchemeProperty.getColourScheme( af.getViewport(), af.getViewport().getAlignment(), data); if (cs != null) { System.out.println( "CMD [-color " + data + "] executed successfully!"); } af.changeColour(cs); } // Must maintain ability to use the groups flag data = aparser.getValue(ArgsParser.GROUPS, true); if (data != null) { af.parseFeaturesFile(data, AppletFormatAdapter.checkProtocol(data)); // System.out.println("Added " + data); System.out.println( "CMD groups[-" + data + "] executed successfully!"); } data = aparser.getValue(ArgsParser.FEATURES, true); if (data != null) { af.parseFeaturesFile(data, AppletFormatAdapter.checkProtocol(data)); // System.out.println("Added " + data); System.out.println( "CMD [-features " + data + "] executed successfully!"); } data = aparser.getValue(ArgsParser.ANNOTATIONS, true); if (data != null) { af.loadJalviewDataFile(data, null, null, null); // System.out.println("Added " + data); System.out.println( "CMD [-annotations " + data + "] executed successfully!"); } if (aparser.contains(ArgsParser.SHOWOVERVIEW)) { af.overviewMenuItem_actionPerformed(null); System.out.println("CMD [showoverview] executed successfully!"); } // set or clear the sortbytree flag. if (aparser.contains(ArgsParser.SORTBYTREE)) { af.getViewport().setSortByTree(true); if (af.getViewport().getSortByTree()) { System.out.println("CMD [-sortbytree] executed successfully!"); } } boolean doUpdateAnnotation = false; /** * we do this earlier in JalviewJS because of a complication with * SHOWOVERVIEW * * For now, just fixing this in JalviewJS. * * * @j2sIgnore * */ { if (aparser.contains(ArgsParser.NOANNOTATION) || aparser.contains(ArgsParser.NOANNOTATION2)) { af.getViewport().setShowAnnotation(false); if (!af.getViewport().isShowAnnotation()) { doUpdateAnnotation = true; System.out .println("CMD no-annotation executed successfully!"); } } } if (aparser.contains(ArgsParser.NOSORTBYTREE)) { af.getViewport().setSortByTree(false); if (!af.getViewport().getSortByTree()) { doUpdateAnnotation = true; System.out .println("CMD [-nosortbytree] executed successfully!"); } } if (doUpdateAnnotation) { // BH 2019.07.24 af.setMenusForViewport(); af.alignPanel.updateLayout(); } data = aparser.getValue(ArgsParser.TREE, true); if (data != null) { try { System.out.println( "CMD [-tree " + data + "] executed successfully!"); NewickFile nf = new NewickFile(data, AppletFormatAdapter.checkProtocol(data)); af.getViewport() .setCurrentTree(af.showNewickTree(nf, data).getTree()); } catch (IOException ex) { System.err.println("Couldn't add tree " + data); ex.printStackTrace(System.err); } } // TODO - load PDB structure(s) to alignment JAL-629 // (associate with identical sequence in alignment, or a specified // sequence) if (isJavaAppletTag) { loadAppletParams(aparser, af); } else if (!isJS) /** * Java only * * @j2sIgnore */ { if (groovyscript != null) { // Execute the groovy script after we've done all the rendering // stuff // and before any images or figures are generated. System.out.println("Executing script " + groovyscript); executeGroovyScript(groovyscript, af); System.out.println("CMD groovy[" + groovyscript + "] executed successfully!"); groovyscript = null; } } createOutputFiles(aparser, af, format); while (aparser.getSize() > 0) { System.out.println("Unknown arg: " + aparser.nextValue()); } } } AlignFrame startUpAlframe = null; // We'll only open the default file if the desktop is visible. // And the user // //////////////////// if (!isJS && !headless && file == null && !haveImport && jalview.bin.Cache.getDefault("SHOW_STARTUP_FILE", true)) /** * Java only * * @j2sIgnore */ { file = jalview.bin.Cache.getDefault("STARTUP_FILE", jalview.bin.Cache.getDefault("www.jalview.org", "http://www.jalview.org") + "/examples/exampleFile_2_7.jar"); if (file.equals( "http://www.jalview.org/examples/exampleFile_2_3.jar")) { // hardwire upgrade of the startup file file.replace("_2_3.jar", "_2_7.jar"); // and remove the stale setting jalview.bin.Cache.removeProperty("STARTUP_FILE"); } protocol = DataSourceType.FILE; if (file.indexOf("http:") > -1) { protocol = DataSourceType.URL; } if (file.endsWith(".jar")) { format = FileFormat.Jalview; } else { try { format = new IdentifyFile().identify(file, protocol); } catch (FileFormatException e) { // TODO what? } } startUpAlframe = new FileLoader(!headless) .LoadFileWaitTillLoaded(file, protocol, format); // extract groovy arguments before anything else. } // Once all other stuff is done, execute any groovy scripts (in order) if (groovyscript != null) { if (Cache.groovyJarsPresent()) { System.out.println("Executing script " + groovyscript); executeGroovyScript(groovyscript, startUpAlframe); } else { System.err.println( "Sorry. Groovy Support is not available, so ignoring the provided groovy script " + groovyscript); } } // and finally, turn off batch mode indicator - if the desktop still exists if (desktop != null) { if (progress != -1) { desktop.setProgressBar(null, progress); } desktop.setInBatchMode(false); } return null; } /** * Writes an output file for each format (if any) specified in the * command-line arguments. Supported formats are currently *
    *
  • png
  • *
  • svg
  • *
  • html
  • *
  • biojsmsa
  • *
  • imgMap
  • *
  • eps
  • *
* A format parameter should be followed by a parameter specifying the output * file name. {@code imgMap} parameters should follow those for the * corresponding alignment image output. * * @param aparser * @param af * @param format */ private void createOutputFiles(ArgsParser aparser, AlignFrame af, FileFormatI format) { String imageName = "unnamed.png"; while (aparser.getSize() > 1) { String outputFormat = aparser.nextValue(); String file = aparser.nextValue(); // System.out.println("format " + outputFormat); if (outputFormat.equalsIgnoreCase("png")) { af.createPNG(new File(file)); imageName = (new File(file)).getName(); System.out.println("Creating PNG image: " + file); continue; } else if (outputFormat.equalsIgnoreCase("svg")) { File imageFile = new File(file); imageName = imageFile.getName(); af.createSVG(imageFile); System.out.println("Creating SVG image: " + file); continue; } else if (outputFormat.equalsIgnoreCase("html")) { File imageFile = new File(file); imageName = imageFile.getName(); HtmlSvgOutput htmlSVG = new HtmlSvgOutput(af.alignPanel); htmlSVG.exportHTML(file); System.out.println("Creating HTML image: " + file); continue; } else if (outputFormat.equalsIgnoreCase("biojsmsa")) { if (file == null) { System.err.println("The output html file must not be null"); return; } try { BioJsHTMLOutput.refreshVersionInfo( BioJsHTMLOutput.BJS_TEMPLATES_LOCAL_DIRECTORY); } catch (URISyntaxException e) { e.printStackTrace(); } BioJsHTMLOutput bjs = new BioJsHTMLOutput(af.alignPanel); bjs.exportHTML(file); System.out.println("Creating BioJS MSA Viwer HTML file: " + file); continue; } else if (outputFormat.equalsIgnoreCase("imgMap")) { af.createImageMap(new File(file), imageName); System.out.println("Creating image map: " + file); continue; } else if (outputFormat.equalsIgnoreCase("eps")) { File outputFile = new File(file); System.out.println( "Creating EPS file: " + outputFile.getAbsolutePath()); af.createEPS(outputFile); continue; } af.saveAlignment(file, format); if (af.isSaveAlignmentSuccessful()) { System.out.println( "Written alignment in " + format + " format to " + file); } else { System.out.println("Error writing file " + file + " in " + format + " format!!"); } } } private static void showUsage() { System.out.println( "Usage: jalview -open [FILE] [OUTPUT_FORMAT] [OUTPUT_FILE]\n\n" + "-nodisplay\tRun Jalview without User Interface.\n" + "-props FILE\tUse the given Jalview properties file instead of users default.\n" + "-colour COLOURSCHEME\tThe colourscheme to be applied to the alignment\n" + "-annotations FILE\tAdd precalculated annotations to the alignment.\n" + "-tree FILE\tLoad the given newick format tree file onto the alignment\n" + "-features FILE\tUse the given file to mark features on the alignment.\n" + "-fasta FILE\tCreate alignment file FILE in Fasta format.\n" + "-clustal FILE\tCreate alignment file FILE in Clustal format.\n" + "-pfam FILE\tCreate alignment file FILE in PFAM format.\n" + "-msf FILE\tCreate alignment file FILE in MSF format.\n" + "-pileup FILE\tCreate alignment file FILE in Pileup format\n" + "-pir FILE\tCreate alignment file FILE in PIR format.\n" + "-blc FILE\tCreate alignment file FILE in BLC format.\n" + "-json FILE\tCreate alignment file FILE in JSON format.\n" + "-jalview FILE\tCreate alignment file FILE in Jalview format.\n" + "-png FILE\tCreate PNG image FILE from alignment.\n" + "-svg FILE\tCreate SVG image FILE from alignment.\n" + "-html FILE\tCreate HTML file from alignment.\n" + "-biojsMSA FILE\tCreate BioJS MSA Viewer HTML file from alignment.\n" + "-imgMap FILE\tCreate HTML file FILE with image map of PNG image.\n" + "-eps FILE\tCreate EPS file FILE from alignment.\n" + "-questionnaire URL\tQueries the given URL for information about any Jalview user questionnaires.\n" + "-noquestionnaire\tTurn off questionnaire check.\n" + "-nonews\tTurn off check for Jalview news.\n" + "-nousagestats\tTurn off google analytics tracking for this session.\n" + "-sortbytree OR -nosortbytree\tEnable or disable sorting of the given alignment by the given tree\n" // + // "-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)" + "-jabaws URL\tSpecify URL for Jabaws services (e.g. for a local installation).\n" + "-fetchfrom nickname\tQuery nickname for features for the alignments and display them.\n" // + // "-vdoc vamsas-document\tImport vamsas document into new // session or join existing session with same URN\n" // + "-vses vamsas-session\tJoin session with given URN\n" + "-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" + "\n~Read documentation in Application or visit http://www.jalview.org for description of Features and Annotations file~\n\n"); } private static void startUsageStats(final Desktop desktop) { /** * start a User Config prompt asking if we can log usage statistics. */ PromptUserConfig prompter = new PromptUserConfig( Desktop.getDesktopPane(), "USAGESTATS", "Jalview Usage Statistics", "Do you want to help make Jalview better by enabling " + "the collection of usage statistics with Google Analytics ?" + "\n\n(you can enable or disable usage tracking in the preferences)", new Runnable() { @Override public void run() { Cache.log.debug( "Initialising googletracker for usage stats."); Cache.initGoogleTracker(); Cache.log.debug("Tracking enabled."); } }, new Runnable() { @Override public void run() { Cache.log.debug("Not enabling Google Tracking."); } }, null, true); desktop.addDialogThread(prompter); } /** * Locate the given string as a file and pass it to the groovy interpreter. * * @param groovyscript * the script to execute * @param jalviewContext * the Jalview Desktop object passed in to the groovy binding as the * 'Jalview' object. */ private void executeGroovyScript(String groovyscript, AlignFrame af) { /** * for scripts contained in files */ File tfile = null; /** * script's URI */ URL sfile = null; if (groovyscript.trim().equals("STDIN")) { // read from stdin into a tempfile and execute it try { tfile = File.createTempFile("jalview", "groovy"); PrintWriter outfile = new PrintWriter( new OutputStreamWriter(new FileOutputStream(tfile))); BufferedReader br = new BufferedReader( new InputStreamReader(System.in)); String line = null; while ((line = br.readLine()) != null) { outfile.write(line + "\n"); } br.close(); outfile.flush(); outfile.close(); } catch (Exception ex) { System.err.println("Failed to read from STDIN into tempfile " + ((tfile == null) ? "(tempfile wasn't created)" : tfile.toString())); ex.printStackTrace(); return; } try { sfile = tfile.toURI().toURL(); } catch (Exception x) { System.err.println( "Unexpected Malformed URL Exception for temporary file created from STDIN: " + tfile.toURI()); x.printStackTrace(); return; } } else { try { sfile = new URI(groovyscript).toURL(); } catch (Exception x) { tfile = new File(groovyscript); if (!tfile.exists()) { System.err.println("File '" + groovyscript + "' does not exist."); return; } if (!tfile.canRead()) { System.err.println("File '" + groovyscript + "' cannot be read."); return; } if (tfile.length() < 1) { System.err.println("File '" + groovyscript + "' is empty."); return; } try { sfile = tfile.getAbsoluteFile().toURI().toURL(); } catch (Exception ex) { System.err.println("Failed to create a file URL for " + tfile.getAbsoluteFile()); return; } } } try { Map vbinding = new HashMap<>(); vbinding.put("Jalview", this); if (af != null) { vbinding.put("currentAlFrame", af); } Binding gbinding = new Binding(vbinding); GroovyScriptEngine gse = new GroovyScriptEngine(new URL[] { sfile }); gse.run(sfile.toString(), gbinding); if ("STDIN".equals(groovyscript)) { // delete temp file that we made - // only if it was successfully executed tfile.delete(); } } catch (Exception e) { System.err.println("Exception Whilst trying to execute file " + sfile + " as a groovy script."); e.printStackTrace(System.err); } } public AlignFrame[] getAlignFrames() { return desktop == null ? new AlignFrame[] { getCurrentAlignFrame() } : Desktop.getAlignFrames(); } /** * Quit method delegates to Desktop.quit - unless running in headless mode * when it just ends the JVM */ public void quit() { if (jsFunctionExec != null) { jsFunctionExec.tidyUp(); jsFunctionExec = null; } if (desktop != null) { desktop.quit(); } else { System.exit(0); } } /** * Handle all JalviewLite applet parameters * * @param aparser * @param af */ private void loadAppletParams(ArgsParser aparser, AlignFrame af) { JalviewApp app = new JalviewApp() { // TODO BH 2019 // // These are methods that are in JalviewLite that various classes call // but are not in JalviewLiteJsApi. Or, even if they are, other classes // call // them to JalviewLite directly. Some may not be necessary, but they have // to // be at least mentioned here, or the classes calling them should // reference // JalviewLite itself. private boolean alignPDBStructures; // From JalviewLite; not implemented private Hashtable> jsmessages; private Hashtable jshashes; @Override public String getParameter(String name) { return aparser.getAppletValue(name, null); } @Override public boolean getDefaultParameter(String name, boolean def) { String stn; return ((stn = getParameter(name)) == null ? def : "true".equalsIgnoreCase(stn)); } /** * Get the applet-like document base even though this is an application. */ @Override public URL getDocumentBase() { return Platform.getDocumentBase(); } /** * Get the applet-like code base even though this is an application. */ @Override public URL getCodeBase() { return Platform.getCodeBase(); } @Override public AlignViewportI getViewport() { return af.getViewport(); } /** * features * */ @Override public boolean parseFeaturesFile(String filename, DataSourceType protocol) { return af.parseFeaturesFile(filename, protocol); } /** * scorefile * */ @Override public boolean loadScoreFile(String sScoreFile) throws IOException { af.loadJalviewDataFile(sScoreFile, null, null, null); return true; } /** * annotations, jpredfile, jnetfile * */ @Override public void updateForAnnotations() { af.updateForAnnotations(); } @Override public void loadTree(NewickFile fin, String treeFile) throws IOException { // n/a -- already done by standard Jalview command line processing } @Override public void setAlignPdbStructures(boolean defaultParameter) { alignPDBStructures = true; } @Override public void newStructureView(PDBEntry pdb, SequenceI[] seqs, String[] chains, DataSourceType protocol) { StructureViewer.launchStructureViewer(af.alignPanel, pdb, seqs); } @Override public void setFeatureGroupState(String[] groups, boolean state) { af.setFeatureGroupState(groups, state); } @Override public void alignedStructureView(PDBEntry[] pdb, SequenceI[][] seqs, String[][] chains, String[] protocols) { System.err.println( "Jalview applet interface alignedStructureView not implemented"); } @Override public void newFeatureSettings() { System.err.println( "Jalview applet interface newFeatureSettings not implemented"); } private Vector jsExecQueue; @Override public Vector getJsExecQueue(JSFunctionExec exec) { jsFunctionExec = exec; return (jsExecQueue == null ? (jsExecQueue = new Vector<>()) : jsExecQueue); } @Override public AppletContext getAppletContext() { // TODO Auto-generated method stub return null; } @Override public boolean isJsfallbackEnabled() { // TODO Auto-generated method stub return false; } @Override public JSObject getJSObject() { // TODO Auto-generated method stub return null; } @Override public StructureSelectionManagerProvider getStructureSelectionManagerProvider() { // TODO Q: what exactly is this? BH return null; } @Override public void updateColoursFromMouseOver(Object source, MouseOverStructureListener mouseOverStructureListener) { // TODO Auto-generated method stub } @Override public Object[] getSelectionForListener(SequenceGroup seqsel, ColumnSelection colsel, HiddenColumns hidden, SelectionSource source, Object alignFrame) { return appLoader.getSelectionForListener(getCurrentAlignFrame(), seqsel, colsel, hidden, source, alignFrame); } @Override public String arrayToSeparatorList(String[] array) { return appLoader.arrayToSeparatorList(array); } @Override public Hashtable getJSHashes() { return (jshashes == null ? (jshashes = new Hashtable<>()) : jshashes); } @Override public Hashtable> getJSMessages() { return (jsmessages == null ? (jsmessages = new Hashtable<>()) : jsmessages); } @Override public Object getFrameForSource(VamsasSource source) { if (source != null) { AlignFrame af; if (source instanceof jalview.gui.AlignViewport && source == (af = getCurrentAlignFrame()).getViewport()) { // should be valid if it just generated an event! return af; } // TODO: ensure that if '_af' is specified along with a handler // function, then only events from that alignFrame are sent to that // function } return null; } @Override public FeatureRenderer getNewFeatureRenderer(AlignViewportI vp) { return new jalview.gui.FeatureRenderer((AlignmentPanel) vp); } }; appLoader = new JalviewAppLoader(true); appLoader.load(app); } /** * * @see jalview.bin.JalviewLiteJsApi#getSelectedSequences() */ @Override public String getSelectedSequences() { return getSelectedSequencesFrom(getCurrentAlignFrame()); } /** * * @see jalview.bin.JalviewLiteJsApi#getSelectedSequences(java.lang.String) */ @Override public String getSelectedSequences(String sep) { return getSelectedSequencesFrom(getCurrentAlignFrame(), sep); } /** * * @see jalview.bin.JalviewLiteJsApi#getSelectedSequencesFrom(jalview.appletgui * .AlignFrame) */ @Override public String getSelectedSequencesFrom(AlignFrameI alf) { if (alf == null) { alf = getCurrentAlignFrame(); } return getSelectedSequencesFrom(alf, null); } /** * * @see jalview.bin.JalviewLiteJsApi#getSelectedSequencesFrom(jalview.appletgui * .AlignFrame, java.lang.String) */ @Override public String getSelectedSequencesFrom(AlignFrameI alf, String sep) { if (alf == null) { alf = getCurrentAlignFrame(); } return appLoader.getSelectedSequencesFrom(alf, sep); } /** * * @see jalview.bin.JalviewLiteJsApi#getSelectedSequencesFrom(jalview.appletgui * .AlignFrame, java.lang.String) */ @Override public void highlight(String sequenceId, String position, String alignedPosition) { highlightIn(null, sequenceId, position, alignedPosition); } @Override public void highlightIn(AlignFrameI alf, String sequenceId, String position, String alignedPosition) { if (alf == null) { alf = getCurrentAlignFrame(); } appLoader.highlightIn(alf, sequenceId, position, alignedPosition); } @Override public void select(String sequenceIds, String columns) { selectIn(getCurrentAlignFrame(), sequenceIds, columns, null); } @Override public void select(String sequenceIds, String columns, String sep) { selectIn(null, sequenceIds, columns, sep); } @Override public void selectIn(AlignFrameI alf, String sequenceIds, String columns) { selectIn(alf, sequenceIds, columns, null); } @Override public void selectIn(AlignFrameI alf, String sequenceIds, String columns, String sep) { if (alf == null) { alf = getCurrentAlignFrame(); } appLoader.selectIn(alf, sequenceIds, columns, sep); } @Override public String getSelectedSequencesAsAlignment(String format, String suffix) { return getSelectedSequencesAsAlignmentFrom(null, format, suffix); } @Override public String getSelectedSequencesAsAlignmentFrom(AlignFrameI alf, String format, String sep) { if (alf == null) { alf = getCurrentAlignFrame(); } return appLoader.getSelectedSequencesAsAlignmentFrom(alf, format, sep); } @Override public String getAlignmentOrder() { return getAlignmentFrom(getCurrentAlignFrame(), null); } @Override public String getAlignmentOrderFrom(AlignFrameI alf) { return getAlignmentFrom(alf, null); } @Override public String getAlignmentOrderFrom(AlignFrameI alf, String sep) { if (alf == null) { alf = getCurrentAlignFrame(); } return appLoader.getAlignmentOrderFrom(alf, sep); } @Override public String orderBy(String order, String undoName) { return orderBy(order, undoName, null); } @Override public String orderBy(String order, String undoName, String sep) { return orderAlignmentBy(getCurrentAlignFrame(), order, undoName, sep); } @Override public String orderAlignmentBy(AlignFrameI alf, String order, String undoName, String sep) { if (alf == null) { alf = getCurrentAlignFrame(); } return appLoader.orderAlignmentBy(alf, order, undoName, sep); } @Override public String getAlignment(String format) { return getAlignmentFrom(null, format, null); } @Override public String getAlignmentFrom(AlignFrameI alf, String format) { return getAlignmentFrom(alf, format, null); } @Override public String getAlignment(String format, String suffix) { return getAlignmentFrom(getCurrentAlignFrame(), format, suffix); } @Override public String getAlignmentFrom(AlignFrameI alf, String format, String suffix) { return appLoader.getAlignmentFrom(alf, format, suffix); } @Override public void loadAnnotation(String annotation) { loadAnnotationFrom(getCurrentAlignFrame(), annotation); } @Override public void loadAnnotationFrom(AlignFrameI alf, String annotation) { if (alf == null) { alf = getCurrentAlignFrame(); } appLoader.loadAnnotationFrom(alf, annotation); } @Override public void loadFeatures(String features, boolean autoenabledisplay) { loadFeaturesFrom(currentAlignFrame, features, autoenabledisplay); } @Override public boolean loadFeaturesFrom(AlignFrameI alf, String features, boolean autoenabledisplay) { if (alf == null) { alf = getCurrentAlignFrame(); } return appLoader.loadFeaturesFrom(alf, features, autoenabledisplay); } @Override public String getFeatures(String format) { return getFeaturesFrom(null, format); } @Override public String getFeaturesFrom(AlignFrameI alf, String format) { if (alf == null) { alf = getCurrentAlignFrame(); } return appLoader.getFeaturesFrom(alf, format, true, false); } @Override public String getAnnotation() { return getAnnotationFrom(null); } @Override public String getAnnotationFrom(AlignFrameI alf) { if (alf == null) { alf = getCurrentAlignFrame(); } return appLoader.getAnnotationFrom(alf); } @Override public AlignFrameI newView() { return newViewFrom(null, null); } @Override public AlignFrameI newView(String name) { return newViewFrom(null, name); } @Override public AlignFrameI newViewFrom(AlignFrameI alf) { return newViewFrom(alf, null); } @Override public AlignFrameI newViewFrom(AlignFrameI alf, String name) { if (alf == null) { alf = getCurrentAlignFrame(); } return appLoader.newViewFrom(alf, name); } @Override public AlignFrameI loadAlignment(String text, String title) { return appLoader.loadAlignment(text, AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT, title); } @Override public boolean addPdbFile(AlignFrameI alFrame, String sequenceId, String pdbEntryString, String pdbFile) { if (alFrame == null) { alFrame = getCurrentAlignFrame(); } return appLoader.addPdbFile(alFrame, sequenceId, pdbEntryString, pdbFile); } @Override public void scrollViewToIn(AlignFrameI alf, String topRow, String leftHandColumn) { if (alf == null) { alf = getCurrentAlignFrame(); } appLoader.scrollViewToIn(alf, topRow, leftHandColumn); } @Override public void scrollViewToRowIn(AlignFrameI alf, String topRow) { if (alf == null) { alf = getCurrentAlignFrame(); } appLoader.scrollViewToRowIn(alf, topRow); } @Override public void scrollViewToColumnIn(AlignFrameI alf, String leftHandColumn) { if (alf == null) { alf = getCurrentAlignFrame(); } appLoader.scrollViewToColumnIn(alf, leftHandColumn); } @Override public String getFeatureGroups() { return getFeatureGroupsOn(null); } @Override public String getFeatureGroupsOn(AlignFrameI alf) { if (alf == null) { alf = getCurrentAlignFrame(); } return appLoader.getFeatureGroupsOn(alf); } @Override public String getFeatureGroupsOfState(boolean visible) { return getFeatureGroupsOfStateOn(null, visible); } @Override public String getFeatureGroupsOfStateOn(AlignFrameI alf, boolean visible) { if (alf == null) { alf = getCurrentAlignFrame(); } return appLoader.getFeatureGroupsOfStateOn(alf, visible); } @Override public void setFeatureGroupState(String groups, boolean state) { // JalviewLite API setFeatureGroupStateOn(null, groups, state); } @Override public void setFeatureGroupStateOn(AlignFrameI alf, String groups, boolean state) { if (alf == null) { alf = getCurrentAlignFrame(); } appLoader.setFeatureGroupStateOn(alf, groups, state); } @Override public String getSeparator() { return appLoader.getSeparator(); } @Override public void setSeparator(String separator) { appLoader.setSeparator(separator); } @Override public String getJsMessage(String messageclass, String viewId) { // see http://www.jalview.org/examples/jalviewLiteJs.html return null; } /** * Open a new Tree panel on the desktop statically. Params are standard (not * set by Groovy). No dialog is opened. * * @param af * @param treeType * @param modelName * @return null, or the string "label.you_need_at_least_n_sequences" if number * of sequences selected is inappropriate */ @Override public Object openTreePanel(AlignFrame af, String treeType, String modelName) { // JalviewJS api if (af == null) { af = getCurrentAlignFrame(); } return CalculationChooser.openTreePanel(af, treeType, modelName, null); } /** * public static method for JalviewJS API to open a PCAPanel without * necessarily using a dialog. * * @param af * @param modelName * @return the PCAPanel, or the string "label.you_need_at_least_n_sequences" * if number of sequences selected is inappropriate */ @Override public Object openPcaPanel(AlignFrame af, String modelName) { if (af == null) { af = getCurrentAlignFrame(); } return CalculationChooser.openPcaPanel(af, modelName, null); } @Override public String getSelectedSequencesAsAlignment(String format, boolean suffix) { return getSelectedSequencesAsAlignmentFrom(null, format, suffix); } @Override public String getSelectedSequencesAsAlignmentFrom(AlignFrameI alf, String format, boolean suffix) { if (alf == null) { alf = getCurrentAlignFrame(); } return appLoader.getSelectedSequencesAsAlignmentFrom(alf, format, "" + suffix); } @Override public String arrayToSeparatorList(String[] array) { return appLoader.arrayToSeparatorList(array); } @Override public String[] separatorListToArray(String list) { return appLoader.separatorListToArray(list); } //// probably not needed in JalviewJS -- From when Jmol and Jalview did not //// have a direct connection? @Override public void setMouseoverListener(String listener) { // TODO Auto-generated method stub } @Override public void setMouseoverListener(AlignFrameI af, String listener) { // TODO Auto-generated method stub } @Override public void setSelectionListener(String listener) { // TODO Auto-generated method stub } @Override public void setSelectionListener(AlignFrameI af, String listener) { // TODO Auto-generated method stub } @Override public void setStructureListener(String listener, String modelSet) { // TODO Auto-generated method stub } @Override public void removeJavascriptListener(AlignFrameI af, String listener) { // TODO Auto-generated method stub } @Override public void mouseOverStructure(String pdbResNum, String chain, String pdbfile) { // TODO Auto-generated method stub } @Override public void showOverview() { currentAlignFrame.overviewMenuItem_actionPerformed(null); } public void notifyWorker(AlignCalcWorkerI worker, String status) { // System.out.println("Jalview worker " + worker.getClass().getSimpleName() // + " " + status); } /** * flag to allow selected Runnable and Thread processes to run synchronously * * JAL-3563 * */ private static boolean isSynchronous = false; /** * Set Jalview to run selected processes synchronously in test and headless * environments. * * JAL-3563 * * @param b * @author Bob Hanson */ public static void setSynchronous(boolean b) { isSynchronous = b; } /** * Allows optional synchronous running of a Runnable that would otherwise use * SwingUtilities.invokeLater. * * JAL-3563 * * @param t * @author Bob Hanson */ public static boolean isSynchronous() { return isSynchronous; } /** * Allows optional synchronous running of a Runnable that would otherwise use * SwingUtilities.invokeLater. * * JAL-3563 * * @param t * @author Bob Hanson */ public static void execRunnable(Runnable r) { if (isSynchronous()) { r.run(); } else { SwingUtilities.invokeLater(r); } } /** * Allows optional synchronous running of a thread that would otherwise be run * using start(). * * JAL-3563 * * @param t * @author Bob Hanson */ public static void execThread(Thread t) { if (isSynchronous()) { t.run(); } else { t.start(); } } /** * Get the SwingJS applet ID and combine that with the frameType * * @param frameType * "alignment", "desktop", etc., or null * @return */ public static String getAppID(String frameType) { String id = Cache.getProperty("Info.j2sAppletID"); if (id == null) { id = "jalview"; } return id + (frameType == null ? "" : "-" + frameType); } }