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 * http://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 java.io.IOException;
20 import java.io.Reader;
21 import java.util.function.Supplier;
22
23 import org.apache.commons.io.function.Erase;
24
25 /**
26 * Always throws an exception from all {@link Reader} methods where {@link IOException} is declared.
27 * <p>
28 * This class is mostly useful for testing error handling.
29 * </p>
30 *
31 * @since 2.7
32 */
33 public class BrokenReader extends Reader {
34
35 /**
36 * A singleton instance using a default IOException.
37 *
38 * @since 2.12.0
39 */
40 public static final BrokenReader INSTANCE = new BrokenReader();
41
42 /**
43 * A supplier for the exception that is thrown by all methods of this class.
44 */
45 private final Supplier<Throwable> exceptionSupplier;
46
47 /**
48 * Constructs a new reader that always throws an {@link IOException}.
49 */
50 public BrokenReader() {
51 this(() -> new IOException("Broken reader"));
52 }
53
54 /**
55 * Constructs a new reader that always throws the given exception.
56 *
57 * @param exception the exception to be thrown.
58 * @deprecated Use {@link #BrokenReader(Throwable)}.
59 */
60 @Deprecated
61 public BrokenReader(final IOException exception) {
62 this(() -> exception);
63 }
64
65 /**
66 * Constructs a new reader that always throws the supplied exception.
67 *
68 * @param exceptionSupplier a supplier for the IOException or RuntimeException to be thrown.
69 * @since 2.12.0
70 */
71 public BrokenReader(final Supplier<Throwable> exceptionSupplier) {
72 this.exceptionSupplier = exceptionSupplier;
73 }
74
75 /**
76 * Constructs a new reader that always throws the given exception.
77 *
78 * @param exception the exception to be thrown.
79 * @since 2.16.0
80 */
81 public BrokenReader(final Throwable exception) {
82 this(() -> exception);
83 }
84
85 /**
86 * Throws the configured exception.
87 *
88 * @throws IOException always throws the exception configured in a constructor.
89 */
90 @Override
91 public void close() throws IOException {
92 throw rethrow();
93 }
94
95 /**
96 * Throws the configured exception.
97 *
98 * @param readAheadLimit ignored.
99 * @throws IOException always throws the exception configured in a constructor.
100 */
101 @Override
102 public void mark(final int readAheadLimit) throws IOException {
103 throw rethrow();
104 }
105
106 /**
107 * Throws the configured exception.
108 *
109 * @param cbuf ignored.
110 * @param off ignored.
111 * @param len ignored.
112 * @return nothing.
113 * @throws IOException always throws the exception configured in a constructor.
114 */
115 @Override
116 public int read(final char[] cbuf, final int off, final int len) throws IOException {
117 throw rethrow();
118 }
119
120 /**
121 * Throws the configured exception.
122 *
123 * @return nothing.
124 * @throws IOException always throws the exception configured in a constructor.
125 */
126 @Override
127 public boolean ready() throws IOException {
128 throw rethrow();
129 }
130
131 /**
132 * Throws the configured exception.
133 *
134 * @throws IOException always throws the exception configured in a constructor.
135 */
136 @Override
137 public void reset() throws IOException {
138 throw rethrow();
139 }
140
141 /**
142 * Throws the configured exception from its supplier.
143 *
144 * @return Throws the configured exception from its supplier.
145 */
146 private RuntimeException rethrow() {
147 return Erase.rethrow(exceptionSupplier.get());
148 }
149
150 /**
151 * Throws the configured exception.
152 *
153 * @param n ignored.
154 * @return nothing.
155 * @throws IOException always throws the exception configured in a constructor.
156 */
157 @Override
158 public long skip(final long n) throws IOException {
159 throw rethrow();
160 }
161
162 }