Skip to content

Commit

Permalink
The Consumer to IOUtils.close(Closeable, IOConsumer) now accepts wrapped
Browse files Browse the repository at this point in the history
Exception, not just IOException
  • Loading branch information
garydgregory committed Feb 23, 2025
1 parent 3b77766 commit 1d2019f
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 15 deletions.
1 change: 1 addition & 0 deletions src/changes/changes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ The <action> type attribute can be add,update,fix,remove.
<action dev="ggregory" type="fix" issue="IO-868" due-to="Julian Reschke, Gary Gregory">Improve Javadoc for a BoundedInputStream builder() throwing IOException.</action>
<action dev="ggregory" type="fix" issue="IO-868" due-to="Julian Reschke, Gary Gregory">Improve Javadoc for all implementations of AbstractOriginSupplier#get().</action>
<action dev="ggregory" type="fix" due-to="Gary Gregory">The Consumer to IOUtils.closeQuietly(Closeable, Consumer) now accepts Exception, not just IOException.</action>
<action dev="ggregory" type="fix" due-to="Gary Gregory">The Consumer to IOUtils.close(Closeable, IOConsumer) now accepts wrapped Exception, not just IOException.</action>
<!-- ADD -->
<action dev="ggregory" type="add" issue="IO-860" due-to="Nico Strecker, Gary Gregory">Add ThrottledInputStream.Builder.setMaxBytes(long, ChronoUnit).</action>
<action dev="ggregory" type="add" due-to="Gary Gregory">Add IOIterable.</action>
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/org/apache/commons/io/IOUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,10 @@ public static void close(final Closeable closeable, final IOConsumer<IOException
if (consumer != null) {
consumer.accept(e);
}
} catch (final Exception e) {
if (consumer != null) {
consumer.accept(new IOException(e));
}
}
}
}
Expand Down
46 changes: 31 additions & 15 deletions src/test/java/org/apache/commons/io/IOUtilsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
import org.apache.commons.io.test.TestUtils;
import org.apache.commons.io.test.ThrowOnCloseReader;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
Expand Down Expand Up @@ -321,28 +322,43 @@ public void testClose() {

@Test
public void testCloseConsumer() {
// null consumer
final Closeable nullCloseable = null;
assertDoesNotThrow(() -> IOUtils.close(nullCloseable, null)); // null consumer
assertDoesNotThrow(() -> IOUtils.close(new StringReader("s"), null)); // null consumer
assertDoesNotThrow(() -> IOUtils.close(new ThrowOnCloseReader(new StringReader("s")), null)); // null consumer

final IOConsumer<IOException> nullConsumer = null; // null consumer doesn't throw
assertDoesNotThrow(() -> IOUtils.close(nullCloseable, null));
assertDoesNotThrow(() -> IOUtils.close(new StringReader("s"), null));
assertDoesNotThrow(() -> IOUtils.close(new ThrowOnCloseReader(new StringReader("s")), null));
// null consumer doesn't throw
final IOConsumer<IOException> nullConsumer = null;
assertDoesNotThrow(() -> IOUtils.close(nullCloseable, nullConsumer));
assertDoesNotThrow(() -> IOUtils.close(new StringReader("s"), nullConsumer));
assertDoesNotThrow(() -> IOUtils.close(new ThrowOnCloseReader(new StringReader("s")), nullConsumer));

final IOConsumer<IOException> silentConsumer = IOConsumer.noop(); // noop consumer doesn't throw
// noop consumer doesn't throw
final IOConsumer<IOException> silentConsumer = IOConsumer.noop();
assertDoesNotThrow(() -> IOUtils.close(nullCloseable, silentConsumer));
assertDoesNotThrow(() -> IOUtils.close(new StringReader("s"), silentConsumer));
assertDoesNotThrow(() -> IOUtils.close(new ThrowOnCloseReader(new StringReader("s")), silentConsumer));

final IOConsumer<IOException> noisyConsumer = i -> {
throw i;
}; // consumer passes on the throw
assertDoesNotThrow(() -> IOUtils.close(nullCloseable, noisyConsumer)); // no throw
assertDoesNotThrow(() -> IOUtils.close(new StringReader("s"), noisyConsumer)); // no throw
assertThrows(IOException.class,
() -> IOUtils.close(new ThrowOnCloseReader(new StringReader("s")), noisyConsumer)); // closeable throws
// consumer passes on the throw
final IOConsumer<IOException> noisyConsumer = ExceptionUtils::rethrow;
// no throw
assertDoesNotThrow(() -> IOUtils.close(nullCloseable, noisyConsumer));
// no throw
assertDoesNotThrow(() -> IOUtils.close(new StringReader("s"), noisyConsumer));
// closeable throws
assertThrows(IOException.class, () -> IOUtils.close(new ThrowOnCloseReader(new StringReader("s")), noisyConsumer));
// consumes other than IOException
final AtomicBoolean b = new AtomicBoolean();
final IOConsumer<IOException> consumer = e -> b.set(true);
// IOException subclass
assertDoesNotThrow(() -> IOUtils.close(new BrokenOutputStream((Throwable) new EOFException()), consumer));
assertTrue(b.get());
b.set(false);
// RuntimeException
assertDoesNotThrow(() -> IOUtils.close(new BrokenOutputStream(new RuntimeException()), consumer));
assertTrue(b.get());
b.set(false);
// RuntimeException subclass
assertDoesNotThrow(() -> IOUtils.close(new BrokenOutputStream(new UnsupportedOperationException()), consumer));
assertTrue(b.get());
}

@Test
Expand Down

0 comments on commit 1d2019f

Please sign in to comment.