public StructureCommandI loadFile(String file)
{
// https://chemapps.stolaf.edu/jmol/docs/#loadfiles
+
return new StructureCommand(
- "load FILES \"" + Platform.escapeBackslashes(file) + "\"");
+ "load FILES \"" + escapeQuotedFilename(file) + "\"");
+ }
+
+
+ /**
+ * escape a filename coping with Jmol's quirks (Jmol 14.31.53 NOLOG4J) for
+ * resolving files on network drives
+ *
+ * @param file
+ * @return escaped file prepended with file: if necessary - needs to be
+ * wrapped in \\\"
+ */
+ public static String escapeQuotedFilename(String file)
+ {
+ String prepend="";
+ if (file.startsWith("//") || file.startsWith("\\\\"))
+ {
+ prepend = "file:";
+ }
+ return prepend+Platform.escapeBackslashes(file);
}
@Override
public StructureCommandI restoreSession(String filePath)
{
return new StructureCommand("restore STATE \""
- + Platform.escapeBackslashes(filePath) + "\"");
+ + escapeQuotedFilename(filePath) + "\"");
}
@Override
{
return null; // not an external viewer
}
+
+ /**
+ * match up Jmol 14.31.53 NOLOG4J's idea of a filepath with Jalview's
+ * @param jmolFile
+ * @param jalviewFile
+ * @return true if strings resolve to the same resource
+ */
+ public static boolean filePathMatch(String jmolFile,String jalviewFile)
+ {
+ if (jmolFile.equalsIgnoreCase(jalviewFile))
+ {
+ return true;
+ }
+ if (jmolFile.startsWith("file:") && (jalviewFile.startsWith("//") || jalviewFile.startsWith("\\\\")))
+ {
+ String jmolPath = jmolFile.substring(5);
+ // jmol needs file: at beginning for network mounts.
+ if (jmolPath.equalsIgnoreCase(jalviewFile))
+ {
+ return true;
+ }
+ if (jmolPath.startsWith("////"))
+ {
+ // faulty translation from backslash to forward slash - put it back the other way
+ jmolPath = jmolPath.replace("//", "/");
+ }
+ if (jmolPath.equalsIgnoreCase(jalviewFile))
+ {
+ return true;
+ }
+ if (jmolPath.startsWith("\\\\\\"))
+ {
+ // faulty translation from backslash to forward slash - put it back the other way
+ jmolPath = jmolPath.replace("\\\\", "//");
+ } // also normalises \\ to / for URLs
+ String jalviewPath = jalviewFile.replace("\\","/");
+ if (jmolPath.equalsIgnoreCase(jalviewPath))
+ {
+ return true;
+ }
+ jmolPath = jmolPath.replace("//", "/");
+ return jmolPath.equalsIgnoreCase(jalviewPath);
+
+ }
+ return false;
+ }
}
import java.util.Map;
import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import jalview.datamodel.Alignment;
// single backslash gets escaped to double
cmd = testee.loadFile("\\some\\filepath");
assertEquals(cmd.getCommand(), "load FILES \"\\\\some\\\\filepath\"");
+
+ // double backslash gets escaped to file:\\\\
+ cmd = testee.loadFile("\\\\some\\filepath");
+ assertEquals(cmd.getCommand(),
+ "load FILES \"file:\\\\\\\\some\\\\filepath\"");
+
+ // double forward slash is escaped to file:////
+ cmd = testee.loadFile("//some/filepath");
+ assertEquals(cmd.getCommand(), "load FILES \"file://some/filepath\"");
+
+ }
+
+ @Test(
+ groups = "Functional",
+ dataProvider = "testFilePathEquivalence",
+ singleThreaded = true)
+ public void testFilePathEquivalence(String jalviewpath, String jmolpath)
+ {
+ assertEquals(JmolCommands.escapeQuotedFilename(jalviewpath), jmolpath,
+ "for " + jalviewpath);
+ // simple unescape
+ assertTrue(JmolCommands.filePathMatch(jmolpath.replace("\\\\", "\\"),
+ jalviewpath));
+ }
+
+ /**
+ * Windows path transformations for Jmol 14.31.53 NOLOG4J positive examples
+ * for escapeQuotedFilename - results of escaping should, after a simple
+ * unescape (remove escape backslashes) also work for filePathMatch
+ *
+ * @return
+ */
+
+ @DataProvider(name = "testFilePathEquivalence")
+ public Object[][] fileEquivalences()
+ {
+ return new String[][] {
+ new String[]
+ { "/some/filepath", "/some/filepath" },
+ new String[]
+ { "\\some\\filepath", "\\\\some\\\\filepath" },
+ new String[]
+ { "\\\\some\\filepath", "file:\\\\\\\\some\\\\filepath" },
+ new String[]
+ { "//some/filepath", "file://some/filepath" } };
+ }
+
+ @Test(
+ groups = "Functional",
+ dataProvider = "testForwardBackslashFilePathEquivalence")
+ public void filePathMatchTest(String jmolPath, String jalviewPath)
+ {
+ assertTrue(JmolCommands.filePathMatch(jmolPath, jalviewPath));
+ }
+
+ /**
+ * Windows path transformations for Jmol 14.31.53 NOLOG4J positive examples
+ * for JmolCommands.filePathMatch - handles windows network drive
+ * transformations
+ *
+ * @return
+ */
+ @DataProvider(name = "testForwardBackslashFilePathEquivalence")
+ public Object[][] forwardBackslashFilePathEquivalence()
+ {
+ return new String[][] {
+ new String[]
+ { "file:\\\\some\\filepath", "\\\\some\\filepath" },
+ new String[]
+ { "file://some/filepath", "\\\\some\\filepath" },
+ new String[]
+ { "file:////some//filepath", "\\\\some\\filepath" },
+ new String[]
+ { "file:\\\\\\\\estorage.dundee.ac.uk\\\\cluster-gjb_lab\\\\jprocter\\\\public_html\\\\1QIP.cif",
+ "//estorage.dundee.ac.uk/cluster-gjb_lab/jprocter/public_html/1QIP.cif" },
+ new String[]
+ { "file:\\\\\\\\estorage.dundee.ac.uk\\\\cluster-gjb_lab\\\\jprocter\\\\public_html\\\\1QIP.cif",
+ "\\\\estorage.dundee.ac.uk\\cluster-gjb_lab\\jprocter\\public_html\\1QIP.cif" },
+ new String[]
+ { "file://estorage.dundee.ac.uk/cluster-gjb_lab/jprocter/public_html/1QIP.cif",
+ "\\\\estorage.dundee.ac.uk\\cluster-gjb_lab\\jprocter\\public_html\\1QIP.cif" },
+ new String[]
+ { "file:////estorage.dundee.ac.uk//cluster-gjb_lab//jprocter//public_html//1QIP.cif",
+ "\\\\estorage.dundee.ac.uk\\cluster-gjb_lab\\jprocter\\public_html\\1QIP.cif" } };
}
@Test(groups = "Functional")