001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018package org.apache.commons.io.input;
019
020import java.io.BufferedReader;
021import java.io.IOException;
022import java.io.Reader;
023import java.io.UncheckedIOException;
024import java.nio.CharBuffer;
025
026import org.apache.commons.io.build.AbstractStreamBuilder;
027import org.apache.commons.io.function.Uncheck;
028
029/**
030 * A {@link BufferedReader} that throws {@link UncheckedIOException} instead of {@link IOException}.
031 *
032 * @see BufferedReader
033 * @see IOException
034 * @see UncheckedIOException
035 * @since 2.12.0
036 */
037public final class UncheckedBufferedReader extends BufferedReader {
038
039    /**
040     * Builds a new {@link UncheckedBufferedReader} instance.
041     * <p>
042     * Using File IO:
043     * </p>
044     * <pre>{@code
045     * UncheckedBufferedReader s = UncheckedBufferedReader.builder()
046     *   .setFile(file)
047     *   .setBufferSize(8192)
048     *   .setCharset(Charset.defaultCharset())
049     *   .get()}
050     * </pre>
051     * <p>
052     * Using NIO Path:
053     * </p>
054     * <pre>{@code
055     * UncheckedBufferedReader s = UncheckedBufferedReader.builder()
056     *   .setPath(path)
057     *   .setBufferSize(8192)
058     *   .setCharset(Charset.defaultCharset())
059     *   .get()}
060     * </pre>
061     */
062    public static class Builder extends AbstractStreamBuilder<UncheckedBufferedReader, Builder> {
063
064        /**
065         * Constructs a new instance.
066         *
067         * @throws UnsupportedOperationException if the origin cannot be converted to a Reader.
068         */
069        @Override
070        public UncheckedBufferedReader get() {
071            // This an unchecked class, so this method is as well.
072            return Uncheck.get(() -> new UncheckedBufferedReader(getOrigin().getReader(getCharset()), getBufferSize()));
073        }
074
075    }
076
077    /**
078     * Constructs a new {@link Builder}.
079     *
080     * @return a new {@link Builder}.
081     */
082    public static Builder builder() {
083        return new Builder();
084    }
085
086    /**
087     * Creates a buffering character-input stream that uses an input buffer of the specified size.
088     *
089     * @param reader     A Reader
090     * @param bufferSize Input-buffer size
091     *
092     * @throws IllegalArgumentException If {@code bufferSize <= 0}
093     */
094    private UncheckedBufferedReader(final Reader reader, final int bufferSize) {
095        super(reader, bufferSize);
096    }
097
098    /**
099     * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}.
100     */
101    @Override
102    public void close() throws UncheckedIOException {
103        Uncheck.run(super::close);
104    }
105
106    /**
107     * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}.
108     */
109    @Override
110    public void mark(final int readAheadLimit) throws UncheckedIOException {
111        Uncheck.accept(super::mark, readAheadLimit);
112    }
113
114    /**
115     * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}.
116     */
117    @Override
118    public int read() throws UncheckedIOException {
119        return Uncheck.get(super::read);
120    }
121
122    /**
123     * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}.
124     */
125    @Override
126    public int read(final char[] cbuf) throws UncheckedIOException {
127        return Uncheck.apply(super::read, cbuf);
128    }
129
130    /**
131     * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}.
132     */
133    @Override
134    public int read(final char[] cbuf, final int off, final int len) throws UncheckedIOException {
135        return Uncheck.apply(super::read, cbuf, off, len);
136    }
137
138    /**
139     * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}.
140     */
141    @Override
142    public int read(final CharBuffer target) throws UncheckedIOException {
143        return Uncheck.apply(super::read, target);
144    }
145
146    /**
147     * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}.
148     */
149    @Override
150    public String readLine() throws UncheckedIOException {
151        return Uncheck.get(super::readLine);
152    }
153
154    /**
155     * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}.
156     */
157    @Override
158    public boolean ready() throws UncheckedIOException {
159        return Uncheck.get(super::ready);
160    }
161
162    /**
163     * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}.
164     */
165    @Override
166    public void reset() throws UncheckedIOException {
167        Uncheck.run(super::reset);
168    }
169
170    /**
171     * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}.
172     */
173    @Override
174    public long skip(final long n) throws UncheckedIOException {
175        return Uncheck.apply(super::skip, n);
176    }
177
178}