14ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira/*
24ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * Licensed to the Apache Software Foundation (ASF) under one or more
34ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * contributor license agreements.  See the NOTICE file distributed with
44ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * this work for additional information regarding copyright ownership.
54ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * The ASF licenses this file to You under the Apache License, Version 2.0
64ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * (the "License"); you may not use this file except in compliance with
74ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * the License.  You may obtain a copy of the License at
84ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira *
94ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira *      http://www.apache.org/licenses/LICENSE-2.0
104ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira *
114ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * Unless required by applicable law or agreed to in writing, software
124ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * distributed under the License is distributed on an "AS IS" BASIS,
134ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
144ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * See the License for the specific language governing permissions and
154ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * limitations under the License.
164ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira */
174ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereirapackage org.apache.commons.io.input;
184ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
194ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereiraimport java.io.IOException;
204ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereiraimport java.io.InputStream;
214ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
224ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira/**
234ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * Proxy stream that closes and discards the underlying stream as soon as the
244ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * end of input has been reached or when the stream is explicitly closed.
254ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * Not even a reference to the underlying stream is kept after it has been
264ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * closed, so any allocated in-memory buffers can be freed even if the
274ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * client application still keeps a reference to the proxy stream.
284ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * <p>
294ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * This class is typically used to release any resources related to an open
304ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * stream as soon as possible even if the client application (by not explicitly
314ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * closing the stream when no longer needed) or the underlying stream (by not
324ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * releasing resources once the last byte has been read) do not do that.
334ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira *
344ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * @version $Id: AutoCloseInputStream.java 610010 2008-01-08 14:50:59Z niallp $
354ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * @since Commons IO 1.4
364ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira */
374ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereirapublic class AutoCloseInputStream extends ProxyInputStream {
384ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
394ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    /**
404ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * Creates an automatically closing proxy for the given input stream.
414ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     *
424ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @param in underlying input stream
434ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     */
444ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    public AutoCloseInputStream(InputStream in) {
454ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        super(in);
464ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    }
474ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
484ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    /**
494ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * Closes the underlying input stream and replaces the reference to it
504ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * with a {@link ClosedInputStream} instance.
514ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * <p>
524ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * This method is automatically called by the read methods when the end
534ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * of input has been reached.
544ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * <p>
554ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * Note that it is safe to call this method any number of times. The original
564ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * underlying input stream is closed and discarded only once when this
574ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * method is first called.
584ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     *
594ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @throws IOException if the underlying input stream can not be closed
604ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     */
614ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    public void close() throws IOException {
624ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        in.close();
634ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        in = new ClosedInputStream();
644ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    }
654ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
664ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    /**
674ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * Reads and returns a single byte from the underlying input stream.
684ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * If the underlying stream returns -1, the {@link #close()} method is
694ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * called to automatically close and discard the stream.
704ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     *
714ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @return next byte in the stream, or -1 if no more bytes are available
724ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @throws IOException if the stream could not be read or closed
734ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     */
744ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    public int read() throws IOException {
754ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        int n = in.read();
764ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        if (n == -1) {
774ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            close();
784ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        }
794ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        return n;
804ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    }
814ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
824ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    /**
834ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * Reads and returns bytes from the underlying input stream to the given
844ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * buffer. If the underlying stream returns -1, the {@link #close()} method
854ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * i called to automatically close and discard the stream.
864ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     *
874ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @param b buffer to which bytes from the stream are written
884ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @return number of bytes read, or -1 if no more bytes are available
894ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @throws IOException if the stream could not be read or closed
904ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     */
914ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    public int read(byte[] b) throws IOException {
924ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        int n = in.read(b);
934ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        if (n == -1) {
944ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            close();
954ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        }
964ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        return n;
974ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    }
984ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
994ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    /**
1004ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * Reads and returns bytes from the underlying input stream to the given
1014ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * buffer. If the underlying stream returns -1, the {@link #close()} method
1024ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * i called to automatically close and discard the stream.
1034ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     *
1044ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @param b buffer to which bytes from the stream are written
1054ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @param off start offset within the buffer
1064ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @param len maximum number of bytes to read
1074ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @return number of bytes read, or -1 if no more bytes are available
1084ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @throws IOException if the stream could not be read or closed
1094ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     */
1104ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    public int read(byte[] b, int off, int len) throws IOException {
1114ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        int n = in.read(b, off, len);
1124ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        if (n == -1) {
1134ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            close();
1144ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        }
1154ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        return n;
1164ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    }
1174ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
1184ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    /**
1194ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * Ensures that the stream is closed before it gets garbage-collected.
1204ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * As mentioned in {@link #close()}, this is a no-op if the stream has
1214ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * already been closed.
1224ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @throws Throwable if an error occurs
1234ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     */
1244ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    protected void finalize() throws Throwable {
1254ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        close();
1264ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        super.finalize();
1274ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    }
1284ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
1294ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira}
130