diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 34101750ad8..5e1b6fe8c44 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -51,6 +51,7 @@ The type attribute can be add,update,fix,remove. Add IOIterator.adapt(Iterable). Add getInputStream() for 'https' and 'http' in URIOrigin #630. Add IOSupplier.getUnchecked(). + Add CloseShieldInputStream.systemIn(InputStream). Add missing unit tests. FileUtils.lastModifiedFileTime(File) calls Objects.requireNonNull() on the wrong object. diff --git a/src/main/java/org/apache/commons/io/input/CloseShieldInputStream.java b/src/main/java/org/apache/commons/io/input/CloseShieldInputStream.java index 03521d90e60..8ca2e16dd96 100644 --- a/src/main/java/org/apache/commons/io/input/CloseShieldInputStream.java +++ b/src/main/java/org/apache/commons/io/input/CloseShieldInputStream.java @@ -30,6 +30,17 @@ */ public class CloseShieldInputStream extends ProxyInputStream { + /** + * Constructs a proxy that only shields {@code System.in} from being closed. + * + * @param inputStream the input stream to wrap + * @return the created proxy + * @since 2.17.0 + */ + public static InputStream systemIn(final InputStream inputStream) { + return inputStream == System.in ? wrap(inputStream) : inputStream; + } + /** * Constructs a proxy that shields the given input stream from being closed. * diff --git a/src/test/java/org/apache/commons/io/input/CloseShieldInputStreamTest.java b/src/test/java/org/apache/commons/io/input/CloseShieldInputStreamTest.java index a839242cf98..7fdc7e9bdae 100644 --- a/src/test/java/org/apache/commons/io/input/CloseShieldInputStreamTest.java +++ b/src/test/java/org/apache/commons/io/input/CloseShieldInputStreamTest.java @@ -18,6 +18,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -33,7 +34,7 @@ public class CloseShieldInputStreamTest { private byte[] data; - private InputStream original; + private InputStream byteArrayInputStream; private InputStream shielded; @@ -42,22 +43,40 @@ public class CloseShieldInputStreamTest { @BeforeEach public void setUp() { data = new byte[] { 'x', 'y', 'z' }; - original = new ByteArrayInputStream(data) { + byteArrayInputStream = new ByteArrayInputStream(data) { @Override public void close() { closed = true; } }; - shielded = CloseShieldInputStream.wrap(original); closed = false; } @Test public void testClose() throws IOException { + shielded = CloseShieldInputStream.wrap(byteArrayInputStream); shielded.close(); assertFalse(closed, "closed"); assertEquals(-1, shielded.read(), "read()"); - assertEquals(data[0], original.read(), "read()"); + assertEquals(data[0], byteArrayInputStream.read(), "read()"); + } + + @Test + public void testSystemInOnSystemInNo() throws IOException { + shielded = CloseShieldInputStream.systemIn(byteArrayInputStream); + shielded.close(); + assertTrue(closed, "closed"); + assertEquals(data[0], shielded.read(), "read()"); + assertEquals(data[1], byteArrayInputStream.read(), "read()"); + } + + @Test + public void testSystemInOnSystemInYes() throws IOException { + shielded = CloseShieldInputStream.systemIn(System.in); + shielded.close(); + assertFalse(closed, "closed"); + assertEquals(-1, shielded.read(), "read()"); + assertEquals(data[0], byteArrayInputStream.read(), "read()"); } }