FULL PRODUCT VERSION :
java version "1.8.0_112"
Java(TM) SE Runtime Environment (build 1.8.0_112-b15)
Java HotSpot(TM) Client VM (build 25.112-b15, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.1.7601]
A DESCRIPTION OF THE PROBLEM :
A logical error in java.nio.file.FileTreeWalker:
reaching the maxDepth and the current entry being a directory causes FileVisitor.visitFile to be called instead of the directory-methods.
The problematic code (starting at line 285):
// at maximum depth or file is not a directory
int depth = stack.size();
if (depth >= maxDepth || !attrs.isDirectory()) {
return new Event(EventType.ENTRY, entry, attrs);
}
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
in Files.walkFileTree with a max-depth and having only directories in maxDepth's subfolders.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.io.IOException;
import java.io.PrintStream;
import java.io.UncheckedIOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.HashSet;
public class TestFTW {
static void testFileTreeWalker() {
try {
final PrintStream verbose = System.out;
verbose.println(
"java version " + System.getProperty("java.version", "unknown"));
Files.createDirectories(Paths.get(".\\subtest\\subtest1"));
final Path start = Paths.get(".\\subtest");
Files.walkFileTree(start, new HashSet<>(), 1,
new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(final Path dir,
final BasicFileAttributes attrs) throws IOException {
verbose.println("preVisitDirectory: " + dir);
if (dir.equals(start))
return FileVisitResult.CONTINUE;
verbose.println("preVisitDirectory: doing something");
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(final Path dir,
final IOException exc) throws IOException {
verbose.println("postVisitDirectory: " + dir);
if (dir.equals(start))
return FileVisitResult.CONTINUE;
verbose.println("postVisitDirectory: doing something");
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(final Path file,
final BasicFileAttributes attrs) throws IOException {
verbose.println("visitFile: " + file);
if (Files.isDirectory(file)) {
throw new IllegalStateException("java error in visitFile: " + file
+ " is directory not a regular file - attrs.isDirectory() = "
+ attrs.isDirectory() + ", attrs.isRegularFile() = "
+ attrs.isRegularFile());
}
verbose.println("visitFile: doing something");
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFileFailed(final Path file,
final IOException exc) throws IOException {
throw exc;
}
});
} catch (final IOException e) {
throw new UncheckedIOException(e);
}
}
public static void main(final String[] args) {
testFileTreeWalker();
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
All FileVisitors have to check the attributes in FileVisitor.visitFile().
java version "1.8.0_112"
Java(TM) SE Runtime Environment (build 1.8.0_112-b15)
Java HotSpot(TM) Client VM (build 25.112-b15, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.1.7601]
A DESCRIPTION OF THE PROBLEM :
A logical error in java.nio.file.FileTreeWalker:
reaching the maxDepth and the current entry being a directory causes FileVisitor.visitFile to be called instead of the directory-methods.
The problematic code (starting at line 285):
// at maximum depth or file is not a directory
int depth = stack.size();
if (depth >= maxDepth || !attrs.isDirectory()) {
return new Event(EventType.ENTRY, entry, attrs);
}
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
in Files.walkFileTree with a max-depth and having only directories in maxDepth's subfolders.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.io.IOException;
import java.io.PrintStream;
import java.io.UncheckedIOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.HashSet;
public class TestFTW {
static void testFileTreeWalker() {
try {
final PrintStream verbose = System.out;
verbose.println(
"java version " + System.getProperty("java.version", "unknown"));
Files.createDirectories(Paths.get(".\\subtest\\subtest1"));
final Path start = Paths.get(".\\subtest");
Files.walkFileTree(start, new HashSet<>(), 1,
new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(final Path dir,
final BasicFileAttributes attrs) throws IOException {
verbose.println("preVisitDirectory: " + dir);
if (dir.equals(start))
return FileVisitResult.CONTINUE;
verbose.println("preVisitDirectory: doing something");
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(final Path dir,
final IOException exc) throws IOException {
verbose.println("postVisitDirectory: " + dir);
if (dir.equals(start))
return FileVisitResult.CONTINUE;
verbose.println("postVisitDirectory: doing something");
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(final Path file,
final BasicFileAttributes attrs) throws IOException {
verbose.println("visitFile: " + file);
if (Files.isDirectory(file)) {
throw new IllegalStateException("java error in visitFile: " + file
+ " is directory not a regular file - attrs.isDirectory() = "
+ attrs.isDirectory() + ", attrs.isRegularFile() = "
+ attrs.isRegularFile());
}
verbose.println("visitFile: doing something");
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFileFailed(final Path file,
final IOException exc) throws IOException {
throw exc;
}
});
} catch (final IOException e) {
throw new UncheckedIOException(e);
}
}
public static void main(final String[] args) {
testFileTreeWalker();
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
All FileVisitors have to check the attributes in FileVisitor.visitFile().