From: hansonr Date: Mon, 13 May 2019 02:17:12 +0000 (-0500) Subject: JalviewAppLoader for moving code from JalviewLite relating to applet X-Git-Url: http://source.jalview.org/gitweb/?a=commitdiff_plain;h=4b0220906ff60a04786c3f3eb95fa306407f27c7;p=jalview.git JalviewAppLoader for moving code from JalviewLite relating to applet parameters --- diff --git a/src/jalview/api/JalviewApp.java b/src/jalview/api/JalviewApp.java new file mode 100644 index 0000000..1d67bc2 --- /dev/null +++ b/src/jalview/api/JalviewApp.java @@ -0,0 +1,43 @@ +package jalview.api; + +import jalview.datamodel.PDBEntry; +import jalview.datamodel.SequenceI; +import jalview.io.DataSourceType; +import jalview.io.NewickFile; + +import java.io.IOException; +import java.net.URL; + +public interface JalviewApp +{ + public String getParameter(String name); + + public boolean getDefaultParameter(String name, boolean def); + + public URL getDocumentBase(); + + public URL getCodeBase(); + + public void setAlignPdbStructures(boolean defaultParameter); + + public void newStructureView(PDBEntry pdb, SequenceI[] seqs, + String[] chains, DataSourceType protocol); + + public void alignedStructureView(PDBEntry[] pdb, SequenceI[][] seqs, + String[][] chains, String[] protocols); + + public void updateForLoader(); + + public AlignViewportI getViewport(); + + public void setFeatureGroupState(String[] groups, boolean state); + + public boolean parseFeaturesFile(String param, DataSourceType protocol); + + public void newFeatureSettings(); + + public boolean loadScoreFile(String sScoreFile) throws IOException; + + public void loadTree(NewickFile fin, String treeFile) throws IOException; + +} diff --git a/src/jalview/bin/Cache.java b/src/jalview/bin/Cache.java index fd382b3..086419b 100755 --- a/src/jalview/bin/Cache.java +++ b/src/jalview/bin/Cache.java @@ -297,8 +297,7 @@ public class Cache }; /** Default file is ~/.jalview_properties */ - // BH 2019.05.07 note: Instances of Jalview will share this file. - static String propertiesFile; + private String propertiesFile; /** * flag to possibly allow properties to be written to a property file @@ -624,18 +623,7 @@ public class Cache */ public static String getProperty(String key) { - return getInstance().getPropertyImpl(key); - } - - private String getPropertyImpl(String key) - { - String prop = applicationProperties.getProperty(key); - if (prop == null && Platform.isJS()) - { - prop = applicationProperties.getProperty(Platform.getUniqueAppletID() - + "_" + JS_PROPERTY_PREFIX + key); - } - return prop; + return getInstance().applicationProperties.getProperty(key); } /** diff --git a/src/jalview/bin/Jalview.java b/src/jalview/bin/Jalview.java index 4167753..cb2b469 100755 --- a/src/jalview/bin/Jalview.java +++ b/src/jalview/bin/Jalview.java @@ -20,9 +20,14 @@ */ package jalview.bin; +import jalview.api.AlignViewportI; +import jalview.api.JalviewApp; +import jalview.datamodel.PDBEntry; +import jalview.datamodel.SequenceI; import jalview.ext.so.SequenceOntology; import jalview.gui.AlignFrame; import jalview.gui.Desktop; +import jalview.gui.Preferences; import jalview.gui.PromptUserConfig; import jalview.io.AppletFormatAdapter; import jalview.io.BioJsHTMLOutput; @@ -115,6 +120,10 @@ public class Jalview private AlignFrame currentAlignFrame; + public boolean isJavaAppletTag; + + public String appletResourcePath; + public static AlignFrame getCurrentAlignFrame() { return getInstance().currentAlignFrame; @@ -285,19 +294,32 @@ public class Jalview String usrPropsFile = aparser.getValue(ArgsParser.PROPS); Cache.loadProperties(usrPropsFile); - if (usrPropsFile != null) + if (Platform.isJS()) { + isJavaAppletTag = aparser.isApplet(); + if (isJavaAppletTag) + { + Preferences.setAppletDefaults(); + Cache.loadProperties(usrPropsFile); // again, because we + // might be changing defaults here? + } System.out.println( - "CMD [-props " + usrPropsFile + "] executed successfully!"); + " found: " + aparser.getValue("Info.j2sAppletID")); + appletResourcePath = aparser.getValue("Info.resourcePath"); } - - if (!Platform.isJS()) + else /** * Java only * * @j2sIgnore */ { + if (usrPropsFile != null) + { + System.out.println( + "CMD [-props " + usrPropsFile + "] executed successfully!"); + } + if (aparser.contains("help") || aparser.contains("h")) { showUsage(); @@ -740,94 +762,103 @@ public class Jalview + "] executed successfully!"); groovyscript = null; } - String imageName = "unnamed.png"; - while (aparser.getSize() > 1) + + if (isJavaAppletTag) + { + loadAppletParams(aparser, af); + } + else { - // PNG filename - // SVG filename - // HTML filename - // biojsmsa filename - String outputFormat = aparser.nextValue(); - file = aparser.nextValue(); - - 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")) + String imageName = "unnamed.png"; + while (aparser.getSize() > 1) { - if (file == null) + // PNG filename + // SVG filename + // HTML filename + // biojsmsa filename + String outputFormat = aparser.nextValue(); + file = aparser.nextValue(); + + if (outputFormat.equalsIgnoreCase("png")) { - System.err.println("The output html file must not be null"); - return; + af.createPNG(new File(file)); + imageName = (new File(file)).getName(); + System.out.println("Creating PNG image: " + file); + continue; } - try + else if (outputFormat.equalsIgnoreCase("svg")) { - BioJsHTMLOutput.refreshVersionInfo( - BioJsHTMLOutput.BJS_TEMPLATES_LOCAL_DIRECTORY); - } catch (URISyntaxException e) + File imageFile = new File(file); + imageName = imageFile.getName(); + af.createSVG(imageFile); + System.out.println("Creating SVG image: " + file); + continue; + } + else if (outputFormat.equalsIgnoreCase("html")) { - e.printStackTrace(); + 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!!"); } - 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 + + while (aparser.getSize() > 0) { - System.out.println("Error writing file " + file + " in " - + format + " format!!"); + System.out.println("Unknown arg: " + aparser.nextValue()); } - - } - - while (aparser.getSize() > 0) - { - System.out.println("Unknown arg: " + aparser.nextValue()); } } } @@ -1129,4 +1160,132 @@ public class Jalview } } + /** + * 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); + } + + private void loadAppletParams(ArgsParser aparser, AlignFrame af) + { + Jalview me = this; + JalviewApp app = new JalviewApp() + { + + + @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)); + } + + @Override + public URL getDocumentBase() + { + return Platform.getDocumentBase(); + } + + @Override + public URL getCodeBase() + { + return Platform.getCodeBase(); + } + + @Override + public AlignViewportI getViewport() + { + return Jalview.getCurrentAlignFrame().getViewport(); + } + + @Override + public boolean loadScoreFile(String sScoreFile) throws IOException + { + Jalview.getCurrentAlignFrame().loadJalviewDataFile(sScoreFile, null, + null, null); + return true; + } + + @Override + public boolean parseFeaturesFile(String filename, + DataSourceType protocol) + { + return af.parseFeaturesFile(filename, protocol); + } + + @Override + public void loadTree(NewickFile fin, String treeFile) + throws IOException + { + // n/a -- already done + } + + @Override + public void setAlignPdbStructures(boolean defaultParameter) + { + // TODO Auto-generated method stub + + } + + @Override + public void newStructureView(PDBEntry pdb, SequenceI[] seqs, + String[] chains, DataSourceType protocol) + { + // TODO Auto-generated method stub + + } + + @Override + public void alignedStructureView(PDBEntry[] pdb, SequenceI[][] seqs, + String[][] chains, String[] protocols) + { + // TODO Auto-generated method stub + + } + + @Override + public void updateForLoader() + { + // TODO Auto-generated method stub + + } + + @Override + public void setFeatureGroupState(String[] groups, boolean state) + { + // TODO Auto-generated method stub + + } + + @Override + public void newFeatureSettings() + { + // TODO Auto-generated method stub + + } + + }; + + new JalviewAppLoader(true).load(app); + + } + } diff --git a/src/jalview/bin/JalviewAppLoader.java b/src/jalview/bin/JalviewAppLoader.java new file mode 100644 index 0000000..5d60cf9 --- /dev/null +++ b/src/jalview/bin/JalviewAppLoader.java @@ -0,0 +1,653 @@ +package jalview.bin; + +import jalview.api.JalviewApp; +import jalview.api.StructureSelectionManagerProvider; +import jalview.datamodel.PDBEntry; +import jalview.datamodel.Sequence; +import jalview.datamodel.SequenceI; +import jalview.io.AnnotationFile; +import jalview.io.DataSourceType; +import jalview.io.JPredFile; +import jalview.io.JnetAnnotationMaker; +import jalview.io.NewickFile; +import jalview.structure.StructureSelectionManager; +import jalview.util.HttpUtils; +import jalview.util.MessageManager; + +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; +import java.util.Vector; + +/** + * A class to load parameters for either JalviewLite or Jalview + * + * @author hansonr + * + */ +public class JalviewAppLoader +{ + + private JalviewApp app; + + private boolean debug; + + private String separator; + + public JalviewAppLoader(boolean debug) + { + this.debug = debug; + } + + public void load(JalviewApp app) + { + + this.app = app; + + String sep = app.getParameter("separator"); + if (sep != null) + { + if (sep.length() > 0) + { + separator = sep; + } + else + { + throw new Error(MessageManager + .getString("error.invalid_separator_parameter")); + } + } + + loadTree(); + loadScoreFile(); + loadFeatures(); + loadAnnotations(); + loadJnetFile(); + loadPdbFiles(); + } + + /** + * Load PDBFiles if any specified by parameter(s). Returns true if loaded, + * else false. + * + * @param loaderFrame + * @return + */ + protected boolean loadPdbFiles() + { + boolean result = false; + /* + * Undocumented for 2.6 - + * related to JAL-434 + */ + + boolean doAlign = app.getDefaultParameter("alignpdbfiles", false); + app.setAlignPdbStructures(doAlign); + /* + * + * + * + * + * + */ + + int pdbFileCount = 0; + // Accumulate pdbs here if they are heading for the same view (if + // alignPdbStructures is true) + Vector pdbs = new Vector<>(); + // create a lazy matcher if we're asked to + jalview.analysis.SequenceIdMatcher matcher = (app + .getDefaultParameter("relaxedidmatch", false)) + ? new jalview.analysis.SequenceIdMatcher( + app.getViewport().getAlignment() + .getSequencesArray()) + : null; + + String param; + do + { + if (pdbFileCount > 0) + { + param = app.getParameter("PDBFILE" + pdbFileCount); + } + else + { + param = app.getParameter("PDBFILE"); + } + + if (param != null) + { + PDBEntry pdb = new PDBEntry(); + + String seqstring; + SequenceI[] seqs = null; + String[] chains = null; + + StringTokenizer st = new StringTokenizer(param, " "); + + if (st.countTokens() < 2) + { + String sequence = app.getParameter("PDBSEQ"); + if (sequence != null) + { + seqs = new SequenceI[] { matcher == null + ? (Sequence) app.getViewport().getAlignment() + .findName(sequence) + : matcher.findIdMatch(sequence) }; + } + + } + else + { + param = st.nextToken(); + List tmp = new ArrayList<>(); + List tmp2 = new ArrayList<>(); + + while (st.hasMoreTokens()) + { + seqstring = st.nextToken(); + StringTokenizer st2 = new StringTokenizer(seqstring, "="); + if (st2.countTokens() > 1) + { + // This is the chain + tmp2.add(st2.nextToken()); + seqstring = st2.nextToken(); + } + tmp.add(matcher == null + ? (Sequence) app.getViewport().getAlignment() + .findName(seqstring) + : matcher.findIdMatch(seqstring)); + } + + seqs = tmp.toArray(new SequenceI[tmp.size()]); + if (tmp2.size() == tmp.size()) + { + chains = tmp2.toArray(new String[tmp2.size()]); + } + } + ret[0] = param; + DataSourceType protocol = resolveFileProtocol(app, + ret); + // TODO check JAL-357 for files in a jar (CLASSLOADER) + pdb.setFile(ret[0]); + + if (seqs != null) + { + for (int i = 0; i < seqs.length; i++) + { + if (seqs[i] != null) + { + ((Sequence) seqs[i]).addPDBId(pdb); + StructureSelectionManager + .getStructureSelectionManager( + (StructureSelectionManagerProvider) app) + .registerPDBEntry(pdb); + } + else + { + if (debug) + { + // this may not really be a problem but we give a warning + // anyway + System.err.println( + "Warning: Possible input parsing error: Null sequence for attachment of PDB (sequence " + + i + ")"); + } + } + } + + if (doAlign) + { + pdbs.addElement(new Object[] { pdb, seqs, chains, protocol }); + } + else + { + app.newStructureView(pdb, seqs, chains, protocol); + } + } + } + + pdbFileCount++; + } while (param != null || pdbFileCount < 10); + if (pdbs.size() > 0) + { + SequenceI[][] seqs = new SequenceI[pdbs.size()][]; + PDBEntry[] pdb = new PDBEntry[pdbs.size()]; + String[][] chains = new String[pdbs.size()][]; + String[] protocols = new String[pdbs.size()]; + for (int pdbsi = 0, pdbsiSize = pdbs + .size(); pdbsi < pdbsiSize; pdbsi++) + { + Object[] o = pdbs.elementAt(pdbsi); + pdb[pdbsi] = (PDBEntry) o[0]; + seqs[pdbsi] = (SequenceI[]) o[1]; + chains[pdbsi] = (String[]) o[2]; + protocols[pdbsi] = (String) o[3]; + } + app.alignedStructureView(pdb, seqs, chains, protocols); + result = true; + } + return result; + } + + /** + * Load in a Jnetfile if specified by parameter. Returns true if loaded, else + * false. + * + * @param alignFrame + * @return + */ + protected boolean loadJnetFile() + { + boolean result = false; + String param = app.getParameter("jnetfile"); + if (param == null) + { + // jnet became jpred around 2016 + param = app.getParameter("jpredfile"); + } + if (param != null) + { + try + { + ret[0] = param; + DataSourceType protocol = resolveFileProtocol(app, + ret); + JPredFile predictions = new JPredFile(ret[0], protocol); + JnetAnnotationMaker.add_annotation(predictions, + app.getViewport().getAlignment(), 0, false); + // false == do not add sequence profile from concise output + app.getViewport().getAlignment().setupJPredAlignment(); + app.updateForLoader(); + result = true; + } catch (Exception ex) + { + ex.printStackTrace(); + } + } + return result; + } + + /** + * Load annotations if specified by parameter. Returns true if loaded, else + * false. + * + * @param alignFrame + * @return + */ + protected boolean loadAnnotations() + { + boolean result = false; + String param = app.getParameter("annotations"); + if (param != null) + { + ret[0] = param; + DataSourceType protocol = resolveFileProtocol(app, + ret); + param = ret[0]; + if (new AnnotationFile().annotateAlignmentView(app.getViewport(), + param, protocol)) + { + app.updateForLoader(); + result = true; + } + else + { + System.err + .println("Annotations were not added from annotation file '" + + param + "'"); + } + } + return result; + } + + /** + * Load features file and view settings as specified by parameters. Returns + * true if features were loaded, else false. + * + * @param alignFrame + * @return + */ + protected boolean loadFeatures() + { + boolean result = false; + // /////////////////////////// + // modify display of features + // we do this before any features have been loaded, ensuring any hidden + // groups are hidden when features first displayed + // + // hide specific groups + // + String param = app.getParameter("hidefeaturegroups"); + if (param != null) + { + app.setFeatureGroupState( + separatorListToArray(param, separator), false); + // app.setFeatureGroupStateOn(newAlignFrame, param, false); + } + // show specific groups + param = app.getParameter("showfeaturegroups"); + if (param != null) + { + app.setFeatureGroupState(separatorListToArray(param, separator), + true); + // app.setFeatureGroupStateOn(newAlignFrame, param, true); + } + // and now load features + param = app.getParameter("features"); + if (param != null) + { + ret[0] = param; + DataSourceType protocol = resolveFileProtocol(app, + ret); + + result = app.parseFeaturesFile(param, protocol); + } + + param = app.getParameter("showFeatureSettings"); + if (param != null && param.equalsIgnoreCase("true")) + { + app.newFeatureSettings(); + } + return result; + } + + /** + * Load a score file if specified by parameter. Returns true if file was + * loaded, else false. + * + * @param loaderFrame + */ + protected boolean loadScoreFile() + { + boolean result = false; + String sScoreFile = app.getParameter("scoreFile"); + if (sScoreFile != null && !"".equals(sScoreFile)) + { + try + { + if (debug) + { + System.err.println( + "Attempting to load T-COFFEE score file from the scoreFile parameter"); + } + result = app.loadScoreFile(sScoreFile); + if (!result) + { + System.err.println( + "Failed to parse T-COFFEE parameter as a valid score file ('" + + sScoreFile + "')"); + } + } catch (Exception e) + { + System.err.printf("Cannot read score file: '%s'. Cause: %s \n", + sScoreFile, e.getMessage()); + } + } + return result; + } + + String[] ret = new String[1]; + /** + * Load a tree for the alignment if specified by parameter. Returns true if a + * tree was loaded, else false. + * + * @param loaderFrame + * @return + */ + protected boolean loadTree() + { + boolean result = false; + String treeFile = app.getParameter("tree"); + if (treeFile == null) + { + treeFile = app.getParameter("treeFile"); + } + + if (treeFile != null) + { + try + { + ret[0] = treeFile; + NewickFile fin = new NewickFile(treeFile, + resolveFileProtocol(app, ret)); + fin.parse(); + + if (fin.getTree() != null) + { + app.loadTree(fin, ret[0]); + result = true; + if (debug) + { + System.out.println("Successfully imported tree."); + } + } + else + { + if (debug) + { + System.out.println("Tree parameter did not resolve to a valid tree."); + } + } + } catch (Exception ex) + { + ex.printStackTrace(); + } + } + return result; + } + + /** + * form a complete URL given a path to a resource and a reference location on + * the same server + * + * @param targetPath + * - an absolute path on the same server as localref or a document + * located relative to localref + * @param localref + * - a URL on the same server as url + * @return a complete URL for the resource located by url + */ + public static String resolveUrlForLocalOrAbsolute(String targetPath, + URL localref) + { + String resolvedPath = ""; + if (targetPath.startsWith("/")) + { + String codebase = localref.toString(); + String localfile = localref.getFile(); + resolvedPath = codebase.substring(0, + codebase.length() - localfile.length()) + targetPath; + return resolvedPath; + } + + /* + * get URL path and strip off any trailing file e.g. + * www.jalview.org/examples/index.html#applets?a=b is trimmed to + * www.jalview.org/examples/ + */ + String urlPath = localref.toString(); + String directoryPath = urlPath; + int lastSeparator = directoryPath.lastIndexOf("/"); + if (lastSeparator > 0) + { + directoryPath = directoryPath.substring(0, lastSeparator + 1); + } + + if (targetPath.startsWith("/")) + { + /* + * construct absolute URL to a file on the server - this is not allowed? + */ + // String localfile = localref.getFile(); + // resolvedPath = urlPath.substring(0, + // urlPath.length() - localfile.length()) + // + targetPath; + resolvedPath = directoryPath + targetPath.substring(1); + } + else + { + resolvedPath = directoryPath + targetPath; + } + if (JalviewLite.debug) + { + System.err.println( + "resolveUrlForLocalOrAbsolute returning " + resolvedPath); + } + return resolvedPath; + } + + /** + * parse the string into a list + * + * @param list + * @param separator + * @return elements separated by separator + */ + public static String[] separatorListToArray(String list, String separator) + { + // TODO use StringUtils version (slightly different...) + int seplen = separator.length(); + if (list == null || list.equals("") || list.equals(separator)) + { + return null; + } + Vector jv = new Vector<>(); + int cp = 0, pos; + while ((pos = list.indexOf(separator, cp)) > cp) + { + jv.addElement(list.substring(cp, pos)); + cp = pos + seplen; + } + if (cp < list.length()) + { + String c = list.substring(cp); + if (!c.equals(separator)) + { + jv.addElement(c); + } + } + if (jv.size() > 0) + { + String[] v = new String[jv.size()]; + for (int i = 0; i < v.length; i++) + { + v[i] = jv.elementAt(i); + } + jv.removeAllElements(); + // if (debug) + // { + // System.err.println("Array from '" + separator + // + "' separated List:\n" + v.length); + // for (int i = 0; i < v.length; i++) + // { + // System.err.println("item " + i + " '" + v[i] + "'"); + // } + // } + return v; + } + // if (debug) + // { + // System.err.println( + // "Empty Array from '" + separator + "' separated List"); + // } + return null; + } + + public static DataSourceType resolveFileProtocol(JalviewApp app, + String[] retPath) + { + String path = retPath[0]; + /* + * is it paste data? + */ + if (path.startsWith("PASTE")) + { + retPath[0] = path.substring(5); + return DataSourceType.PASTE; + } + + /* + * is it a URL? + */ + if (path.indexOf("://") >= 0) + { + return DataSourceType.URL; + } + + /* + * try relative to document root + */ + URL documentBase = app.getDocumentBase(); + String withDocBase = resolveUrlForLocalOrAbsolute(path, + documentBase); + if (HttpUtils.isValidUrl(withDocBase)) + { + // if (debug) + // { + // System.err.println("Prepended document base '" + documentBase + // + "' to make: '" + withDocBase + "'"); + // } + retPath[0] = withDocBase; + return DataSourceType.URL; + } + + /* + * try relative to codebase (if different to document base) + */ + URL codeBase = app.getCodeBase(); + String withCodeBase = resolveUrlForLocalOrAbsolute(path, + codeBase); + if (!withCodeBase.equals(withDocBase) + && HttpUtils.isValidUrl(withCodeBase)) + { + // if (debug) + // { + // System.err.println("Prepended codebase '" + codeBase + // + "' to make: '" + withCodeBase + "'"); + // } + retPath[0] = withCodeBase; + return DataSourceType.URL; + } + + /* + * try locating by classloader; try this last so files in the directory + * are resolved using document base + */ + if (inArchive(app.getClass(), path)) + { + return DataSourceType.CLASSLOADER; + } + return null; + } + + /** + * Discovers whether the given file is in the Applet Archive + * + * @param f + * String + * @return boolean + */ + private static boolean inArchive(Class c, String f) + { + // This might throw a security exception in certain browsers + // Netscape Communicator for instance. + try + { + boolean rtn = (c.getResourceAsStream("/" + f) != null); + // if (debug) + // { + // System.err.println("Resource '" + f + "' was " + // + (rtn ? "" : "not ") + "located by classloader."); + // } + return rtn; + } catch (Exception ex) + { + System.out.println("Exception checking resources: " + f + " " + ex); + return false; + } + } + +} diff --git a/src/jalview/bin/JalviewLite.java b/src/jalview/bin/JalviewLite.java index e483fce..5cb599f 100644 --- a/src/jalview/bin/JalviewLite.java +++ b/src/jalview/bin/JalviewLite.java @@ -21,6 +21,8 @@ package jalview.bin; import jalview.analysis.AlignmentUtils; +import jalview.api.AlignViewportI; +import jalview.api.JalviewApp; import jalview.api.StructureSelectionManagerProvider; import jalview.appletgui.AlignFrame; import jalview.appletgui.AlignViewport; @@ -32,7 +34,6 @@ import jalview.datamodel.AlignmentI; import jalview.datamodel.AlignmentOrder; import jalview.datamodel.ColumnSelection; import jalview.datamodel.PDBEntry; -import jalview.datamodel.Sequence; import jalview.datamodel.SequenceGroup; import jalview.datamodel.SequenceI; import jalview.io.AnnotationFile; @@ -42,8 +43,6 @@ import jalview.io.FileFormatI; import jalview.io.FileFormats; import jalview.io.FileParse; import jalview.io.IdentifyFile; -import jalview.io.JPredFile; -import jalview.io.JnetAnnotationMaker; import jalview.io.NewickFile; import jalview.javascript.JSFunctionExec; import jalview.javascript.JalviewLiteJsApi; @@ -52,7 +51,6 @@ import jalview.javascript.MouseOverStructureListener; import jalview.structure.SelectionListener; import jalview.structure.StructureSelectionManager; import jalview.util.ColorUtils; -import jalview.util.HttpUtils; import jalview.util.MessageManager; import java.applet.Applet; @@ -73,7 +71,6 @@ import java.net.URL; import java.util.ArrayList; import java.util.Hashtable; import java.util.List; -import java.util.StringTokenizer; import java.util.Vector; import netscape.javascript.JSObject; @@ -85,9 +82,14 @@ import netscape.javascript.JSObject; * @version $Revision: 1.92 $ */ public class JalviewLite extends Applet - implements StructureSelectionManagerProvider, JalviewLiteJsApi + implements StructureSelectionManagerProvider, JalviewLiteJsApi, + JalviewApp { + public JalviewLite() + { + appLoader = new JalviewAppLoader(debug); + } private static final String TRUE = "true"; private static final String FALSE = "false"; @@ -294,8 +296,8 @@ public class JalviewLite extends Applet } } // deparse fields - String[] ids = separatorListToArray(sequenceIds, sep); - String[] cols = separatorListToArray(columns, sep); + String[] ids = JalviewAppLoader.separatorListToArray(sequenceIds, sep); + String[] cols = JalviewAppLoader.separatorListToArray(columns, sep); final SequenceGroup sel = new SequenceGroup(); final ColumnSelection csel = new ColumnSelection(); AlignmentI al = alf.viewport.getAlignment(); @@ -618,7 +620,7 @@ public class JalviewLite extends Applet public String orderAlignmentBy(AlignFrame alf, String order, String undoName, String sep) { - String[] ids = separatorListToArray(order, sep); + String[] ids = JalviewAppLoader.separatorListToArray(order, sep); SequenceI[] sqs = null; if (ids != null && ids.length > 0) { @@ -1338,6 +1340,10 @@ public class JalviewLite extends Applet */ public boolean useXtrnalSviewer = false; + public JalviewAppLoader appLoader; + + public AlignFrame loaderFrame; + public static boolean debug = false; static String builddate = null, version = null, installation = null; @@ -1836,7 +1842,7 @@ public class JalviewLite extends Applet JalviewLite applet; - private void dbgMsg(String msg) + public void dbgMsg(String msg) { if (JalviewLite.debug) { @@ -1853,67 +1859,10 @@ public class JalviewLite extends Applet */ public String resolveFileProtocol(String path) { - /* - * is it paste data? - */ - if (path.startsWith("PASTE")) - { - protocol = DataSourceType.PASTE; - return path.substring(5); - } - - /* - * is it a URL? - */ - if (path.indexOf("://") != -1) - { - protocol = DataSourceType.URL; - return path; - } - - /* - * try relative to document root - */ - URL documentBase = getDocumentBase(); - String withDocBase = resolveUrlForLocalOrAbsolute(path, documentBase); - if (HttpUtils.isValidUrl(withDocBase)) - { - if (debug) - { - System.err.println("Prepended document base '" + documentBase - + "' to make: '" + withDocBase + "'"); - } - protocol = DataSourceType.URL; - return withDocBase; - } - - /* - * try relative to codebase (if different to document base) - */ - URL codeBase = getCodeBase(); - String withCodeBase = applet.resolveUrlForLocalOrAbsolute(path, - codeBase); - if (!withCodeBase.equals(withDocBase) - && HttpUtils.isValidUrl(withCodeBase)) - { - protocol = DataSourceType.URL; - if (debug) - { - System.err.println("Prepended codebase '" + codeBase - + "' to make: '" + withCodeBase + "'"); - } - return withCodeBase; - } - /* - * try locating by classloader; try this last so files in the directory - * are resolved using document base - */ - if (inArchive(path)) - { - protocol = DataSourceType.CLASSLOADER; - } - return path; + String[] ret = new String[] { path }; + protocol = JalviewAppLoader.resolveFileProtocol(applet, ret); + return ret[0]; } public LoadingThread(String file, String file2, JalviewLite _applet) @@ -1958,17 +1907,8 @@ public class JalviewLite extends Applet if (newAlignFrame != null) { addToDisplay(newAlignFrame, newAlignFrame2); - loadTree(newAlignFrame); - - loadScoreFile(newAlignFrame); - - loadFeatures(newAlignFrame); - - loadAnnotations(newAlignFrame); - - loadJnetFile(newAlignFrame); - - loadPdbFiles(newAlignFrame); + applet.loaderFrame = newAlignFrame; + appLoader.load(applet); } else { @@ -2089,392 +2029,6 @@ public class JalviewLite extends Applet return null; } - /** - * Load PDBFiles if any specified by parameter(s). Returns true if loaded, - * else false. - * - * @param alignFrame - * @return - */ - protected boolean loadPdbFiles(AlignFrame alignFrame) - { - boolean result = false; - /* - * Undocumented for 2.6 - - * related to JAL-434 - */ - - applet.setAlignPdbStructures( - getDefaultParameter("alignpdbfiles", false)); - /* - * - * - * - * - * - */ - - int pdbFileCount = 0; - // Accumulate pdbs here if they are heading for the same view (if - // alignPdbStructures is true) - Vector pdbs = new Vector(); - // create a lazy matcher if we're asked to - jalview.analysis.SequenceIdMatcher matcher = (applet - .getDefaultParameter("relaxedidmatch", false)) - ? new jalview.analysis.SequenceIdMatcher( - alignFrame.getAlignViewport().getAlignment() - .getSequencesArray()) - : null; - - String param; - do - { - if (pdbFileCount > 0) - { - param = applet.getParameter("PDBFILE" + pdbFileCount); - } - else - { - param = applet.getParameter("PDBFILE"); - } - - if (param != null) - { - PDBEntry pdb = new PDBEntry(); - - String seqstring; - SequenceI[] seqs = null; - String[] chains = null; - - StringTokenizer st = new StringTokenizer(param, " "); - - if (st.countTokens() < 2) - { - String sequence = applet.getParameter("PDBSEQ"); - if (sequence != null) - { - seqs = new SequenceI[] { matcher == null - ? (Sequence) alignFrame.getAlignViewport() - .getAlignment().findName(sequence) - : matcher.findIdMatch(sequence) }; - } - - } - else - { - param = st.nextToken(); - List tmp = new ArrayList<>(); - List tmp2 = new ArrayList<>(); - - while (st.hasMoreTokens()) - { - seqstring = st.nextToken(); - StringTokenizer st2 = new StringTokenizer(seqstring, "="); - if (st2.countTokens() > 1) - { - // This is the chain - tmp2.add(st2.nextToken()); - seqstring = st2.nextToken(); - } - tmp.add(matcher == null - ? (Sequence) alignFrame.getAlignViewport() - .getAlignment().findName(seqstring) - : matcher.findIdMatch(seqstring)); - } - - seqs = tmp.toArray(new SequenceI[tmp.size()]); - if (tmp2.size() == tmp.size()) - { - chains = tmp2.toArray(new String[tmp2.size()]); - } - } - param = resolveFileProtocol(param); - // TODO check JAL-357 for files in a jar (CLASSLOADER) - pdb.setFile(param); - - if (seqs != null) - { - for (int i = 0; i < seqs.length; i++) - { - if (seqs[i] != null) - { - ((Sequence) seqs[i]).addPDBId(pdb); - StructureSelectionManager - .getStructureSelectionManager(applet) - .registerPDBEntry(pdb); - } - else - { - if (JalviewLite.debug) - { - // this may not really be a problem but we give a warning - // anyway - System.err.println( - "Warning: Possible input parsing error: Null sequence for attachment of PDB (sequence " - + i + ")"); - } - } - } - - if (!alignPdbStructures) - { - alignFrame.newStructureView(applet, pdb, seqs, chains, - protocol); - } - else - { - pdbs.addElement(new Object[] { pdb, seqs, chains, protocol }); - } - } - } - - pdbFileCount++; - } while (param != null || pdbFileCount < 10); - if (pdbs.size() > 0) - { - SequenceI[][] seqs = new SequenceI[pdbs.size()][]; - PDBEntry[] pdb = new PDBEntry[pdbs.size()]; - String[][] chains = new String[pdbs.size()][]; - String[] protocols = new String[pdbs.size()]; - for (int pdbsi = 0, pdbsiSize = pdbs - .size(); pdbsi < pdbsiSize; pdbsi++) - { - Object[] o = (Object[]) pdbs.elementAt(pdbsi); - pdb[pdbsi] = (PDBEntry) o[0]; - seqs[pdbsi] = (SequenceI[]) o[1]; - chains[pdbsi] = (String[]) o[2]; - protocols[pdbsi] = (String) o[3]; - } - alignFrame.alignedStructureView(applet, pdb, seqs, chains, - protocols); - result = true; - } - return result; - } - - /** - * Load in a Jnetfile if specified by parameter. Returns true if loaded, - * else false. - * - * @param alignFrame - * @return - */ - protected boolean loadJnetFile(AlignFrame alignFrame) - { - boolean result = false; - String param = applet.getParameter("jnetfile"); - if (param == null) - { - // jnet became jpred around 2016 - param = applet.getParameter("jpredfile"); - } - if (param != null) - { - try - { - param = resolveFileProtocol(param); - JPredFile predictions = new JPredFile(param, protocol); - JnetAnnotationMaker.add_annotation(predictions, - alignFrame.viewport.getAlignment(), 0, false); - // false == do not add sequence profile from concise output - - alignFrame.viewport.getAlignment().setupJPredAlignment(); - - alignFrame.alignPanel.fontChanged(); - alignFrame.alignPanel.setScrollValues(0, 0); - result = true; - } catch (Exception ex) - { - ex.printStackTrace(); - } - } - return result; - } - - /** - * Load annotations if specified by parameter. Returns true if loaded, else - * false. - * - * @param alignFrame - * @return - */ - protected boolean loadAnnotations(AlignFrame alignFrame) - { - boolean result = false; - String param = applet.getParameter("annotations"); - if (param != null) - { - param = resolveFileProtocol(param); - - if (new AnnotationFile().annotateAlignmentView(alignFrame.viewport, - param, protocol)) - { - alignFrame.alignPanel.fontChanged(); - alignFrame.alignPanel.setScrollValues(0, 0); - result = true; - } - else - { - System.err.println( - "Annotations were not added from annotation file '" - + param + "'"); - } - } - return result; - } - - /** - * Load features file and view settings as specified by parameters. Returns - * true if features were loaded, else false. - * - * @param alignFrame - * @return - */ - protected boolean loadFeatures(AlignFrame alignFrame) - { - boolean result = false; - // /////////////////////////// - // modify display of features - // we do this before any features have been loaded, ensuring any hidden - // groups are hidden when features first displayed - // - // hide specific groups - // - String param = applet.getParameter("hidefeaturegroups"); - if (param != null) - { - alignFrame.setFeatureGroupState(separatorListToArray(param), false); - // applet.setFeatureGroupStateOn(newAlignFrame, param, false); - } - // show specific groups - param = applet.getParameter("showfeaturegroups"); - if (param != null) - { - alignFrame.setFeatureGroupState(separatorListToArray(param), true); - // applet.setFeatureGroupStateOn(newAlignFrame, param, true); - } - // and now load features - param = applet.getParameter("features"); - if (param != null) - { - param = resolveFileProtocol(param); - - result = alignFrame.parseFeaturesFile(param, protocol); - } - - param = applet.getParameter("showFeatureSettings"); - if (param != null && param.equalsIgnoreCase(TRUE)) - { - alignFrame.viewport.setShowSequenceFeatures(true); - new FeatureSettings(alignFrame.alignPanel); - } - return result; - } - - /** - * Load a score file if specified by parameter. Returns true if file was - * loaded, else false. - * - * @param alignFrame - */ - protected boolean loadScoreFile(AlignFrame alignFrame) - { - boolean result = false; - String sScoreFile = applet.getParameter("scoreFile"); - if (sScoreFile != null && !"".equals(sScoreFile)) - { - try - { - if (debug) - { - System.err.println( - "Attempting to load T-COFFEE score file from the scoreFile parameter"); - } - result = alignFrame.loadScoreFile(sScoreFile); - if (!result) - { - System.err.println( - "Failed to parse T-COFFEE parameter as a valid score file ('" - + sScoreFile + "')"); - } - } catch (Exception e) - { - System.err.printf("Cannot read score file: '%s'. Cause: %s \n", - sScoreFile, e.getMessage()); - } - } - return result; - } - - /** - * Load a tree for the alignment if specified by parameter. Returns true if - * a tree was loaded, else false. - * - * @param alignFrame - * @return - */ - protected boolean loadTree(AlignFrame alignFrame) - { - boolean result = false; - String treeFile = applet.getParameter("tree"); - if (treeFile == null) - { - treeFile = applet.getParameter("treeFile"); - } - - if (treeFile != null) - { - try - { - treeFile = resolveFileProtocol(treeFile); - NewickFile fin = new NewickFile(treeFile, protocol); - fin.parse(); - - if (fin.getTree() != null) - { - alignFrame.loadTree(fin, treeFile); - result = true; - dbgMsg("Successfully imported tree."); - } - else - { - dbgMsg("Tree parameter did not resolve to a valid tree."); - } - } catch (Exception ex) - { - ex.printStackTrace(); - } - } - return result; - } - - /** - * Discovers whether the given file is in the Applet Archive - * - * @param f - * String - * @return boolean - */ - boolean inArchive(String f) - { - // This might throw a security exception in certain browsers - // Netscape Communicator for instance. - try - { - boolean rtn = (getClass().getResourceAsStream("/" + f) != null); - if (debug) - { - System.err.println("Resource '" + f + "' was " - + (rtn ? "" : "not ") + "located by classloader."); - } - return rtn; - } catch (Exception ex) - { - System.out.println("Exception checking resources: " + f + " " + ex); - return false; - } - } } /** @@ -2517,64 +2071,7 @@ public class JalviewLite extends Applet */ public String[] separatorListToArray(String list) { - return separatorListToArray(list, separator); - } - - /** - * parse the string into a list - * - * @param list - * @param separator - * @return elements separated by separator - */ - public static String[] separatorListToArray(String list, String separator) - { - // TODO use StringUtils version (slightly different...) - int seplen = separator.length(); - if (list == null || list.equals("") || list.equals(separator)) - { - return null; - } - java.util.Vector jv = new Vector(); - int cp = 0, pos; - while ((pos = list.indexOf(separator, cp)) > cp) - { - jv.addElement(list.substring(cp, pos)); - cp = pos + seplen; - } - if (cp < list.length()) - { - String c = list.substring(cp); - if (!c.equals(separator)) - { - jv.addElement(c); - } - } - if (jv.size() > 0) - { - String[] v = new String[jv.size()]; - for (int i = 0; i < v.length; i++) - { - v[i] = (String) jv.elementAt(i); - } - jv.removeAllElements(); - if (debug) - { - System.err.println("Array from '" + separator - + "' separated List:\n" + v.length); - for (int i = 0; i < v.length; i++) - { - System.err.println("item " + i + " '" + v[i] + "'"); - } - } - return v; - } - if (debug) - { - System.err.println( - "Empty Array from '" + separator + "' separated List"); - } - return null; + return JalviewAppLoader.separatorListToArray(list, separator); } /** @@ -2755,6 +2252,7 @@ public class JalviewLite extends Applet * the value to return otherwise * @return true or false */ + @Override public boolean getDefaultParameter(String name, boolean def) { String stn; @@ -2782,7 +2280,8 @@ public class JalviewLite extends Applet return alFrame.addPdbFile(sequenceId, pdbEntryString, pdbFile); } - protected void setAlignPdbStructures(boolean alignPdbStructures) + @Override + public void setAlignPdbStructures(boolean alignPdbStructures) { this.alignPdbStructures = alignPdbStructures; } @@ -2914,66 +2413,6 @@ public class JalviewLite extends Applet } /** - * form a complete URL given a path to a resource and a reference location on - * the same server - * - * @param targetPath - * - an absolute path on the same server as localref or a document - * located relative to localref - * @param localref - * - a URL on the same server as url - * @return a complete URL for the resource located by url - */ - private String resolveUrlForLocalOrAbsolute(String targetPath, - URL localref) - { - String resolvedPath = ""; - if (targetPath.startsWith("/")) - { - String codebase = localref.toString(); - String localfile = localref.getFile(); - resolvedPath = codebase.substring(0, - codebase.length() - localfile.length()) + targetPath; - return resolvedPath; - } - - /* - * get URL path and strip off any trailing file e.g. - * www.jalview.org/examples/index.html#applets?a=b is trimmed to - * www.jalview.org/examples/ - */ - String urlPath = localref.toString(); - String directoryPath = urlPath; - int lastSeparator = directoryPath.lastIndexOf("/"); - if (lastSeparator > 0) - { - directoryPath = directoryPath.substring(0, lastSeparator + 1); - } - - if (targetPath.startsWith("/")) - { - /* - * construct absolute URL to a file on the server - this is not allowed? - */ - // String localfile = localref.getFile(); - // resolvedPath = urlPath.substring(0, - // urlPath.length() - localfile.length()) - // + targetPath; - resolvedPath = directoryPath + targetPath.substring(1); - } - else - { - resolvedPath = directoryPath + targetPath; - } - if (debug) - { - System.err.println( - "resolveUrlForLocalOrAbsolute returning " + resolvedPath); - } - return resolvedPath; - } - - /** * open a URL in the browser - resolving it according to relative refs and * coping with javascript: protocol if necessary. * @@ -2990,7 +2429,7 @@ public class JalviewLite extends Applet // form valid URL // Should really use docbase, not codebase. URL prepend; - url = resolveUrlForLocalOrAbsolute(url, + url = JalviewAppLoader.resolveUrlForLocalOrAbsolute(url, prepend = getDefaultParameter("resolvetocodebase", false) ? getCodeBase() : getDocumentBase()); @@ -3023,6 +2462,65 @@ public class JalviewLite extends Applet } } + @Override + public AlignViewportI getViewport() + { + return loaderFrame.getAlignViewport(); + } + + @Override + public void newStructureView(PDBEntry pdb, SequenceI[] seqs, + String[] chains, DataSourceType protocol) + { + loaderFrame.newStructureView(this, pdb, seqs, chains, + protocol); + } + + @Override + public void alignedStructureView(PDBEntry[] pdb, SequenceI[][] seqs, + String[][] chains, String[] protocols) + { + loaderFrame.alignedStructureView(this, pdb, seqs, chains, protocols); + } + + @Override + public void updateForLoader() + { + loaderFrame.alignPanel.fontChanged(); + loaderFrame.alignPanel.setScrollValues(0, 0); + } + + @Override + public void setFeatureGroupState(String[] groups, boolean state) + { + loaderFrame.setFeatureGroupState(groups, state); + } + + @Override + public boolean parseFeaturesFile(String param, DataSourceType protocol) + { + return loaderFrame.parseFeaturesFile(param, protocol); + } + + @Override + public void newFeatureSettings() + { + getViewport().setShowSequenceFeatures(true); + new FeatureSettings(loaderFrame.alignPanel); + } + + @Override + public boolean loadScoreFile(String sScoreFile) throws IOException + { + return loaderFrame.loadScoreFile(sScoreFile); + } + + @Override + public void loadTree(NewickFile tree, String treeFile) throws IOException + { + loaderFrame.loadTree(tree, treeFile); + } + /** * bind structures in a viewer to any matching sequences in an alignFrame (use * sequenceIds to limit scope of search to specific sequences) diff --git a/test/jalview/bin/JalviewLiteTest.java b/test/jalview/bin/JalviewLiteTest.java index 07e1b25..4535b7e 100644 --- a/test/jalview/bin/JalviewLiteTest.java +++ b/test/jalview/bin/JalviewLiteTest.java @@ -43,20 +43,20 @@ public class JalviewLiteTest @Test(groups = "Functional") public void testSeparatorListToArray() { - assertNull(JalviewLite.separatorListToArray(null, "|")); - assertNull(JalviewLite.separatorListToArray("", "|")); - assertNull(JalviewLite.separatorListToArray("|", "|")); - assertNull(JalviewLite.separatorListToArray("abc", "abc")); + assertNull(JalviewAppLoader.separatorListToArray(null, "|")); + assertNull(JalviewAppLoader.separatorListToArray("", "|")); + assertNull(JalviewAppLoader.separatorListToArray("|", "|")); + assertNull(JalviewAppLoader.separatorListToArray("abc", "abc")); - String[] array = JalviewLite.separatorListToArray("abc|def|ghi|", "|"); + String[] array = JalviewAppLoader.separatorListToArray("abc|def|ghi|", "|"); assertEquals(3, array.length); assertEquals("abc", array[0]); assertEquals("def", array[1]); assertEquals("ghi", array[2]); assertEquals("[abc]", - Arrays.toString(JalviewLite.separatorListToArray("abc|", "|"))); - assertEquals("[abc]", Arrays.toString(JalviewLite.separatorListToArray( + Arrays.toString(JalviewAppLoader.separatorListToArray("abc|", "|"))); + assertEquals("[abc]", Arrays.toString(JalviewAppLoader.separatorListToArray( "abcxy", "xy"))); // these fail: