diff --git a/src/main/org/apache/tools/ant/DirectoryScanner.java b/src/main/org/apache/tools/ant/DirectoryScanner.java index 876fa3ec3..7c540f06a 100644 --- a/src/main/org/apache/tools/ant/DirectoryScanner.java +++ b/src/main/org/apache/tools/ant/DirectoryScanner.java @@ -20,6 +20,9 @@ package org.apache.tools.ant; import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -44,7 +47,6 @@ import org.apache.tools.ant.types.selectors.SelectorUtils; import org.apache.tools.ant.types.selectors.TokenizedPath; import org.apache.tools.ant.types.selectors.TokenizedPattern; import org.apache.tools.ant.util.FileUtils; -import org.apache.tools.ant.util.SymbolicLinkUtils; import org.apache.tools.ant.util.VectorSet; /** @@ -227,10 +229,6 @@ public class DirectoryScanner /** Helper. */ private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); - /** Helper. */ - private static final SymbolicLinkUtils SYMLINK_UTILS = - SymbolicLinkUtils.getSymbolicLinkUtils(); - /** * Patterns which should be excluded by default. * @@ -874,7 +872,7 @@ public class DirectoryScanner excludes = nullExcludes ? new String[0] : excludes; if (basedir != null && !followSymlinks - && SYMLINK_UTILS.isSymbolicLink(basedir)) { + && Files.isSymbolicLink(basedir.toPath())) { notFollowedSymlinks.add(basedir.getAbsolutePath()); basedir = null; } @@ -919,8 +917,6 @@ public class DirectoryScanner includes = nullIncludes ? null : includes; excludes = nullExcludes ? null : excludes; } - } catch (final IOException ex) { - throw new BuildException(ex); } finally { basedir = savedBase; synchronized (scanLock) { @@ -1220,25 +1216,23 @@ public class DirectoryScanner } if (!followSymlinks) { final ArrayList noLinks = new ArrayList<>(); - for (String newfile : newfiles) { - try { - if (SYMLINK_UTILS.isSymbolicLink(dir, newfile)) { - final String name = vpath + newfile; - final File file = new File(dir, newfile); - if (file.isDirectory()) { - dirsExcluded.addElement(name); - } else if (file.isFile()) { - filesExcluded.addElement(name); - } - accountForNotFollowedSymlink(name, file); - } else { - noLinks.add(newfile); + for (final String newfile : newfiles) { + final Path filePath; + if (dir == null) { + filePath = Paths.get(newfile); + } else { + filePath = Paths.get(dir.toPath().toString(), newfile); + } + if (Files.isSymbolicLink(filePath)) { + final String name = vpath + newfile; + final File file = new File(dir, newfile); + if (file.isDirectory()) { + dirsExcluded.addElement(name); + } else if (file.isFile()) { + filesExcluded.addElement(name); } - } catch (final IOException ioe) { - final String msg = "IOException caught while checking " - + "for links, couldn't get canonical path!"; - // will be caught and redirected to Ant's logging system - System.err.println(msg); + accountForNotFollowedSymlink(name, file); + } else { noLinks.add(newfile); } } @@ -1815,9 +1809,15 @@ public class DirectoryScanner private boolean causesIllegalSymlinkLoop(final String dirName, final File parent, final Deque directoryNamesFollowed) { try { + final Path dirPath; + if (parent == null) { + dirPath = Paths.get(dirName); + } else { + dirPath = Paths.get(parent.toPath().toString(), dirName); + } if (directoryNamesFollowed.size() >= maxLevelsOfSymlinks && Collections.frequency(directoryNamesFollowed, dirName) >= maxLevelsOfSymlinks - && SYMLINK_UTILS.isSymbolicLink(parent, dirName)) { + && Files.isSymbolicLink(dirPath)) { final List files = new ArrayList<>(); File f = FILE_UTILS.resolveFile(parent, dirName); diff --git a/src/main/org/apache/tools/ant/taskdefs/Delete.java b/src/main/org/apache/tools/ant/taskdefs/Delete.java index 224e3c7e7..12be2d41f 100644 --- a/src/main/org/apache/tools/ant/taskdefs/Delete.java +++ b/src/main/org/apache/tools/ant/taskdefs/Delete.java @@ -19,7 +19,9 @@ package org.apache.tools.ant.taskdefs; import java.io.File; -import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Arrays; import java.util.Comparator; import java.util.Iterator; @@ -61,7 +63,6 @@ import org.apache.tools.ant.types.selectors.SelectSelector; import org.apache.tools.ant.types.selectors.SizeSelector; import org.apache.tools.ant.types.selectors.modifiedselector.ModifiedSelector; import org.apache.tools.ant.util.FileUtils; -import org.apache.tools.ant.util.SymbolicLinkUtils; /** * Deletes a file or directory, or set of files defined by a fileset. @@ -81,8 +82,6 @@ public class Delete extends MatchingTask { private static final ResourceComparator REVERSE_FILESYSTEM = new Reverse(new FileSystem()); private static final ResourceSelector EXISTS = new Exists(); private static FileUtils FILE_UTILS = FileUtils.getFileUtils(); - private static SymbolicLinkUtils SYMLINK_UTILS = - SymbolicLinkUtils.getSymbolicLinkUtils(); private static class ReverseDirs implements ResourceCollection { @@ -715,12 +714,15 @@ public class Delete extends MatchingTask { System.arraycopy(n, 0, links, 0, n.length); Arrays.sort(links, Comparator.reverseOrder()); for (int l = 0; l < links.length; l++) { - try { - SYMLINK_UTILS - .deleteSymbolicLink(new File(links[l]), - this); - } catch (java.io.IOException ex) { - handle(ex); + final Path filePath = Paths.get(links[l]); + if (!Files.isSymbolicLink(filePath)) { + // it's not a symbolic link, so move on + continue; + } + // it's a symbolic link, so delete it + final boolean deleted = filePath.toFile().delete(); + if (!deleted) { + handle("Could not delete symbolic link at " + filePath); } } } @@ -876,14 +878,13 @@ public class Delete extends MatchingTask { } } - private boolean isDanglingSymlink(File f) { - try { - return SYMLINK_UTILS.isDanglingSymbolicLink(f); - } catch (IOException e) { - log("Error while trying to detect " + f.getAbsolutePath() - + " as broken symbolic link. " + e.getMessage(), - quiet ? Project.MSG_VERBOSE : verbosity); + private boolean isDanglingSymlink(final File f) { + if (!Files.isSymbolicLink(f.toPath())) { + // it's not a symlink, so clearly it's not a dangling one return false; } + // it's a symbolic link, now check the existence of the (target) file (by "following links") + final boolean targetFileExists = Files.exists(f.toPath()); + return !targetFileExists; } } diff --git a/src/main/org/apache/tools/ant/types/selectors/TokenizedPath.java b/src/main/org/apache/tools/ant/types/selectors/TokenizedPath.java index 3eae584f1..5a63fb79d 100644 --- a/src/main/org/apache/tools/ant/types/selectors/TokenizedPath.java +++ b/src/main/org/apache/tools/ant/types/selectors/TokenizedPath.java @@ -19,11 +19,12 @@ package org.apache.tools.ant.types.selectors; import java.io.File; -import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.util.FileUtils; -import org.apache.tools.ant.util.SymbolicLinkUtils; /** * Container for a path that has been split into its components. @@ -39,9 +40,6 @@ public class TokenizedPath { /** Helper. */ private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); - /** Helper. */ - private static final SymbolicLinkUtils SYMLINK_UTILS = - SymbolicLinkUtils.getSymbolicLinkUtils(); /** iterations for case-sensitive scanning. */ private static final boolean[] CS_SCAN_ONLY = new boolean[] {true}; /** iterations for non-case-sensitive scanning. */ @@ -142,22 +140,16 @@ public class TokenizedPath { */ public boolean isSymlink(File base) { for (int i = 0; i < tokenizedPath.length; i++) { - try { - if ((base != null - && SYMLINK_UTILS.isSymbolicLink(base, tokenizedPath[i])) - || - (base == null - && SYMLINK_UTILS.isSymbolicLink(tokenizedPath[i])) - ) { - return true; - } - base = new File(base, tokenizedPath[i]); - } catch (IOException ioe) { - String msg = "IOException caught while checking " - + "for links, couldn't get canonical path!"; - // will be caught and redirected to Ant's logging system - System.err.println(msg); + final Path pathToTraverse; + if (base == null) { + pathToTraverse = Paths.get(tokenizedPath[i]); + } else { + pathToTraverse = Paths.get(base.toPath().toString(), tokenizedPath[i]); + } + if (Files.isSymbolicLink(pathToTraverse)) { + return true; } + base = new File(base, tokenizedPath[i]); } return false; } diff --git a/src/main/org/apache/tools/ant/util/FileUtils.java b/src/main/org/apache/tools/ant/util/FileUtils.java index 9c6e59fb2..ce75d3446 100644 --- a/src/main/org/apache/tools/ant/util/FileUtils.java +++ b/src/main/org/apache/tools/ant/util/FileUtils.java @@ -33,6 +33,7 @@ import java.net.URLConnection; import java.nio.channels.Channel; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.text.DecimalFormat; import java.util.ArrayList; @@ -1141,16 +1142,15 @@ public class FileUtils { * @return true if the file is a symbolic link. * @throws IOException on error. * @since Ant 1.5 - * @deprecated use SymbolicLinkUtils instead + * @deprecated use {@link Files#isSymbolicLink(Path)} instead */ @Deprecated - public boolean isSymbolicLink(File parent, String name) + public boolean isSymbolicLink(final File parent, final String name) throws IOException { - SymbolicLinkUtils u = SymbolicLinkUtils.getSymbolicLinkUtils(); if (parent == null) { - return u.isSymbolicLink(name); + return Files.isSymbolicLink(Paths.get(name)); } - return u.isSymbolicLink(parent, name); + return Files.isSymbolicLink(Paths.get(parent.toPath().toString(), name)); } /** diff --git a/src/main/org/apache/tools/ant/util/SymbolicLinkUtils.java b/src/main/org/apache/tools/ant/util/SymbolicLinkUtils.java index 46ddf774e..9854dc03c 100644 --- a/src/main/org/apache/tools/ant/util/SymbolicLinkUtils.java +++ b/src/main/org/apache/tools/ant/util/SymbolicLinkUtils.java @@ -30,6 +30,9 @@ import org.apache.tools.ant.taskdefs.Execute; * a symbolic link based on the absent support for them in Java. * * @since Ant 1.8.0 + * @deprecated Starting Ant 1.10.2, this class is now deprecated in favour + * of the Java {@link java.nio.file.Files} APIs introduced in + * Java 7, for dealing with symbolic links */ public class SymbolicLinkUtils { private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();