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
18 package org.apache.commons.io.input;
19
20 import java.io.FilterReader;
21 import java.io.IOException;
22 import java.io.Reader;
23 import java.io.UncheckedIOException;
24 import java.nio.CharBuffer;
25
26 import org.apache.commons.io.build.AbstractStreamBuilder;
27 import org.apache.commons.io.function.Uncheck;
28
29 /**
30 * A {@link FilterReader} that throws {@link UncheckedIOException} instead of {@link IOException}.
31 * <p>
32 * To build an instance, use {@link Builder}.
33 * </p>
34 *
35 * @see Builder
36 * @see FilterReader
37 * @see IOException
38 * @see UncheckedIOException
39 * @since 2.12.0
40 */
41 public final class UncheckedFilterReader extends FilterReader {
42
43 // @formatter:off
44 /**
45 * Builds a new {@link UncheckedFilterReader}.
46 *
47 * <p>
48 * Using File IO:
49 * </p>
50 * <pre>{@code
51 * UncheckedFilterReader s = UncheckedFilterReader.builder()
52 * .setFile(file)
53 * .get();}
54 * </pre>
55 * <p>
56 * Using NIO Path:
57 * </p>
58 * <pre>{@code
59 * UncheckedFilterReader s = UncheckedFilterReader.builder()
60 * .setPath(path)
61 * .get();}
62 * </pre>
63 *
64 * @see #get()
65 */
66 // @formatter:on
67 public static class Builder extends AbstractStreamBuilder<UncheckedFilterReader, Builder> {
68
69 /**
70 * Constructs a new builder of {@link UncheckedFilterReader}.
71 */
72 public Builder() {
73 // empty
74 }
75
76 /**
77 * Builds a new {@link UncheckedFilterReader}.
78 * <p>
79 * You must set an aspect that supports {@link #getReader()} on this builder, otherwise, this method throws an exception.
80 * </p>
81 * <p>
82 * This builder uses the following aspects:
83 * </p>
84 * <ul>
85 * <li>{@link #getReader()}</li>
86 * </ul>
87 *
88 * @return a new instance.
89 * @throws UnsupportedOperationException if the origin cannot provide a {@link Reader}.
90 * @throws IllegalStateException if the {@code origin} is {@code null}.
91 * @see #getReader()
92 * @see #getUnchecked()
93 */
94 @Override
95 public UncheckedFilterReader get() {
96 // This an unchecked class, so this method is as well.
97 return Uncheck.get(() -> new UncheckedFilterReader(this));
98 }
99
100 }
101
102 /**
103 * Constructs a new {@link Builder}.
104 *
105 * @return a new {@link Builder}.
106 */
107 public static Builder builder() {
108 return new Builder();
109 }
110
111 /**
112 * Constructs a new filtered reader.
113 *
114 * @param builder a Builder object providing the underlying stream.
115 * @throws IOException if an I/O error occurs.
116 * @throws NullPointerException if {@code reader} is {@code null}.
117 */
118 @SuppressWarnings("resource")
119 private UncheckedFilterReader(final Builder builder) throws IOException {
120 super(builder.getReader());
121 }
122
123 /**
124 * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}.
125 */
126 @Override
127 public void close() throws UncheckedIOException {
128 Uncheck.run(super::close);
129 }
130
131 /**
132 * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}.
133 */
134 @Override
135 public void mark(final int readAheadLimit) throws UncheckedIOException {
136 Uncheck.accept(super::mark, readAheadLimit);
137 }
138
139 /**
140 * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}.
141 */
142 @Override
143 public int read() throws UncheckedIOException {
144 return Uncheck.getAsInt(super::read);
145 }
146
147 /**
148 * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}.
149 */
150 @Override
151 public int read(final char[] cbuf) throws UncheckedIOException {
152 return Uncheck.apply(super::read, cbuf);
153 }
154
155 /**
156 * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}.
157 */
158 @Override
159 public int read(final char[] cbuf, final int off, final int len) throws UncheckedIOException {
160 return Uncheck.apply(super::read, cbuf, off, len);
161 }
162
163 /**
164 * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}.
165 */
166 @Override
167 public int read(final CharBuffer target) throws UncheckedIOException {
168 return Uncheck.apply(super::read, target);
169 }
170
171 /**
172 * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}.
173 */
174 @Override
175 public boolean ready() throws UncheckedIOException {
176 return Uncheck.getAsBoolean(super::ready);
177 }
178
179 /**
180 * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}.
181 */
182 @Override
183 public void reset() throws UncheckedIOException {
184 Uncheck.run(super::reset);
185 }
186
187 /**
188 * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}.
189 */
190 @Override
191 public long skip(final long n) throws UncheckedIOException {
192 return Uncheck.apply(super::skip, n);
193 }
194
195 }