View Javadoc
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 }