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.FilterInputStream;
022import java.io.IOException;
023import java.io.InputStream;
024import java.io.UncheckedIOException;
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 * <p>
032 * To build an instance, see {@link Builder}.
033 * </p>
034 *
035 * @see BufferedReader
036 * @see IOException
037 * @see UncheckedIOException
038 * @since 2.12.0
039 */
040public final class UncheckedFilterInputStream extends FilterInputStream {
041
042    /**
043     * Builds a new {@link UncheckedFilterInputStream} instance.
044     * <p>
045     * Using File IO:
046     * </p>
047     * <pre>{@code
048     * UncheckedFilterInputStream s = UncheckedFilterInputStream.builder()
049     *   .setFile(file)
050     *   .get();}
051     * </pre>
052     * <p>
053     * Using NIO Path:
054     * </p>
055     * <pre>{@code
056     * UncheckedFilterInputStream s = UncheckedFilterInputStream.builder()
057     *   .setPath(path)
058     *   .get();}
059     * </pre>
060     */
061    public static class Builder extends AbstractStreamBuilder<UncheckedFilterInputStream, Builder> {
062
063        /**
064         * Constructs a new instance.
065         * <p>
066         * This builder use the aspect InputStream and OpenOption[].
067         * </p>
068         * <p>
069         * You must provide an origin that can be converted to an InputStream by this builder, otherwise, this call will throw an
070         * {@link UnsupportedOperationException}.
071         * </p>
072         *
073         * @return a new instance.
074         * @throws UnsupportedOperationException if the origin cannot provide an InputStream.
075         * @see #getInputStream()
076         */
077        @Override
078        public UncheckedFilterInputStream get() {
079            // This an unchecked class, so this method is as well.
080            return Uncheck.get(() -> new UncheckedFilterInputStream(getInputStream()));
081        }
082
083    }
084
085    /**
086     * Constructs a new {@link Builder}.
087     *
088     * @return a new {@link Builder}.
089     */
090    public static Builder builder() {
091        return new Builder();
092    }
093
094    /**
095     * Constructs a {@link UncheckedFilterInputStream}.
096     *
097     * @param inputStream the underlying input stream, or {@code null} if this instance is to be created without an
098     *        underlying stream.
099     */
100    private UncheckedFilterInputStream(final InputStream inputStream) {
101        super(inputStream);
102    }
103
104    /**
105     * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}.
106     */
107    @Override
108    public int available() throws UncheckedIOException {
109        return Uncheck.get(super::available);
110    }
111
112    /**
113     * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}.
114     */
115    @Override
116    public void close() throws UncheckedIOException {
117        Uncheck.run(super::close);
118    }
119
120    /**
121     * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}.
122     */
123    @Override
124    public int read() throws UncheckedIOException {
125        return Uncheck.get(super::read);
126    }
127
128    /**
129     * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}.
130     */
131    @Override
132    public int read(final byte[] b) throws UncheckedIOException {
133        return Uncheck.apply(super::read, b);
134    }
135
136    /**
137     * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}.
138     */
139    @Override
140    public int read(final byte[] b, final int off, final int len) throws UncheckedIOException {
141        return Uncheck.apply(super::read, b, off, len);
142    }
143
144    /**
145     * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}.
146     */
147    @Override
148    public synchronized void reset() throws UncheckedIOException {
149        Uncheck.run(super::reset);
150    }
151
152    /**
153     * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}.
154     */
155    @Override
156    public long skip(final long n) throws UncheckedIOException {
157        return Uncheck.apply(super::skip, n);
158    }
159
160}