| @@ -20,6 +20,9 @@ package org.apache.tools.ant; | |||||
| import java.io.File; | import java.io.File; | ||||
| import java.io.IOException; | 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.ArrayList; | ||||
| import java.util.Arrays; | import java.util.Arrays; | ||||
| import java.util.Collections; | 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.TokenizedPath; | ||||
| import org.apache.tools.ant.types.selectors.TokenizedPattern; | import org.apache.tools.ant.types.selectors.TokenizedPattern; | ||||
| import org.apache.tools.ant.util.FileUtils; | import org.apache.tools.ant.util.FileUtils; | ||||
| import org.apache.tools.ant.util.SymbolicLinkUtils; | |||||
| import org.apache.tools.ant.util.VectorSet; | import org.apache.tools.ant.util.VectorSet; | ||||
| /** | /** | ||||
| @@ -227,10 +229,6 @@ public class DirectoryScanner | |||||
| /** Helper. */ | /** Helper. */ | ||||
| private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); | private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); | ||||
| /** Helper. */ | |||||
| private static final SymbolicLinkUtils SYMLINK_UTILS = | |||||
| SymbolicLinkUtils.getSymbolicLinkUtils(); | |||||
| /** | /** | ||||
| * Patterns which should be excluded by default. | * Patterns which should be excluded by default. | ||||
| * | * | ||||
| @@ -874,7 +872,7 @@ public class DirectoryScanner | |||||
| excludes = nullExcludes ? new String[0] : excludes; | excludes = nullExcludes ? new String[0] : excludes; | ||||
| if (basedir != null && !followSymlinks | if (basedir != null && !followSymlinks | ||||
| && SYMLINK_UTILS.isSymbolicLink(basedir)) { | |||||
| && Files.isSymbolicLink(basedir.toPath())) { | |||||
| notFollowedSymlinks.add(basedir.getAbsolutePath()); | notFollowedSymlinks.add(basedir.getAbsolutePath()); | ||||
| basedir = null; | basedir = null; | ||||
| } | } | ||||
| @@ -919,8 +917,6 @@ public class DirectoryScanner | |||||
| includes = nullIncludes ? null : includes; | includes = nullIncludes ? null : includes; | ||||
| excludes = nullExcludes ? null : excludes; | excludes = nullExcludes ? null : excludes; | ||||
| } | } | ||||
| } catch (final IOException ex) { | |||||
| throw new BuildException(ex); | |||||
| } finally { | } finally { | ||||
| basedir = savedBase; | basedir = savedBase; | ||||
| synchronized (scanLock) { | synchronized (scanLock) { | ||||
| @@ -1220,25 +1216,23 @@ public class DirectoryScanner | |||||
| } | } | ||||
| if (!followSymlinks) { | if (!followSymlinks) { | ||||
| final ArrayList<String> noLinks = new ArrayList<>(); | final ArrayList<String> 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); | noLinks.add(newfile); | ||||
| } | } | ||||
| } | } | ||||
| @@ -1815,9 +1809,15 @@ public class DirectoryScanner | |||||
| private boolean causesIllegalSymlinkLoop(final String dirName, final File parent, | private boolean causesIllegalSymlinkLoop(final String dirName, final File parent, | ||||
| final Deque<String> directoryNamesFollowed) { | final Deque<String> directoryNamesFollowed) { | ||||
| try { | try { | ||||
| final Path dirPath; | |||||
| if (parent == null) { | |||||
| dirPath = Paths.get(dirName); | |||||
| } else { | |||||
| dirPath = Paths.get(parent.toPath().toString(), dirName); | |||||
| } | |||||
| if (directoryNamesFollowed.size() >= maxLevelsOfSymlinks | if (directoryNamesFollowed.size() >= maxLevelsOfSymlinks | ||||
| && Collections.frequency(directoryNamesFollowed, dirName) >= maxLevelsOfSymlinks | && Collections.frequency(directoryNamesFollowed, dirName) >= maxLevelsOfSymlinks | ||||
| && SYMLINK_UTILS.isSymbolicLink(parent, dirName)) { | |||||
| && Files.isSymbolicLink(dirPath)) { | |||||
| final List<String> files = new ArrayList<>(); | final List<String> files = new ArrayList<>(); | ||||
| File f = FILE_UTILS.resolveFile(parent, dirName); | File f = FILE_UTILS.resolveFile(parent, dirName); | ||||
| @@ -19,7 +19,9 @@ | |||||
| package org.apache.tools.ant.taskdefs; | package org.apache.tools.ant.taskdefs; | ||||
| import java.io.File; | 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.Arrays; | ||||
| import java.util.Comparator; | import java.util.Comparator; | ||||
| import java.util.Iterator; | 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.SizeSelector; | ||||
| import org.apache.tools.ant.types.selectors.modifiedselector.ModifiedSelector; | import org.apache.tools.ant.types.selectors.modifiedselector.ModifiedSelector; | ||||
| import org.apache.tools.ant.util.FileUtils; | 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. | * 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 ResourceComparator REVERSE_FILESYSTEM = new Reverse(new FileSystem()); | ||||
| private static final ResourceSelector EXISTS = new Exists(); | private static final ResourceSelector EXISTS = new Exists(); | ||||
| private static FileUtils FILE_UTILS = FileUtils.getFileUtils(); | private static FileUtils FILE_UTILS = FileUtils.getFileUtils(); | ||||
| private static SymbolicLinkUtils SYMLINK_UTILS = | |||||
| SymbolicLinkUtils.getSymbolicLinkUtils(); | |||||
| private static class ReverseDirs implements ResourceCollection { | private static class ReverseDirs implements ResourceCollection { | ||||
| @@ -715,12 +714,15 @@ public class Delete extends MatchingTask { | |||||
| System.arraycopy(n, 0, links, 0, n.length); | System.arraycopy(n, 0, links, 0, n.length); | ||||
| Arrays.sort(links, Comparator.reverseOrder()); | Arrays.sort(links, Comparator.reverseOrder()); | ||||
| for (int l = 0; l < links.length; l++) { | 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; | 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; | |||||
| } | } | ||||
| } | } | ||||
| @@ -19,11 +19,12 @@ | |||||
| package org.apache.tools.ant.types.selectors; | package org.apache.tools.ant.types.selectors; | ||||
| import java.io.File; | 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.BuildException; | ||||
| import org.apache.tools.ant.util.FileUtils; | 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. | * Container for a path that has been split into its components. | ||||
| @@ -39,9 +40,6 @@ public class TokenizedPath { | |||||
| /** Helper. */ | /** Helper. */ | ||||
| private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); | private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); | ||||
| /** Helper. */ | |||||
| private static final SymbolicLinkUtils SYMLINK_UTILS = | |||||
| SymbolicLinkUtils.getSymbolicLinkUtils(); | |||||
| /** iterations for case-sensitive scanning. */ | /** iterations for case-sensitive scanning. */ | ||||
| private static final boolean[] CS_SCAN_ONLY = new boolean[] {true}; | private static final boolean[] CS_SCAN_ONLY = new boolean[] {true}; | ||||
| /** iterations for non-case-sensitive scanning. */ | /** iterations for non-case-sensitive scanning. */ | ||||
| @@ -142,22 +140,16 @@ public class TokenizedPath { | |||||
| */ | */ | ||||
| public boolean isSymlink(File base) { | public boolean isSymlink(File base) { | ||||
| for (int i = 0; i < tokenizedPath.length; i++) { | 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; | return false; | ||||
| } | } | ||||
| @@ -33,6 +33,7 @@ import java.net.URLConnection; | |||||
| import java.nio.channels.Channel; | import java.nio.channels.Channel; | ||||
| import java.nio.file.Files; | import java.nio.file.Files; | ||||
| import java.nio.file.Path; | import java.nio.file.Path; | ||||
| import java.nio.file.Paths; | |||||
| import java.nio.file.StandardOpenOption; | import java.nio.file.StandardOpenOption; | ||||
| import java.text.DecimalFormat; | import java.text.DecimalFormat; | ||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||
| @@ -1141,16 +1142,15 @@ public class FileUtils { | |||||
| * @return true if the file is a symbolic link. | * @return true if the file is a symbolic link. | ||||
| * @throws IOException on error. | * @throws IOException on error. | ||||
| * @since Ant 1.5 | * @since Ant 1.5 | ||||
| * @deprecated use SymbolicLinkUtils instead | |||||
| * @deprecated use {@link Files#isSymbolicLink(Path)} instead | |||||
| */ | */ | ||||
| @Deprecated | @Deprecated | ||||
| public boolean isSymbolicLink(File parent, String name) | |||||
| public boolean isSymbolicLink(final File parent, final String name) | |||||
| throws IOException { | throws IOException { | ||||
| SymbolicLinkUtils u = SymbolicLinkUtils.getSymbolicLinkUtils(); | |||||
| if (parent == null) { | 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)); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -30,6 +30,9 @@ import org.apache.tools.ant.taskdefs.Execute; | |||||
| * a symbolic link based on the absent support for them in Java. | * a symbolic link based on the absent support for them in Java. | ||||
| * | * | ||||
| * @since Ant 1.8.0 | * @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 { | public class SymbolicLinkUtils { | ||||
| private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); | private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); | ||||