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 68be2fbbe Add and use IOUtils.closeQuietly(Closeable, Throwable) (#818)
68be2fbbe is described below
commit 68be2fbbe46d26a854d6a8af6e38a8f60a4b49a0
Author: Gary Gregory <[email protected]>
AuthorDate: Thu Dec 11 16:20:55 2025 -0500
Add and use IOUtils.closeQuietly(Closeable, Throwable) (#818)
* [IO-856] Try test on all OSs for GitHub CI
* Add and use IOUtils.closeQuietly(Closeable, Throwable)
---
src/main/java/org/apache/commons/io/FileUtils.java | 2 +-
src/main/java/org/apache/commons/io/IOUtils.java | 37 ++++++++++++++++++++--
.../java/org/apache/commons/io/LineIterator.java | 3 +-
.../commons/io/output/FileWriterWithEncoding.java | 6 +---
.../java/org/apache/commons/io/IOUtilsTest.java | 13 ++++++++
5 files changed, 51 insertions(+), 10 deletions(-)
diff --git a/src/main/java/org/apache/commons/io/FileUtils.java
b/src/main/java/org/apache/commons/io/FileUtils.java
index 523c2c1fd..a24ab813a 100644
--- a/src/main/java/org/apache/commons/io/FileUtils.java
+++ b/src/main/java/org/apache/commons/io/FileUtils.java
@@ -2290,7 +2290,7 @@ public static LineIterator lineIterator(final File file,
final String charsetNam
inputStream = Files.newInputStream(file.toPath());
return IOUtils.lineIterator(inputStream, charsetName);
} catch (final IOException | RuntimeException ex) {
- IOUtils.closeQuietly(inputStream, ex::addSuppressed);
+ IOUtils.closeQuietly(inputStream, ex);
throw ex;
}
}
diff --git a/src/main/java/org/apache/commons/io/IOUtils.java
b/src/main/java/org/apache/commons/io/IOUtils.java
index 09a018b03..8a4057ae5 100644
--- a/src/main/java/org/apache/commons/io/IOUtils.java
+++ b/src/main/java/org/apache/commons/io/IOUtils.java
@@ -780,7 +780,7 @@ public static void close(final URLConnection conn) {
* @param closeable the object to close, may be null.
*/
private static void closeQ(final Closeable closeable) {
- closeQuietly(closeable, null);
+ closeQuietly(closeable, (Consumer<Exception>) null);
}
/**
@@ -824,7 +824,40 @@ private static void closeQ(final Closeable closeable) {
* @see Throwable#addSuppressed(Throwable)
*/
public static void closeQuietly(final Closeable closeable) {
- closeQuietly(closeable, null);
+ closeQuietly(closeable, (Consumer<Exception>) null);
+ }
+
+ /**
+ * Closes a {@link Closeable} unconditionally and adds any exception
thrown by the {@code close()} to the given Throwable.
+ *
+ * <p>
+ * For example:
+ * </p>
+ *
+ * <pre>
+ * Closeable closeable = ...;
+ * try {
+ * // process closeable
+ * closeable.close();
+ * } catch (Exception e) {
+ * // error handling
+ * throw IOUtils.closeQuietly(closeable, e);
+ * }
+ * </pre>
+ * <p>
+ * Also consider using a try-with-resources statement where appropriate.
+ * </p>
+ *
+ * @param <T> The Throwable type.
+ * @param closeable The object to close, may be null or already closed.
+ * @param throwable Add the exception throw by the closeable to the given
Throwable.
+ * @return The given Throwable.
+ * @since 2.22.0
+ * @see Throwable#addSuppressed(Throwable)
+ */
+ public static <T extends Throwable> T closeQuietly(final Closeable
closeable, final T throwable) {
+ closeQuietly(closeable, (Consumer<Exception>)
throwable::addSuppressed);
+ return throwable;
}
/**
diff --git a/src/main/java/org/apache/commons/io/LineIterator.java
b/src/main/java/org/apache/commons/io/LineIterator.java
index 293847e7a..2e1bf0169 100644
--- a/src/main/java/org/apache/commons/io/LineIterator.java
+++ b/src/main/java/org/apache/commons/io/LineIterator.java
@@ -135,8 +135,7 @@ public boolean hasNext() {
}
}
} catch (final IOException ioe) {
- IOUtils.closeQuietly(this, ioe::addSuppressed);
- throw new IllegalStateException(ioe);
+ throw new IllegalStateException(IOUtils.closeQuietly(this, ioe));
}
}
diff --git
a/src/main/java/org/apache/commons/io/output/FileWriterWithEncoding.java
b/src/main/java/org/apache/commons/io/output/FileWriterWithEncoding.java
index 42d378cc0..1bb15a37a 100644
--- a/src/main/java/org/apache/commons/io/output/FileWriterWithEncoding.java
+++ b/src/main/java/org/apache/commons/io/output/FileWriterWithEncoding.java
@@ -188,11 +188,7 @@ private static OutputStreamWriter initWriter(final File
file, final Object encod
}
return new OutputStreamWriter(outputStream, (String) encoding);
} catch (final IOException | RuntimeException ex) {
- try {
- IOUtils.close(outputStream);
- } catch (final IOException e) {
- ex.addSuppressed(e);
- }
+ IOUtils.closeQuietly(outputStream, ex);
if (!fileExistedAlready) {
FileUtils.deleteQuietly(file);
}
diff --git a/src/test/java/org/apache/commons/io/IOUtilsTest.java
b/src/test/java/org/apache/commons/io/IOUtilsTest.java
index 033fdffdd..df90ab66e 100644
--- a/src/test/java/org/apache/commons/io/IOUtilsTest.java
+++ b/src/test/java/org/apache/commons/io/IOUtilsTest.java
@@ -20,6 +20,7 @@
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNotSame;
import static org.junit.jupiter.api.Assertions.assertNull;
@@ -539,6 +540,18 @@ void testCloseQuietly_AllCloseableIOException() {
assertDoesNotThrow(() -> IOUtils.closeQuietly((Iterable<Closeable>)
null));
}
+ @SuppressWarnings("resource")
+ @Test
+ void testCloseQuietly_CloseableIOExceptionAddSuppressed() {
+ final Throwable e = new Exception("test").fillInStackTrace();
+ assertEquals(0, e.getSuppressed().length);
+ assertSame(e, IOUtils.closeQuietly(new BrokenInputStream(new
EOFException("Suppressed").fillInStackTrace()), e));
+ assertEquals(1, e.getSuppressed().length);
+ final Throwable suppressed0 = e.getSuppressed()[0];
+ assertInstanceOf(EOFException.class, suppressed0);
+ assertEquals("Suppressed", suppressed0.getMessage());
+ }
+
@Test
void testCloseQuietly_CloseableException() {
// IOException