From abc2c1bfc68e2c8cbaa21aa3adc5092918121033 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sat, 14 Sep 2024 19:01:16 -0400 Subject: [PATCH] Refactoring - Pull up closed state - Move checkOpen() for cleaner reuse --- .../java/org/apache/commons/io/IOUtils.java | 1 + .../commons/io/input/AbstractInputStream.java | 14 +----- .../input/BufferedFileChannelInputStream.java | 2 +- .../org/apache/commons/io/input/Input.java | 39 ++++++++++++++++ .../commons/io/input/ProxyInputStream.java | 2 +- .../input/UnsynchronizedBufferedReader.java | 45 +++++++------------ .../io/input/UnsynchronizedReader.java | 37 +++++++++++++++ 7 files changed, 95 insertions(+), 45 deletions(-) create mode 100644 src/main/java/org/apache/commons/io/input/Input.java diff --git a/src/main/java/org/apache/commons/io/IOUtils.java b/src/main/java/org/apache/commons/io/IOUtils.java index 7f938a40568..817ec76af6f 100644 --- a/src/main/java/org/apache/commons/io/IOUtils.java +++ b/src/main/java/org/apache/commons/io/IOUtils.java @@ -14,6 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.commons.io; import java.io.BufferedInputStream; diff --git a/src/main/java/org/apache/commons/io/input/AbstractInputStream.java b/src/main/java/org/apache/commons/io/input/AbstractInputStream.java index de2f9d8c543..7a300a5f51b 100644 --- a/src/main/java/org/apache/commons/io/input/AbstractInputStream.java +++ b/src/main/java/org/apache/commons/io/input/AbstractInputStream.java @@ -27,18 +27,6 @@ */ public abstract class AbstractInputStream extends InputStream { - /** - * Throws an IOException on false input. - * - * @param isOpen whether the stream is open or not. - * @throws IOException if this instance is closed. - */ - static void checkOpen(final boolean isOpen) throws IOException { - if (!isOpen) { - throw new IOException("The stream is closed."); - } - } - /** * Whether {@link #close()} completed successfully. */ @@ -50,7 +38,7 @@ static void checkOpen(final boolean isOpen) throws IOException { * @throws IOException if this instance is closed. */ void checkOpen() throws IOException { - checkOpen(!isClosed()); + Input.checkOpen(!isClosed()); } @Override diff --git a/src/main/java/org/apache/commons/io/input/BufferedFileChannelInputStream.java b/src/main/java/org/apache/commons/io/input/BufferedFileChannelInputStream.java index 70075e3aff9..c947929e9b0 100644 --- a/src/main/java/org/apache/commons/io/input/BufferedFileChannelInputStream.java +++ b/src/main/java/org/apache/commons/io/input/BufferedFileChannelInputStream.java @@ -243,7 +243,7 @@ public synchronized int read(final byte[] b, final int offset, int len) throws I * @throws IOException if an I/O error occurs. */ private boolean refill() throws IOException { - AbstractInputStream.checkOpen(fileChannel.isOpen()); + Input.checkOpen(fileChannel.isOpen()); if (!byteBuffer.hasRemaining()) { byteBuffer.clear(); int nRead = 0; diff --git a/src/main/java/org/apache/commons/io/input/Input.java b/src/main/java/org/apache/commons/io/input/Input.java new file mode 100644 index 00000000000..9af87a68960 --- /dev/null +++ b/src/main/java/org/apache/commons/io/input/Input.java @@ -0,0 +1,39 @@ +/* + * 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 java.io.IOException; + +/** + * Package-wide internals for input. + */ +class Input { + + /** + * Throws an IOException on false input. + * + * @param isOpen whether an input is open or not. + * @throws IOException if {@code isOpen} is false indicating an input is closed. + */ + static void checkOpen(final boolean isOpen) throws IOException { + if (!isOpen) { + throw new IOException("Closed"); + } + } + +} diff --git a/src/main/java/org/apache/commons/io/input/ProxyInputStream.java b/src/main/java/org/apache/commons/io/input/ProxyInputStream.java index 523d07ab5f5..207af34a12d 100644 --- a/src/main/java/org/apache/commons/io/input/ProxyInputStream.java +++ b/src/main/java/org/apache/commons/io/input/ProxyInputStream.java @@ -149,7 +149,7 @@ protected void beforeRead(final int n) throws IOException { * @throws IOException if this instance is closed. */ void checkOpen() throws IOException { - AbstractInputStream.checkOpen(!isClosed()); + Input.checkOpen(!isClosed()); } /** diff --git a/src/main/java/org/apache/commons/io/input/UnsynchronizedBufferedReader.java b/src/main/java/org/apache/commons/io/input/UnsynchronizedBufferedReader.java index fc6a1da2b40..c0ded3212eb 100644 --- a/src/main/java/org/apache/commons/io/input/UnsynchronizedBufferedReader.java +++ b/src/main/java/org/apache/commons/io/input/UnsynchronizedBufferedReader.java @@ -91,8 +91,7 @@ public class UnsynchronizedBufferedReader extends UnsynchronizedReader { * @param in the Reader that is buffered. */ public UnsynchronizedBufferedReader(final Reader in) { - this.in = in; - buf = new char[IOUtils.DEFAULT_BUFFER_SIZE]; + this(in, IOUtils.DEFAULT_BUFFER_SIZE); } /** @@ -110,12 +109,6 @@ public UnsynchronizedBufferedReader(final Reader in, final int size) { buf = new char[size]; } - private void checkClosed() throws IOException { - if (isClosed()) { - throw new IOException("Closed"); - } - } - /** * Peeks at the next input character, refilling the buffer if necessary. If this character is a newline character ("\n"), it is discarded. */ @@ -136,6 +129,7 @@ public void close() throws IOException { if (!isClosed()) { in.close(); buf = null; + super.close(); } } @@ -183,15 +177,6 @@ private int fillBuf() throws IOException { return count; } - /** - * Tests whether or not this reader is closed. - * - * @return {@code true} if this reader is closed, {@code false} otherwise. - */ - private boolean isClosed() { - return buf == null; - } - /** * Sets a mark position in this reader. The parameter {@code markLimit} indicates how many characters can be read before the mark is invalidated. Calling * {@link #reset()} will reposition the reader back to the marked position if {@code markLimit} has not been surpassed. @@ -207,7 +192,7 @@ public void mark(final int markLimit) throws IOException { if (markLimit < 0) { throw new IllegalArgumentException(); } - checkClosed(); + checkOpen(); this.markLimit = markLimit; mark = pos; } @@ -234,7 +219,7 @@ public boolean markSupported() { */ @Override public int read() throws IOException { - checkClosed(); + checkOpen(); /* Are there buffered characters available? */ if (pos < end || fillBuf() != EOF) { return buf[pos++]; @@ -257,7 +242,7 @@ public int read() throws IOException { */ @Override public int read(final char[] buffer, int offset, final int length) throws IOException { - checkClosed(); + checkOpen(); if (offset < 0 || offset > buffer.length - length || length < 0) { throw new IndexOutOfBoundsException(); } @@ -317,7 +302,7 @@ public int read(final char[] buffer, int offset, final int length) throws IOExce * @throws IOException if this reader is closed or some other I/O error occurs. */ public String readLine() throws IOException { - checkClosed(); + checkOpen(); /* has the underlying stream been exhausted? */ if (pos == end && fillBuf() == EOF) { return null; @@ -331,7 +316,8 @@ public String readLine() throws IOException { final String res = new String(buf, pos, charPos - pos); pos = charPos + 1; return res; - } else if (ch == CR) { + } + if (ch == CR) { final String res = new String(buf, pos, charPos - pos); pos = charPos + 1; if ((pos < end || fillBuf() != EOF) && buf[pos] == LF) { @@ -360,11 +346,7 @@ public String readLine() throws IOException { } for (int charPos = pos; charPos < end; charPos++) { final char c = buf[charPos]; - if (eol == NUL) { - if (c == LF || c == CR) { - eol = c; - } - } else { + if (eol != NUL) { if (eol == CR && c == LF) { if (charPos > pos) { result.append(buf, pos, charPos - pos - 1); @@ -378,6 +360,9 @@ public String readLine() throws IOException { } return result.toString(); } + if (c == LF || c == CR) { + eol = c; + } } if (eol == NUL) { result.append(buf, pos, end - pos); @@ -398,7 +383,7 @@ public String readLine() throws IOException { */ @Override public boolean ready() throws IOException { - checkClosed(); + checkOpen(); return end - pos > 0 || in.ready(); } @@ -411,7 +396,7 @@ public boolean ready() throws IOException { */ @Override public void reset() throws IOException { - checkClosed(); + checkOpen(); if (mark == -1) { throw new IOException("mark == -1"); } @@ -435,7 +420,7 @@ public long skip(final long amount) throws IOException { if (amount < 0) { throw new IllegalArgumentException(); } - checkClosed(); + checkOpen(); if (amount < 1) { return 0; } diff --git a/src/main/java/org/apache/commons/io/input/UnsynchronizedReader.java b/src/main/java/org/apache/commons/io/input/UnsynchronizedReader.java index 1350d2153c9..73f0bb8421f 100644 --- a/src/main/java/org/apache/commons/io/input/UnsynchronizedReader.java +++ b/src/main/java/org/apache/commons/io/input/UnsynchronizedReader.java @@ -36,11 +36,48 @@ public abstract class UnsynchronizedReader extends Reader { */ private static final int MAX_SKIP_BUFFER_SIZE = IOUtils.DEFAULT_BUFFER_SIZE; + /** + * Whether {@link #close()} completed successfully. + */ + private boolean closed; + /** * The skip buffer, defaults to null until allocated in {@link UnsynchronizedReader#skip(long)}. */ private char skipBuffer[]; + /** + * Checks if this instance is closed and throws an IOException if so. + * + * @throws IOException if this instance is closed. + */ + void checkOpen() throws IOException { + Input.checkOpen(!isClosed()); + } + + @Override + public void close() throws IOException { + closed = true; + } + + /** + * Tests whether this instance is closed; if {@link #close()} completed successfully. + * + * @return whether this instance is closed. + */ + public boolean isClosed() { + return closed; + } + + /** + * Sets whether this instance is closed. + * + * @param closed whether this instance is closed. + */ + public void setClosed(final boolean closed) { + this.closed = closed; + } + /** * Skips characters by reading from this instance. *