@@ -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(); | ||||