1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.commons.io.input;
18
19 import static org.apache.commons.io.IOUtils.EOF;
20
21 import java.io.IOException;
22 import java.io.Reader;
23
24 import org.apache.commons.io.IOUtils;
25
26 /**
27 * Always returns {@link IOUtils#EOF} to all attempts to read something from it.
28 * <p>
29 * Typically uses of this class include testing for corner cases in methods that accept readers and acting as a sentinel
30 * value instead of a {@code null} reader.
31 * </p>
32 *
33 * @since 2.7
34 */
35 public class ClosedReader extends Reader {
36
37 /**
38 * The singleton instance.
39 *
40 * @since 2.12.0
41 */
42 public static final ClosedReader INSTANCE = new ClosedReader();
43
44 /**
45 * The singleton instance.
46 *
47 * @deprecated {@link #INSTANCE}.
48 */
49 @Deprecated
50 public static final ClosedReader CLOSED_READER = INSTANCE;
51
52 /**
53 * Construct a new instance.
54 */
55 public ClosedReader() {
56 // empty
57 }
58
59 @Override
60 public void close() throws IOException {
61 // noop
62 }
63
64 /**
65 * A no-op read method that always indicates end-of-stream.
66 *
67 * <p>Behavior:</p>
68 * <ul>
69 * <li>If {@code len == 0}, returns {@code 0} immediately (no characters are read).</li>
70 * <li>Otherwise, always returns {@value IOUtils#EOF} to signal that the stream is closed or at end-of-stream.</li>
71 * </ul>
72 *
73 * @param cbuf The destination buffer.
74 * @param off The offset at which to start storing characters.
75 * @param len The maximum number of characters to read.
76 * @return {@code 0} if {@code len == 0}; otherwise always {@value IOUtils#EOF}.
77 * @throws IndexOutOfBoundsException If {@code off < 0}, {@code len < 0}, or {@code off + len > cbuf.length}.
78 */
79 @Override
80 public int read(final char[] cbuf, final int off, final int len) {
81 IOUtils.checkFromIndexSize(cbuf, off, len);
82 if (len == 0) {
83 return 0;
84 }
85 return EOF;
86 }
87
88 }