    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    package org.apache.commons.io.input;
    018
    019    import java.io.FilterInputStream;
    020    import java.io.IOException;
    021    import java.io.InputStream;
    022
    023    /**
    024     * A Proxy stream which acts as expected, that is it passes the method
    025     * calls on to the proxied stream and doesn't change which methods are
    026     * being called.
    027     * <p>
    028     * It is an alternative base class to FilterInputStream
    029     * to increase reusability, because FilterInputStream changes the
    030     * methods being called, such as read(byte[]) to read(byte[], int, int).
    031     * <p>
    032     * See the protected methods for ways in which a subclass can easily decorate
    033     * a stream with custom pre-, post- or error processing functionality.
    034     *
    035     * @author Stephen Colebourne
    036     * @version $Id: ProxyInputStream.java 934041 2010-04-14 17:37:24Z jukka $
    037     */
    038    public abstract class ProxyInputStream extends FilterInputStream {
    039
    040        /**
    041         * Constructs a new ProxyInputStream.
    042         *
    043         * @param proxy  the InputStream to delegate to
    044         */
    045        public ProxyInputStream(InputStream proxy) {
    046            super(proxy);
    047            // the proxy is stored in a protected superclass variable named 'in'
    048        }
    049
    050        /**
    051         * Invokes the delegate's <code>read()</code> method.
    052         * @return the byte read or -1 if the end of stream
    053         * @throws IOException if an I/O error occurs
    054         */
    055        @Override
    056        public int read() throws IOException {
    057            try {
    058                beforeRead(1);
    059                int b = in.read();
    060                afterRead(b != -1 ? 1 : -1);
    061                return b;
    062            } catch (IOException e) {
    063                handleIOException(e);
    064                return -1;
    065            }
    066        }
    067
    068        /**
    069         * Invokes the delegate's <code>read(byte[])</code> method.
    070         * @param bts the buffer to read the bytes into
    071         * @return the number of bytes read or -1 if the end of stream
    072         * @throws IOException if an I/O error occurs
    073         */
    074        @Override
    075        public int read(byte[] bts) throws IOException {
    076            try {
    077                beforeRead(bts != null ? bts.length : 0);
    078                int n = in.read(bts);
    079                afterRead(n);
    080                return n;
    081            } catch (IOException e) {
    082                handleIOException(e);
    083                return -1;
    084            }
    085        }
    086
    087        /**
    088         * Invokes the delegate's <code>read(byte[], int, int)</code> method.
    089         * @param bts the buffer to read the bytes into
    090         * @param off The start offset
    091         * @param len The number of bytes to read
    092         * @return the number of bytes read or -1 if the end of stream
    093         * @throws IOException if an I/O error occurs
    094         */
    095        @Override
    096        public int read(byte[] bts, int off, int len) throws IOException {
    097            try {
    098                beforeRead(len);
    099                int n = in.read(bts, off, len);
    100                afterRead(n);
    101                return n;
    102            } catch (IOException e) {
    103                handleIOException(e);
    104                return -1;
    105            }
    106        }
    107
    108        /**
    109         * Invokes the delegate's <code>skip(long)</code> method.
    110         * @param ln the number of bytes to skip
    111         * @return the actual number of bytes skipped
    112         * @throws IOException if an I/O error occurs
    113         */
    114        @Override
    115        public long skip(long ln) throws IOException {
    116            try {
    117                return in.skip(ln);
    118            } catch (IOException e) {
    119                handleIOException(e);
    120                return 0;
    121            }
    122        }
    123
    124        /**
    125         * Invokes the delegate's <code>available()</code> method.
    126         * @return the number of available bytes
    127         * @throws IOException if an I/O error occurs
    128         */
    129        @Override
    130        public int available() throws IOException {
    131            try {
    132                return super.available();
    133            } catch (IOException e) {
    134                handleIOException(e);
    135                return 0;
    136            }
    137        }
    138
    139        /**
    140         * Invokes the delegate's <code>close()</code> method.
    141         * @throws IOException if an I/O error occurs
    142         */
    143        @Override
    144        public void close() throws IOException {
    145            try {
    146                in.close();
    147            } catch (IOException e) {
    148                handleIOException(e);
    149            }
    150        }
    151
    152        /**
    153         * Invokes the delegate's <code>mark(int)</code> method.
    154         * @param readlimit read ahead limit
    155         */
    156        @Override
    157        public synchronized void mark(int readlimit) {
    158            in.mark(readlimit);
    159        }
    160
    161        /**
    162         * Invokes the delegate's <code>reset()</code> method.
    163         * @throws IOException if an I/O error occurs
    164         */
    165        @Override
    166        public synchronized void reset() throws IOException {
    167            try {
    168                in.reset();
    169            } catch (IOException e) {
    170                handleIOException(e);
    171            }
    172        }
    173
    174        /**
    175         * Invokes the delegate's <code>markSupported()</code> method.
    176         * @return true if mark is supported, otherwise false
    177         */
    178        @Override
    179        public boolean markSupported() {
    180            return in.markSupported();
    181        }
    182
    183        /**
    184         * Invoked by the read methods before the call is proxied. The number
    185         * of bytes that the caller wanted to read (1 for the {@link #read()}
    186         * method, buffer length for {@link #read(byte[])}, etc.) is given as
    187         * an argument.
    188         * <p>
    189         * Subclasses can override this method to add common pre-processing
    190         * functionality without having to override all the read methods.
    191         * The default implementation does nothing.
    192         * <p>
    193         * Note this method is <em>not</em> called from {@link #skip(long)} or
    194         * {@link #reset()}. You need to explicitly override those methods if
    195         * you want to add pre-processing steps also to them.
    196         *
    197         * @since Commons IO 2.0
    198         * @param n number of bytes that the caller asked to be read
    199         * @throws IOException if the pre-processing fails
    200         */
    201        protected void beforeRead(int n) throws IOException {
    202        }
    203
    204        /**
    205         * Invoked by the read methods after the proxied call has returned
    206         * successfully. The number of bytes returned to the caller (or -1 if
    207         * the end of stream was reached) is given as an argument.
    208         * <p>
    209         * Subclasses can override this method to add common post-processing
    210         * functionality without having to override all the read methods.
    211         * The default implementation does nothing.
    212         * <p>
    213         * Note this method is <em>not</em> called from {@link #skip(long)} or
    214         * {@link #reset()}. You need to explicitly override those methods if
    215         * you want to add post-processing steps also to them.
    216         *
    217         * @since Commons IO 2.0
    218         * @param n number of bytes read, or -1 if the end of stream was reached
    219         * @throws IOException if the post-processing fails
    220         */
    221        protected void afterRead(int n) throws IOException {
    222        }
    223
    224        /**
    225         * Handle any IOExceptions thrown.
    226         * <p>
    227         * This method provides a point to implement custom exception
    228         * handling. The default behaviour is to re-throw the exception.
    229         * @param e The IOException thrown
    230         * @throws IOException if an I/O error occurs
    231         * @since Commons IO 2.0
    232         */
    233        protected void handleIOException(IOException e) throws IOException {
    234            throw e;
    235        }
    236
    237    }