提交 56fb870b 编写于 作者: A alanb

6907737: (file) FileVisitor and Files.walkFileTree issues

Reviewed-by: sherman
上级 07cfa85d
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.nio.file;
/**
* Checked exception thrown when a file system loop, or cycle, is encountered.
*
* @since 1.7
* @see Files#walkFileTree
*/
public class FileSystemLoopException
extends FileSystemException
{
private static final long serialVersionUID = 4843039591949217617L;
/**
* Constructs an instance of this class.
*
* @param file
* a string identifying the file causing the cycle or {@code null} if
* not known
*/
public FileSystemLoopException(String file) {
super(file);
}
}
......@@ -38,7 +38,6 @@ import sun.nio.fs.BasicFileAttributesHolder;
class FileTreeWalker {
private final boolean followLinks;
private final boolean detectCycles;
private final LinkOption[] linkOptions;
private final FileVisitor<? super Path> visitor;
private final int maxDepth;
......@@ -48,17 +47,15 @@ class FileTreeWalker {
int maxDepth)
{
boolean fl = false;
boolean dc = false;
for (FileVisitOption option: options) {
// will throw NPE if options contains null
switch (option) {
case FOLLOW_LINKS : fl = true; break;
case DETECT_CYCLES : dc = true; break;
case FOLLOW_LINKS : fl = true; break;
default:
throw new AssertionError("Should not get here");
}
}
this.followLinks = fl;
this.detectCycles = fl | dc;
this.linkOptions = (fl) ? new LinkOption[0] :
new LinkOption[] { LinkOption.NOFOLLOW_LINKS };
this.visitor = visitor;
......@@ -68,13 +65,11 @@ class FileTreeWalker {
/**
* Walk file tree starting at the given file
*/
void walk(Path start) {
void walk(Path start) throws IOException {
FileVisitResult result = walk(start,
0,
new ArrayList<AncestorDirectory>());
if (result == null) {
throw new NullPointerException("Visitor returned 'null'");
}
Objects.nonNull(result, "FileVisitor returned null");
}
/**
......@@ -88,11 +83,8 @@ class FileTreeWalker {
private FileVisitResult walk(Path file,
int depth,
List<AncestorDirectory> ancestors)
throws IOException
{
// depth check
if (depth > maxDepth)
return FileVisitResult.CONTINUE;
// if attributes are cached then use them if possible
BasicFileAttributes attrs = null;
if ((depth > 0) &&
......@@ -137,13 +129,13 @@ class FileTreeWalker {
return visitor.visitFileFailed(file, exc);
}
// file is not a directory so invoke visitFile method
if (!attrs.isDirectory()) {
// at maximum depth or file is not a directory
if (depth >= maxDepth || !attrs.isDirectory()) {
return visitor.visitFile(file, attrs);
}
// check for cycles
if (detectCycles) {
// check for cycles when following links
if (followLinks) {
Object key = attrs.fileKey();
// if this directory and ancestor has a file key then we compare
......@@ -153,19 +145,23 @@ class FileTreeWalker {
if (key != null && ancestorKey != null) {
if (key.equals(ancestorKey)) {
// cycle detected
return visitor.visitFile(file, attrs);
return visitor.visitFileFailed(file,
new FileSystemLoopException(file.toString()));
}
} else {
boolean isSameFile = false;
try {
if (file.isSameFile(ancestor.file())) {
// cycle detected
return visitor.visitFile(file, attrs);
}
isSameFile = file.isSameFile(ancestor.file());
} catch (IOException x) {
// ignore
} catch (SecurityException x) {
// ignore
}
if (isSameFile) {
// cycle detected
return visitor.visitFileFailed(file,
new FileSystemLoopException(file.toString()));
}
}
}
......@@ -181,7 +177,7 @@ class FileTreeWalker {
try {
stream = file.newDirectoryStream();
} catch (IOException x) {
return visitor.preVisitDirectoryFailed(file, x);
return visitor.visitFileFailed(file, x);
} catch (SecurityException x) {
// ignore, as per spec
return FileVisitResult.CONTINUE;
......@@ -192,20 +188,14 @@ class FileTreeWalker {
// invoke preVisitDirectory and then visit each entry
try {
result = visitor.preVisitDirectory(file);
result = visitor.preVisitDirectory(file, attrs);
if (result != FileVisitResult.CONTINUE) {
return result;
}
// if an I/O occurs during iteration then a CME is thrown. We
// need to distinguish this from a CME thrown by the visitor.
boolean inAction = false;
try {
for (Path entry: stream) {
inAction = true;
result = walk(entry, depth+1, ancestors);
inAction = false;
// returning null will cause NPE to be thrown
if (result == null || result == FileVisitResult.TERMINATE)
......@@ -215,17 +205,9 @@ class FileTreeWalker {
if (result == FileVisitResult.SKIP_SIBLINGS)
break;
}
} catch (ConcurrentModificationException x) {
// if CME thrown because the iteration failed then remember
// the IOException so that it is notified to postVisitDirectory
if (!inAction) {
// iteration failed
Throwable t = x.getCause();
if (t instanceof IOException)
ioe = (IOException)t;
}
if (ioe == null)
throw x;
} catch (DirectoryIteratorException e) {
// IOException will be notified to postVisitDirectory
ioe = e.getCause();
}
} finally {
try {
......@@ -238,7 +220,7 @@ class FileTreeWalker {
} finally {
// remove key from trail if doing cycle detection
if (detectCycles) {
if (followLinks) {
ancestors.remove(ancestors.size()-1);
}
}
......
......@@ -37,9 +37,5 @@ public enum FileVisitOption {
/**
* Follow symbolic links.
*/
FOLLOW_LINKS,
/**
* Detect cycles in the file tree.
*/
DETECT_CYCLES;
FOLLOW_LINKS;
}
......@@ -40,33 +40,28 @@ import java.io.IOException;
* Path start = ...
* Files.walkFileTree(start, new SimpleFileVisitor&lt;Path&gt;() {
* &#64;Override
* public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
* try {
* file.delete();
* } catch (IOException exc) {
* // failed to delete, do error handling here
* }
* public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
* throws IOException
* {
* file.delete();
* return FileVisitResult.CONTINUE;
* }
* &#64;Override
* public FileVisitResult postVisitDirectory(Path dir, IOException e) {
* if (e == null) {
* try {
* dir.delete();
* } catch (IOException exc) {
* // failed to delete, do error handling here
* }
* } else {
* public FileVisitResult postVisitDirectory(Path dir, IOException e)
* throws IOException
* {
* if (e != null) {
* // directory iteration failed
* throw e;
* }
* dir.delete();
* return FileVisitResult.CONTINUE;
* }
* });
* </pre>
* <p> Furthermore, suppose we want to copy a file tree rooted at a source
* directory to a target location. In that case, symbolic links should be
* followed and the target directory should be created before the entries in
* the directory are copied.
* <p> Furthermore, suppose we want to copy a file tree to a target location.
* In that case, symbolic links should be followed and the target directory
* should be created before the entries in the directory are copied.
* <pre>
* final Path source = ...
* final Path target = ...
......@@ -74,25 +69,21 @@ import java.io.IOException;
* Files.walkFileTree(source, EnumSet.of(FileVisitOption.FOLLOW_LINKS), Integer.MAX_VALUE,
* new SimpleFileVisitor&lt;Path&gt;() {
* &#64;Override
* public FileVisitResult preVisitDirectory(Path dir) {
* public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
* throws IOException
* {
* try {
* dir.copyTo(target.resolve(source.relativize(dir)));
* } catch (FileAlreadyExistsException e) {
* // ignore
* } catch (IOException e) {
* // copy failed, do error handling here
* // skip rest of directory and descendants
* return SKIP_SUBTREE;
* }
* return CONTINUE;
* }
* &#64;Override
* public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
* try {
* file.copyTo(target.resolve(source.relativize(file)));
* } catch (IOException e) {
* // copy failed, do error handling here
* }
* public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
* throws IOException
* {
* file.copyTo(target.resolve(source.relativize(file)));
* return CONTINUE;
* }
* });
......@@ -114,22 +105,16 @@ public interface FileVisitor<T> {
*
* @param dir
* a reference to the directory
* @param attrs
* the directory's basic attributes
*
* @return the visit result
*/
FileVisitResult preVisitDirectory(T dir);
/**
* Invoked for a directory that could not be opened.
*
* @param dir
* a reference to the directory
* @param exc
* the I/O exception thrown from the attempt to open the directory
*
* @return the visit result
* @throws IOException
* if an I/O error occurs
*/
FileVisitResult preVisitDirectoryFailed(T dir, IOException exc);
FileVisitResult preVisitDirectory(T dir, BasicFileAttributes attrs)
throws IOException;
/**
* Invoked for a file in a directory.
......@@ -140,21 +125,30 @@ public interface FileVisitor<T> {
* the file's basic attributes
*
* @return the visit result
*
* @throws IOException
* if an I/O error occurs
*/
FileVisitResult visitFile(T file, BasicFileAttributes attrs);
FileVisitResult visitFile(T file, BasicFileAttributes attrs)
throws IOException;
/**
* Invoked for a file when its basic file attributes could not be read.
* Invoked for a file that could not be visited. This method is invoked
* if the file's attributes could not be read, the file is a directory
* that could not be opened, and other reasons.
*
* @param file
* a reference to the file
* @param exc
* the I/O exception thrown from the attempt to read the file
* attributes
* the I/O exception that prevented the file from being visited
*
* @return the visit result
*
* @throws IOException
* if an I/O error occurs
*/
FileVisitResult visitFileFailed(T file, IOException exc);
FileVisitResult visitFileFailed(T file, IOException exc)
throws IOException;
/**
* Invoked for a directory after entries in the directory, and all of their
......@@ -171,6 +165,10 @@ public interface FileVisitor<T> {
* of the directory to complete prematurely
*
* @return the visit result
*
* @throws IOException
* if an I/O error occurs
*/
FileVisitResult postVisitDirectory(T dir, IOException exc);
FileVisitResult postVisitDirectory(T dir, IOException exc)
throws IOException;
}
......@@ -135,9 +135,9 @@ public final class Files {
* FileVisitor} invoked for each file encountered. File tree traversal
* completes when all accessible files in the tree have been visited, or a
* visit method returns a result of {@link FileVisitResult#TERMINATE
* TERMINATE}. Where a visit method terminates due an uncaught error or
* runtime exception then the traversal is terminated and the error or
* exception is propagated to the caller of this method.
* TERMINATE}. Where a visit method terminates due an {@code IOException},
* an uncaught error, or runtime exception, then the traversal is terminated
* and the error or exception is propagated to the caller of this method.
*
* <p> For each file encountered this method attempts to gets its {@link
* java.nio.file.attribute.BasicFileAttributes}. If the file is not a
......@@ -146,12 +146,10 @@ public final class Files {
* due to an I/O exception, then the {@link FileVisitor#visitFileFailed
* visitFileFailed} method is invoked with the I/O exception.
*
* <p> Where the file is a directory, this method attempts to open it by
* invoking its {@link Path#newDirectoryStream newDirectoryStream} method.
* Where the directory could not be opened, due to an {@code IOException},
* then the {@link FileVisitor#preVisitDirectoryFailed preVisitDirectoryFailed}
* method is invoked with the I/O exception, after which, the file tree walk
* continues, by default, at the next <em>sibling</em> of the directory.
* <p> Where the file is a directory, and the directory could not be opened,
* then the {@code visitFileFailed} method is invoked with the I/O exception,
* after which, the file tree walk continues, by default, at the next
* <em>sibling</em> of the directory.
*
* <p> Where the directory is opened successfully, then the entries in the
* directory, and their <em>descendants</em> are visited. When all entries
......@@ -171,26 +169,25 @@ public final class Files {
* method is invoked as specified above).
*
* <p> If the {@code options} parameter contains the {@link
* FileVisitOption#DETECT_CYCLES DETECT_CYCLES} or {@link
* FileVisitOption#FOLLOW_LINKS FOLLOW_LINKS} options then this method keeps
* FileVisitOption#FOLLOW_LINKS FOLLOW_LINKS} option then this method keeps
* track of directories visited so that cycles can be detected. A cycle
* arises when there is an entry in a directory that is an ancestor of the
* directory. Cycle detection is done by recording the {@link
* java.nio.file.attribute.BasicFileAttributes#fileKey file-key} of directories,
* or if file keys are not available, by invoking the {@link Path#isSameFile
* isSameFile} method to test if a directory is the same file as an
* ancestor. When a cycle is detected the {@link FileVisitor#visitFile
* visitFile} is invoked with the attributes of the directory. The {@link
* java.nio.file.attribute.BasicFileAttributes#isDirectory isDirectory}
* method may be used to test if the file is a directory and that a cycle is
* detected. The {@code preVisitDirectory} and {@code postVisitDirectory}
* methods are not invoked.
* ancestor. When a cycle is detected it is treated as an I/O error, and the
* {@link FileVisitor#visitFileFailed visitFileFailed} method is invoked with
* an instance of {@link FileSystemLoopException}.
*
* <p> The {@code maxDepth} parameter is the maximum number of levels of
* directories to visit. A value of {@code 0} means that only the starting
* file is visited, unless denied by the security manager. A value of
* {@link Integer#MAX_VALUE MAX_VALUE} may be used to indicate that all
* levels should be visited.
* levels should be visited. The {@code visitFile} method is invoked for all
* files, including directories, encountered at {@code maxDepth}, unless the
* basic file attributes cannot be read, in which case the {@code
* visitFileFailed} method is invoked.
*
* <p> If a visitor returns a result of {@code null} then {@code
* NullPointerException} is thrown.
......@@ -215,11 +212,14 @@ public final class Files {
* In the case of the default provider, the {@link
* SecurityManager#checkRead(String) checkRead} method is invoked
* to check read access to the directory.
* @throws IOException
* If an I/O error is thrown by a visitor method
*/
public static void walkFileTree(Path start,
Set<FileVisitOption> options,
int maxDepth,
FileVisitor<? super Path> visitor)
throws IOException
{
if (maxDepth < 0)
throw new IllegalArgumentException("'maxDepth' is negative");
......@@ -245,8 +245,12 @@ public final class Files {
* In the case of the default provider, the {@link
* SecurityManager#checkRead(String) checkRead} method is invoked
* to check read access to the directory.
* @throws IOException
* If an I/O error is thrown by a visitor method
*/
public static void walkFileTree(Path start, FileVisitor<? super Path> visitor) {
public static void walkFileTree(Path start, FileVisitor<? super Path> visitor)
throws IOException
{
walkFileTree(start,
EnumSet.noneOf(FileVisitOption.class),
Integer.MAX_VALUE,
......
......@@ -27,7 +27,7 @@ package java.nio.file;
import java.nio.file.attribute.BasicFileAttributes;
import java.io.IOException;
import java.io.IOError;
import java.util.Objects;
/**
* A simple visitor of files with default behavior to visit all files and to
......@@ -47,14 +47,6 @@ public class SimpleFileVisitor<T> implements FileVisitor<T> {
protected SimpleFileVisitor() {
}
/**
* Throws NullPointerException if obj is null.
*/
private static void checkNotNull(Object obj) {
if (obj == null)
throw new NullPointerException();
}
/**
* Invoked for a directory before entries in the directory are visited.
*
......@@ -62,28 +54,14 @@ public class SimpleFileVisitor<T> implements FileVisitor<T> {
* CONTINUE}.
*/
@Override
public FileVisitResult preVisitDirectory(T dir) {
checkNotNull(dir);
public FileVisitResult preVisitDirectory(T dir, BasicFileAttributes attrs)
throws IOException
{
Objects.nonNull(dir);
Objects.nonNull(attrs);
return FileVisitResult.CONTINUE;
}
/**
* Invoked for a directory that could not be opened.
*
* <p> Unless overridden, this method throws {@link IOError} with the I/O
* exception as cause.
*
* @throws IOError
* with the I/O exception thrown when the attempt to open the
* directory failed
*/
@Override
public FileVisitResult preVisitDirectoryFailed(T dir, IOException exc) {
checkNotNull(dir);
checkNotNull(exc);
throw new IOError(exc);
}
/**
* Invoked for a file in a directory.
*
......@@ -91,27 +69,26 @@ public class SimpleFileVisitor<T> implements FileVisitor<T> {
* CONTINUE}.
*/
@Override
public FileVisitResult visitFile(T file, BasicFileAttributes attrs) {
checkNotNull(file);
checkNotNull(attrs);
public FileVisitResult visitFile(T file, BasicFileAttributes attrs)
throws IOException
{
Objects.nonNull(file);
Objects.nonNull(attrs);
return FileVisitResult.CONTINUE;
}
/**
* Invoked for a file when its basic file attributes could not be read.
*
* <p> Unless overridden, this method throws {@link IOError} with the I/O
* exception as cause.
* Invoked for a file that could not be visited.
*
* @throws IOError
* with the I/O exception thrown when the attempt to read the file
* attributes failed
* <p> Unless overridden, this method re-throws the I/O exception that prevented
* the file from being visited.
*/
@Override
public FileVisitResult visitFileFailed(T file, IOException exc) {
checkNotNull(file);
checkNotNull(exc);
throw new IOError(exc);
public FileVisitResult visitFileFailed(T file, IOException exc)
throws IOException
{
Objects.nonNull(file);
throw exc;
}
/**
......@@ -120,18 +97,16 @@ public class SimpleFileVisitor<T> implements FileVisitor<T> {
*
* <p> Unless overridden, this method returns {@link FileVisitResult#CONTINUE
* CONTINUE} if the directory iteration completes without an I/O exception;
* otherwise this method throws {@link IOError} with the I/O exception as
* cause.
*
* @throws IOError
* with the I/O exception thrown when iteration of the directory
* completed prematurely due to an I/O error
* otherwise this method re-throws the I/O exception that caused the iteration
* of the directory to terminate prematurely.
*/
@Override
public FileVisitResult postVisitDirectory(T dir, IOException exc) {
checkNotNull(dir);
public FileVisitResult postVisitDirectory(T dir, IOException exc)
throws IOException
{
Objects.nonNull(dir);
if (exc != null)
throw new IOError(exc);
throw exc;
return FileVisitResult.CONTINUE;
}
}
......@@ -285,17 +285,11 @@ public class Chmod {
}
@Override
public FileVisitResult preVisitDirectory(FileRef dir) {
public FileVisitResult preVisitDirectory(FileRef dir, BasicFileAttributes attrs) {
chmod(dir, changer);
return CONTINUE;
}
@Override
public FileVisitResult preVisitDirectoryFailed(FileRef dir, IOException exc) {
System.err.println("WARNING: " + exc);
return CONTINUE;
}
@Override
public FileVisitResult visitFile(FileRef file, BasicFileAttributes attrs) {
chmod(file, changer);
......
......@@ -85,7 +85,7 @@ public class Copy {
}
@Override
public FileVisitResult preVisitDirectory(Path dir) {
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
// before visiting entries in a directory we copy the directory
// (okay if directory already exists).
CopyOption[] options = (preserve) ?
......@@ -103,20 +103,10 @@ public class Copy {
return CONTINUE;
}
@Override
public FileVisitResult preVisitDirectoryFailed(Path dir, IOException exc) {
System.err.format("Unable to copy: %s: %s%n", dir, exc);
return CONTINUE;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
if (attrs.isDirectory()) {
System.err.println("cycle detected: " + file);
} else {
copyFile(file, target.resolve(source.relativize(file)),
prompt, preserve);
}
copyFile(file, target.resolve(source.relativize(file)),
prompt, preserve);
return CONTINUE;
}
......@@ -137,7 +127,11 @@ public class Copy {
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) {
System.err.format("Unable to copy: %s: %s%n", file, exc);
if (exc instanceof FileSystemLoopException) {
System.err.println("cycle detected: " + file);
} else {
System.err.format("Unable to copy: %s: %s%n", file, exc);
}
return CONTINUE;
}
}
......
......@@ -78,12 +78,10 @@ public class WatchDir {
// register directory and sub-directories
Files.walkFileTree(start, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path dir) {
try {
register(dir);
} catch (IOException x) {
throw new IOError(x);
}
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
throws IOException
{
register(dir);
return FileVisitResult.CONTINUE;
}
});
......
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.nio.file.*;
import java.nio.file.attribute.*;
import java.io.IOException;
import java.util.*;
/**
* Unit test for Files.walkFileTree to test maxDepth parameter
*/
public class MaxDepth {
public static void main(String[] args) throws Exception {
final Path top = Paths.get(args[0]);
for (int i=0; i<5; i++) {
Set<FileVisitOption> opts = Collections.emptySet();
final int maxDepth = i;
Files.walkFileTree(top, opts, maxDepth, new SimpleFileVisitor<Path>() {
// compute depth based on relative path to top directory
private int depth(Path file) {
Path rp = file.relativize(top);
return (rp == null) ? 0 : rp.getNameCount();
}
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
int d = depth(dir);
if (d == maxDepth)
throw new RuntimeException("Should not open directories at maxDepth");
if (d > maxDepth)
throw new RuntimeException("Too deep");
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
int d = depth(file);
if (d > maxDepth)
throw new RuntimeException("Too deep");
return FileVisitResult.CONTINUE;
}
});
}
}
}
......@@ -30,6 +30,7 @@
import java.nio.file.*;
import java.nio.file.attribute.Attributes;
import java.nio.file.attribute.BasicFileAttributes;
import java.io.IOException;
import java.util.*;
......@@ -117,25 +118,25 @@ public class Misc {
SimpleFileVisitor<Path> visitor = new SimpleFileVisitor<Path>() { };
boolean ranTheGauntlet = false;
try { visitor.preVisitDirectory(null);
BasicFileAttributes attrs = Attributes.readBasicFileAttributes(Paths.get("."));
try { visitor.preVisitDirectory(null, attrs);
} catch (NullPointerException x0) {
try { visitor.preVisitDirectoryFailed(null, new IOException());
try { visitor.preVisitDirectory(dir, null);
} catch (NullPointerException x1) {
try { visitor.preVisitDirectoryFailed(dir, null);
try { visitor.visitFile(null, attrs);
} catch (NullPointerException x2) {
try { visitor.visitFile(null, Attributes.readBasicFileAttributes(Paths.get(".")));
} catch (NullPointerException x3) {
try { visitor.visitFile(dir, null);
} catch (NullPointerException x4) {
} catch (NullPointerException x3) {
try { visitor.visitFileFailed(null, new IOException());
} catch (NullPointerException x5) {
} catch (NullPointerException x4) {
try { visitor.visitFileFailed(dir, null);
} catch (NullPointerException x6) {
} catch (NullPointerException x5) {
try { visitor.postVisitDirectory(null, new IOException());
} catch (NullPointerException x7) {
} catch (NullPointerException x6) {
// if we get here then all visit* methods threw NPE as expected
ranTheGauntlet = true;
}}}}}}}}
}}}}}}}
if (!ranTheGauntlet)
throw new RuntimeException("A visit method did not throw NPE");
}
......
......@@ -56,29 +56,34 @@ public class PrintFileTree {
final boolean reportCycles = printCycles;
Files.walkFileTree(dir, options, Integer.MAX_VALUE, new FileVisitor<FileRef>() {
public FileVisitResult preVisitDirectory(FileRef dir) {
@Override
public FileVisitResult preVisitDirectory(FileRef dir, BasicFileAttributes attrs) {
System.out.println(dir);
return FileVisitResult.CONTINUE;
}
public FileVisitResult preVisitDirectoryFailed(FileRef dir, IOException exc) {
exc.printStackTrace();
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(FileRef file, BasicFileAttributes attrs) {
if (!attrs.isDirectory() || reportCycles)
System.out.println(file);
return FileVisitResult.CONTINUE;
}
public FileVisitResult postVisitDirectory(FileRef dir, IOException exc) {
if (exc != null) {
exc.printStackTrace();
return FileVisitResult.TERMINATE;
}
@Override
public FileVisitResult postVisitDirectory(FileRef dir, IOException exc)
throws IOException
{
if (exc != null)
throw exc;
return FileVisitResult.CONTINUE;
}
public FileVisitResult visitFileFailed(FileRef file, IOException exc) {
exc.printStackTrace();
return FileVisitResult.TERMINATE;
@Override
public FileVisitResult visitFileFailed(FileRef file, IOException exc)
throws IOException
{
if (reportCycles && (exc instanceof FileSystemLoopException)) {
System.out.println(file);
return FileVisitResult.CONTINUE;
}
throw exc;
}
});
}
......
......@@ -54,32 +54,28 @@ public class SkipSiblings {
public static void main(String[] args) throws Exception {
Path dir = Paths.get(args[0]);
Files.walkFileTree(dir, new FileVisitor<Path>() {
public FileVisitResult preVisitDirectory(Path dir) {
Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
check(dir);
if (skip(dir))
return FileVisitResult.SKIP_SIBLINGS;
return FileVisitResult.CONTINUE;
}
public FileVisitResult preVisitDirectoryFailed(Path dir, IOException exc) {
throw new RuntimeException(exc);
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
check(file);
if (skip(file))
return FileVisitResult.SKIP_SIBLINGS;
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException x) {
if (x != null)
throw new RuntimeException(x);
check(dir);
return FileVisitResult.CONTINUE;
}
public FileVisitResult visitFileFailed(Path file, IOException x) {
throw new RuntimeException(x);
}
});
}
}
......@@ -49,22 +49,19 @@ public class TerminateWalk {
public static void main(String[] args) throws Exception {
Path dir = Paths.get(args[0]);
Files.walkFileTree(dir, new FileVisitor<Path>() {
public FileVisitResult preVisitDirectory(Path dir) {
return maybeTerminate();
}
public FileVisitResult preVisitDirectoryFailed(Path dir, IOException exc) {
Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
return maybeTerminate();
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
return maybeTerminate();
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException x) {
return maybeTerminate();
}
public FileVisitResult visitFileFailed(Path file, IOException x) {
return maybeTerminate();
}
});
}
}
......@@ -116,7 +116,7 @@ public class WalkWithSecurity {
}
@Override
public FileVisitResult preVisitDirectory(Path dir) {
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
System.out.println(dir);
count++;
return FileVisitResult.CONTINUE;
......
......@@ -22,9 +22,9 @@
#
# @test
# @bug 4313887
# @bug 4313887 6907737
# @summary Unit test for walkFileTree method
# @build CreateFileTree PrintFileTree SkipSiblings TerminateWalk
# @build CreateFileTree PrintFileTree SkipSiblings TerminateWalk MaxDepth
# @run shell walk_file_tree.sh
# if TESTJAVA isn't set then we assume an interactive run.
......@@ -84,6 +84,10 @@ if [ $? != 0 ]; then failures=`expr $failures + 1`; fi
$JAVA TerminateWalk "$ROOT"
if [ $? != 0 ]; then failures=`expr $failures + 1`; fi
# test maxDepth
$JAVA MaxDepth "$ROOT"
if [ $? != 0 ]; then failures=`expr $failures + 1`; fi
# clean-up
rm -r "$ROOT"
......
......@@ -44,15 +44,10 @@ public class TestUtil {
return createTemporaryDirectory(System.getProperty("java.io.tmpdir"));
}
static void removeAll(Path dir) {
static void removeAll(Path dir) throws IOException {
Files.walkFileTree(dir, new FileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path dir) {
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult preVisitDirectoryFailed(Path dir, IOException exc) {
System.err.format("Error occured accessing directory %s\n", dir, exc);
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
return FileVisitResult.CONTINUE;
}
@Override
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册