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 3816c57 [IO-613] Add classes ClosedReader and CloseShieldReader. Closes #84. Applied modified patch from Rob Spoor. 3816c57 is described below commit 3816c572bc1dea6d2661a4c86082a4953526c059 Author: Gary Gregory <gardgreg...@gmail.com> AuthorDate: Wed Aug 7 08:26:53 2019 -0400 [IO-613] Add classes ClosedReader and CloseShieldReader. Closes #84. Applied modified patch from Rob Spoor. --- src/changes/changes.xml | 3 ++ .../commons/io/input/CloseShieldInputStream.java | 3 +- ...ieldInputStream.java => CloseShieldReader.java} | 25 +++++----- ...oseShieldInputStream.java => ClosedReader.java} | 46 ++++++++++------- .../commons/io/input/CloseShieldReaderTest.java | 58 ++++++++++++++++++++++ .../apache/commons/io/input/ClosedReaderTest.java | 35 +++++++++++++ 6 files changed, 138 insertions(+), 32 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 875ea25..d37231a 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -113,6 +113,9 @@ The <action> type attribute can be add,update,fix,remove. <action issue="IO-612" dev="ggregory" type="add" due-to="Rob Spoor, Gary Gregory"> Add class TeeReader. </action> + <action issue="IO-613" dev="ggregory" type="add" due-to="Rob Spoor, Gary Gregory"> + Add classes ClosedReader and CloseShieldReader. #84. + </action> </release> <release version="2.6" date="2017-10-15" description="Java 7 required, Java 9 supported."> 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 5b66f84..0463506 100644 --- a/src/main/java/org/apache/commons/io/input/CloseShieldInputStream.java +++ b/src/main/java/org/apache/commons/io/input/CloseShieldInputStream.java @@ -24,6 +24,7 @@ import java.io.InputStream; * This class is typically used in cases where an input stream needs to be * passed to a component that wants to explicitly close the stream even if * more input would still be available to other components. + * </p> * * @since 1.4 */ @@ -46,7 +47,7 @@ public class CloseShieldInputStream extends ProxyInputStream { */ @Override public void close() { - in = new ClosedInputStream(); + in = ClosedInputStream.CLOSED_INPUT_STREAM; } } diff --git a/src/main/java/org/apache/commons/io/input/CloseShieldInputStream.java b/src/main/java/org/apache/commons/io/input/CloseShieldReader.java similarity index 60% copy from src/main/java/org/apache/commons/io/input/CloseShieldInputStream.java copy to src/main/java/org/apache/commons/io/input/CloseShieldReader.java index 5b66f84..ca8f1bc 100644 --- a/src/main/java/org/apache/commons/io/input/CloseShieldInputStream.java +++ b/src/main/java/org/apache/commons/io/input/CloseShieldReader.java @@ -16,37 +16,38 @@ */ package org.apache.commons.io.input; -import java.io.InputStream; +import java.io.Reader; /** - * Proxy stream that prevents the underlying input stream from being closed. + * Proxy stream that prevents the underlying reader from being closed. * <p> - * This class is typically used in cases where an input stream needs to be - * passed to a component that wants to explicitly close the stream even if + * This class is typically used in cases where a reader needs to be + * passed to a component that wants to explicitly close the reader even if * more input would still be available to other components. + * <p> * - * @since 1.4 + * @since 2.7 */ -public class CloseShieldInputStream extends ProxyInputStream { +public class CloseShieldReader extends ProxyReader { /** - * Creates a proxy that shields the given input stream from being + * Creates a proxy that shields the given reader from being * closed. * - * @param in underlying input stream + * @param in underlying reader */ - public CloseShieldInputStream(final InputStream in) { + public CloseShieldReader(final Reader in) { super(in); } /** - * Replaces the underlying input stream with a {@link ClosedInputStream} - * sentinel. The original input stream will remain open, but this proxy + * Replaces the underlying reader with a {@link ClosedReader} + * sentinel. The original reader will remain open, but this proxy * will appear closed. */ @Override public void close() { - in = new ClosedInputStream(); + in = ClosedReader.CLOSED_READER; } } diff --git a/src/main/java/org/apache/commons/io/input/CloseShieldInputStream.java b/src/main/java/org/apache/commons/io/input/ClosedReader.java similarity index 52% copy from src/main/java/org/apache/commons/io/input/CloseShieldInputStream.java copy to src/main/java/org/apache/commons/io/input/ClosedReader.java index 5b66f84..a425e0a 100644 --- a/src/main/java/org/apache/commons/io/input/CloseShieldInputStream.java +++ b/src/main/java/org/apache/commons/io/input/ClosedReader.java @@ -16,37 +16,45 @@ */ package org.apache.commons.io.input; -import java.io.InputStream; +import static org.apache.commons.io.IOUtils.EOF; + +import java.io.IOException; +import java.io.Reader; /** - * Proxy stream that prevents the underlying input stream from being closed. + * Closed reader. This reader returns EOF to all attempts to read + * something from it. * <p> - * This class is typically used in cases where an input stream needs to be - * passed to a component that wants to explicitly close the stream even if - * more input would still be available to other components. + * Typically uses of this class include testing for corner cases in methods + * that accept readers and acting as a sentinel value instead of a + * {@code null} reader. + * </p> * - * @since 1.4 + * @since 2.7 */ -public class CloseShieldInputStream extends ProxyInputStream { +public class ClosedReader extends Reader { /** - * Creates a proxy that shields the given input stream from being - * closed. - * - * @param in underlying input stream + * A singleton. */ - public CloseShieldInputStream(final InputStream in) { - super(in); - } + public static final ClosedReader CLOSED_READER = new ClosedReader(); /** - * Replaces the underlying input stream with a {@link ClosedInputStream} - * sentinel. The original input stream will remain open, but this proxy - * will appear closed. + * Returns -1 to indicate that the stream is closed. + * + * @param cbuf ignored + * @param off ignored + * @param len ignored + * @return always -1 */ @Override - public void close() { - in = new ClosedInputStream(); + public int read(final char[] cbuf, final int off, final int len) { + return EOF; + } + + @Override + public void close() throws IOException { + // noop } } diff --git a/src/test/java/org/apache/commons/io/input/CloseShieldReaderTest.java b/src/test/java/org/apache/commons/io/input/CloseShieldReaderTest.java new file mode 100644 index 0000000..6c6d659 --- /dev/null +++ b/src/test/java/org/apache/commons/io/input/CloseShieldReaderTest.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.io.input; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; + +import java.io.IOException; +import java.io.Reader; + +import org.junit.Before; +import org.junit.Test; + +/** + * JUnit Test Case for {@link CloseShieldReader}. + */ +public class CloseShieldReaderTest { + + private String data; + + private Reader original; + + private Reader shielded; + + @Before + public void setUp() { + data = "xyz"; + original = spy(new CharSequenceReader(data)); + shielded = new CloseShieldReader(original); + } + + @Test + public void testClose() throws IOException { + shielded.close(); + verify(original, never()).close(); + char[] cbuf = new char[10]; + assertEquals("read(cbuf, off, len)", -1, shielded.read(cbuf, 0, 10)); + assertEquals("read(cbuf, off, len)", data.length(), original.read(cbuf, 0, 10)); + assertEquals(data, new String(cbuf, 0, data.length())); + } + +} diff --git a/src/test/java/org/apache/commons/io/input/ClosedReaderTest.java b/src/test/java/org/apache/commons/io/input/ClosedReaderTest.java new file mode 100644 index 0000000..75f8112 --- /dev/null +++ b/src/test/java/org/apache/commons/io/input/ClosedReaderTest.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.io.input; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +/** + * JUnit Test Case for {@link ClosedReader}. + */ +public class ClosedReaderTest { + + @Test + public void testRead() throws Exception { + try (final ClosedReader cr = new ClosedReader()) { + assertEquals("read(cbuf, off, len)", -1, cr.read(new char[10], 0, 10)); + } + } + +}