+ * - workdir + * - a + * - b + * - c (symlink to a) + * - d (symlink to e) + * - e + *+ * + * @throws java.io.IOException + */ + public void testIsRecursiveSymbolicLink() throws IOException { + if (!checkSymlinksSupported()) { + return; + } + File dir = getWorkDir(); + File a = new File(dir, "a"); + File b = new File(a, "b"); + File c = new File(b, "c"); + File d = new File(b, "d"); + File e = new File(dir, "e"); + b.mkdirs(); + e.mkdirs(); + Files.createSymbolicLink(c.toPath(), a.toPath()); + Files.createSymbolicLink(d.toPath(), e.toPath()); + FileObject dirFO = FileUtil.toFileObject(dir); + dirFO.refresh(); + FileObject cFO = dirFO.getFileObject("a/b/c"); + FileObject dFO = dirFO.getFileObject("a/b/d"); + assertTrue(FileUtil.isRecursiveSymbolicLink(cFO)); + assertFalse(FileUtil.isRecursiveSymbolicLink(dFO)); + assertFalse(FileUtil.isRecursiveSymbolicLink(dirFO)); + } + + /** + * Test isRecursiveSymbolicLink method. Use this folder tree: + *
+ * - workdir + * - a + * - b + * - c (symlink to d) + * - d (symlink to a) + *+ * + * @throws java.io.IOException + */ + public void testIsRecursiveSymbolicLinkIndirect() throws IOException { + if (!checkSymlinksSupported()) { + return; + } + File dir = getWorkDir(); + File a = new File(dir, "a"); + File b = new File(a, "b"); + File c = new File(b, "c"); + File d = new File(dir, "d"); + b.mkdirs(); + Files.createSymbolicLink(d.toPath(), a.toPath()); + Files.createSymbolicLink(c.toPath(), d.toPath()); + FileObject dirFO = FileUtil.toFileObject(dir); + FileObject cFO = dirFO.getFileObject("a/b/c"); + assertTrue(FileUtil.isRecursiveSymbolicLink(cFO)); + } + + public void testReadSymbolicLinkAbsolute() throws IOException { + if (!checkSymlinksSupported()) { + return; + } + File dir = getWorkDir(); + File data = new File(dir, "data.dat"); + File link = new File(dir, "link.lnk"); + data.createNewFile(); + Files.createSymbolicLink(link.toPath(), data.toPath()); + FileObject linkFO = FileUtil.toFileObject(link); + FileObject dataFO = linkFO.readSymbolicLink(); + assertNotSame(linkFO, dataFO); + assertNotNull(dataFO); + assertEquals("data.dat", dataFO.getNameExt()); + } + + public void testReadSymbolicLinkRelative() throws IOException { + if (!checkSymlinksSupported()) { + return; + } + File dir = getWorkDir(); + File folder = new File(dir, "folder"); + File link = new File(dir, "link"); + folder.mkdir(); + Path lp = Files.createSymbolicLink(link.toPath(), Paths.get("folder")); + assertNotNull(lp); + FileObject linkFO = FileUtil.toFileObject(link); + assertNotNull(linkFO); + FileObject dataFO = linkFO.readSymbolicLink(); + assertNotSame(linkFO, dataFO); + assertNotNull(dataFO); + assertEquals("folder", dataFO.getNameExt()); + } + + public void testReadSymbolicLinkPath() throws IOException { + if (!checkSymlinksSupported()) { + return; + } + File dir = getWorkDir(); + File data = new File(dir, "data.dat"); + File link = new File(dir, "link.lnk"); + data.createNewFile(); + Files.createSymbolicLink(link.toPath(), data.toPath()); + FileObject linkFO = FileUtil.toFileObject(link); + assertTrue(linkFO.readSymbolicLinkPath().endsWith("data.dat")); + } + + /** + * Test getCanonicalFileObject method. + * + * Use this directory tree: + *
+ * - workdir + * - a + * - data.dat + * - b + * - link.lnk (symlink to data.dat) + * - c + * - link2.lnk (symlink to link.link) + * - d + * - folderLink (symlink to c) + *+ * @throws java.io.IOException + */ + public void testGetRealFileObject() throws IOException { + if (!checkSymlinksSupported()) { + return; + } + File dir = getWorkDir(); + File a = new File(dir, "a"); + File dataDat = new File(a, "data.dat"); + File b = new File(dir, "b"); + File linkLnk = new File(b, "link.lnk"); + File c = new File(dir, "c"); + File link2Lnk = new File(c, "link2.lnk"); + File d = new File(dir, "d"); + File folderLink = new File(d, "folderLink"); + a.mkdir(); + dataDat.createNewFile(); + b.mkdir(); + Files.createSymbolicLink(linkLnk.toPath(), dataDat.toPath()); + c.mkdir(); + Files.createSymbolicLink(link2Lnk.toPath(), linkLnk.toPath()); + d.mkdir(); + Files.createSymbolicLink(folderLink.toPath(), c.toPath()); + FileObject dirFO = FileUtil.toFileObject(dir); + dirFO.refresh(); + FileObject fo = dirFO.getFileObject("d/folderLink/link2.lnk"); + assertNotNull(fo); + FileObject realFO = fo.getCanonicalFileObject(); + assertNotNull(realFO); + assertTrue(realFO.getPath().endsWith("a/data.dat")); + } + + /** + * Recursively delete all symlinks in a directory. + */ + private void deleteSymlinks(File root) { + for (File f : root.listFiles()) { + if (Files.isSymbolicLink(f.toPath())) { + f.delete(); + } else if (f.isDirectory()) { + deleteSymlinks(f); + } + } + } + + private boolean checkSymlinksSupported() { + File dir; + try { + dir = getWorkDir(); + } catch (IOException ex) { + printSkipping(); + return false; + } + File a = new File(dir, "a"); + try { + File lk = new File(dir, "lk"); + Files.createSymbolicLink(lk.toPath(), a.toPath()); + lk.delete(); + return true; + } catch (RuntimeException e) { + } catch (IOException ex) { + } + printSkipping(); + return false; + } + + private void printSkipping() { + System.out.println( + "Symbolic links are not supported, skipping test " + getName()); + } +} --- a/openide.filesystems/apichanges.xml +++ a/openide.filesystems/apichanges.xml @@ -49,6 +49,36 @@
+ Add methods to FileObject
for handling of
+ symbolic links:
+
isSymbolicLink()
readSymbolicLink()
readSymbolicLinkPath()
getCanonicalFileObject()
+ Add utility method to FileUtil
for dealing with
+ recursive symbolic links.
+
isRecursiveSymbolicLink()