This is an automated email from the ASF dual-hosted git repository.
ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-io.git
The following commit(s) were added to refs/heads/master by this push:
new 1a8fcd01 [IO-811] Files.walk() direct and indirect callers fail to
close the returned Stream<Path>
1a8fcd01 is described below
commit 1a8fcd01226b7cd547f0e9897d217ef381a94e64
Author: Gary Gregory <[email protected]>
AuthorDate: Sat Sep 30 08:34:16 2023 -0400
[IO-811] Files.walk() direct and indirect callers fail to close the
returned Stream<Path>
- Update Javadoc
- Release resource in test
---
src/main/java/org/apache/commons/io/FileUtils.java | 12 +++--
.../org/apache/commons/io/file/FilesUncheck.java | 60 +++++++++++++++++-----
.../java/org/apache/commons/io/file/PathUtils.java | 11 +++-
.../apache/commons/io/file/FilesUncheckTest.java | 5 +-
4 files changed, 70 insertions(+), 18 deletions(-)
diff --git a/src/main/java/org/apache/commons/io/FileUtils.java
b/src/main/java/org/apache/commons/io/FileUtils.java
index 46275c5f..8a8adca7 100644
--- a/src/main/java/org/apache/commons/io/FileUtils.java
+++ b/src/main/java/org/apache/commons/io/FileUtils.java
@@ -36,6 +36,7 @@ import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.charset.UnsupportedCharsetException;
import java.nio.file.CopyOption;
+import java.nio.file.DirectoryStream;
import java.nio.file.FileVisitOption;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
@@ -2960,13 +2961,16 @@ public class FileUtils {
}
/**
- * Streams over the files in a given directory (and optionally
- * its subdirectories) which match an array of extensions.
+ * Streams over the files in a given directory (and optionally its
subdirectories) which match an array of extensions.
+ * <p>
+ * The returned {@link Stream} may wrap one or more {@link
DirectoryStream}s. When you require timely disposal of file system resources,
use a
+ * {@code try}-with-resources block to ensure invocation of the stream's
{@link Stream#close()} method after the stream operations are completed.
Calling a
+ * closed stream causes a {@link IllegalStateException}.
+ * </p>
*
* @param directory the directory to search in
* @param recursive if true all subdirectories are searched as well
- * @param extensions an array of extensions, ex. {"java","xml"}. If this
- * parameter is {@code null}, all files are returned.
+ * @param extensions an array of extensions, ex. {"java","xml"}. If this
parameter is {@code null}, all files are returned.
* @return an iterator of java.io.File with the matching files
* @throws IOException if an I/O error is thrown when accessing the
starting file.
* @since 2.9.0
diff --git a/src/main/java/org/apache/commons/io/file/FilesUncheck.java
b/src/main/java/org/apache/commons/io/file/FilesUncheck.java
index 02a1febb..02688cac 100644
--- a/src/main/java/org/apache/commons/io/file/FilesUncheck.java
+++ b/src/main/java/org/apache/commons/io/file/FilesUncheck.java
@@ -22,6 +22,7 @@ import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.io.Reader;
import java.io.UncheckedIOException;
import java.nio.channels.SeekableByteChannel;
import java.nio.charset.Charset;
@@ -244,6 +245,10 @@ public final class FilesUncheck {
/**
* Delegates to {@link Files#find(Path, int, BiPredicate,
FileVisitOption...)} throwing {@link UncheckedIOException} instead of {@link
IOException}.
+ * <p>
+ * The returned {@link Stream} wraps a {@link DirectoryStream}. When you
require timely disposal of file system resources, use a {@code
try}-with-resources
+ * block to ensure invocation of the stream's {@link Stream#close()}
method after the stream operations are completed.
+ * </p>
*
* @param start See delegate.
* @param maxDepth See delegate.
@@ -348,6 +353,10 @@ public final class FilesUncheck {
/**
* Delegates to {@link Files#lines(Path)} throwing {@link
UncheckedIOException} instead of {@link IOException}.
+ * <p>
+ * The returned {@link Stream} wraps a {@link Reader}. When you require
timely disposal of file system resources, use a {@code try}-with-resources
block to
+ * ensure invocation of the stream's {@link Stream#close()} method after
the stream operations are completed.
+ * </p>
*
* @param path See delegate.
* @return See delegate.
@@ -359,6 +368,10 @@ public final class FilesUncheck {
/**
* Delegates to {@link Files#lines(Path, Charset)} throwing {@link
UncheckedIOException} instead of {@link IOException}.
+ * <p>
+ * The returned {@link Stream} wraps a {@link Reader}. When you require
timely disposal of file system resources, use a {@code try}-with-resources
block to
+ * ensure invocation of the stream's {@link Stream#close()} method after
the stream operations are completed.
+ * </p>
*
* @param path See delegate.
* @param cs See delegate.
@@ -371,6 +384,10 @@ public final class FilesUncheck {
/**
* Delegates to {@link Files#list(Path)} throwing {@link
UncheckedIOException} instead of {@link IOException}.
+ * <p>
+ * The returned {@link Stream} wraps a {@link DirectoryStream}. When you
require timely disposal of file system resources, use a {@code
try}-with-resources
+ * block to ensure invocation of the stream's {@link Stream#close()}
method after the stream operations are completed.
+ * </p>
*
* @param dir See delegate.
* @return See delegate.
@@ -474,8 +491,11 @@ public final class FilesUncheck {
}
/**
- * Delegates to {@link Files#newDirectoryStream(Path)} throwing {@link
UncheckedIOException} instead of
- * {@link IOException}.
+ * Delegates to {@link Files#newDirectoryStream(Path)} throwing {@link
UncheckedIOException} instead of {@link IOException}.
+ * <p>
+ * If you don't use the try-with-resources construct, then you must call
the stream's {@link Stream#close()} method after iteration is complete to free
any
+ * resources held for the open directory.
+ * </p>
*
* @param dir See delegate.
* @return See delegate.
@@ -485,10 +505,14 @@ public final class FilesUncheck {
}
/**
- * Delegates to {@link Files#newDirectoryStream(Path,
java.nio.file.DirectoryStream.Filter)} throwing
- * {@link UncheckedIOException} instead of {@link IOException}.
+ * Delegates to {@link Files#newDirectoryStream(Path,
java.nio.file.DirectoryStream.Filter)} throwing {@link UncheckedIOException}
instead of
+ * {@link IOException}.
+ * <p>
+ * If you don't use the try-with-resources construct, then you must call
the stream's {@link Stream#close()} method after iteration is complete to free
any
+ * resources held for the open directory.
+ * </p>
*
- * @param dir See delegate.
+ * @param dir See delegate.
* @param filter See delegate.
* @return See delegate.
*/
@@ -499,6 +523,10 @@ public final class FilesUncheck {
/**
* Delegates to {@link Files#newDirectoryStream(Path, String)} throwing
{@link UncheckedIOException} instead of
* {@link IOException}.
+ * <p>
+ * The returned {@link Stream} wraps a {@link DirectoryStream}. When you
require timely disposal of file system resources, use a {@code
try}-with-resources
+ * block to ensure invocation of the stream's {@link Stream#close()}
method after the stream operations are completed.
+ * </p>
*
* @param dir See delegate.
* @param glob See delegate.
@@ -674,10 +702,14 @@ public final class FilesUncheck {
}
/**
- * Delegates to {@link Files#walk(Path, FileVisitOption...)} throwing
{@link UncheckedIOException} instead of
- * {@link IOException}.
+ * Delegates to {@link Files#walk(Path, FileVisitOption...)} throwing
{@link UncheckedIOException} instead of {@link IOException}.
+ * <p>
+ * The returned {@link Stream} may wrap one or more {@link
DirectoryStream}s. When you require timely disposal of file system resources,
use a
+ * {@code try}-with-resources block to ensure invocation of the stream's
{@link Stream#close()} method after the stream operations are completed.
Calling a
+ * closed stream causes a {@link IllegalStateException}.
+ * </p>
*
- * @param start See delegate.
+ * @param start See delegate.
* @param options See delegate.
* @return See delegate.
*/
@@ -686,12 +718,16 @@ public final class FilesUncheck {
}
/**
- * Delegates to {@link Files#walk(Path, int, FileVisitOption...)} throwing
{@link UncheckedIOException} instead of
- * {@link IOException}.
+ * Delegates to {@link Files#walk(Path, int, FileVisitOption...)} throwing
{@link UncheckedIOException} instead of {@link IOException}.
+ * <p>
+ * The returned {@link Stream} may wrap one or more {@link
DirectoryStream}s. When you require timely disposal of file system resources,
use a
+ * {@code try}-with-resources block to ensure invocation of the stream's
{@link Stream#close()} method after the stream operations are completed.
Calling a
+ * closed stream causes a {@link IllegalStateException}.
+ * </p>
*
- * @param start See delegate.
+ * @param start See delegate.
* @param maxDepth See delegate.
- * @param options See delegate.
+ * @param options See delegate.
* @return See delegate.
*/
public static Stream<Path> walk(final Path start, final int maxDepth,
final FileVisitOption... options) {
diff --git a/src/main/java/org/apache/commons/io/file/PathUtils.java
b/src/main/java/org/apache/commons/io/file/PathUtils.java
index 56b2a05c..3cd85f08 100644
--- a/src/main/java/org/apache/commons/io/file/PathUtils.java
+++ b/src/main/java/org/apache/commons/io/file/PathUtils.java
@@ -1182,8 +1182,12 @@ public final class PathUtils {
/**
* Creates a new DirectoryStream for Paths rooted at the given directory.
+ * <p>
+ * If you don't use the try-with-resources construct, then you must call
the stream's {@link Stream#close()} method after iteration is complete to free
any
+ * resources held for the open directory.
+ * </p>
*
- * @param dir the path to the directory to stream.
+ * @param dir the path to the directory to stream.
* @param pathFilter the directory stream filter.
* @return a new instance.
* @throws IOException if an I/O error occurs.
@@ -1751,6 +1755,11 @@ public final class PathUtils {
/**
* Returns a stream of filtered paths.
+ * <p>
+ * The returned {@link Stream} may wrap one or more {@link
DirectoryStream}s. When you require timely disposal of file system resources,
use a
+ * {@code try}-with-resources block to ensure invocation of the stream's
{@link Stream#close()} method after the stream operations are completed.
Calling a
+ * closed stream causes a {@link IllegalStateException}.
+ * </p>
*
* @param start the start path
* @param pathFilter the path filter
diff --git a/src/test/java/org/apache/commons/io/file/FilesUncheckTest.java
b/src/test/java/org/apache/commons/io/file/FilesUncheckTest.java
index 4fa73681..917de24f 100644
--- a/src/test/java/org/apache/commons/io/file/FilesUncheckTest.java
+++ b/src/test/java/org/apache/commons/io/file/FilesUncheckTest.java
@@ -50,6 +50,7 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
+import java.util.stream.Stream;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.function.Uncheck;
@@ -166,7 +167,9 @@ public class FilesUncheckTest {
@Test
public void testFind() {
- assertNotNull(FilesUncheck.find(FILE_PATH_EMPTY, 0, (t, u) -> false));
+ try (Stream<Path> find = FilesUncheck.find(FILE_PATH_EMPTY, 0, (t, u)
-> false)) {
+ assertNotNull(find);
+ }
}
@Test