1bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook/*
2bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Licensed to the Apache Software Foundation (ASF) under one or more
3bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * contributor license agreements.  See the NOTICE file distributed with
4bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * this work for additional information regarding copyright ownership.
5bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * The ASF licenses this file to You under the Apache License, Version 2.0
6bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * (the "License"); you may not use this file except in compliance with
7bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * the License.  You may obtain a copy of the License at
8bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *
9bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *      http://www.apache.org/licenses/LICENSE-2.0
10bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *
11bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Unless required by applicable law or agreed to in writing, software
12bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * distributed under the License is distributed on an "AS IS" BASIS,
13bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * See the License for the specific language governing permissions and
15bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * limitations under the License.
16bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */
17bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookpackage org.apache.commons.io.input;
18bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
19bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport java.io.IOException;
20bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport java.io.InputStream;
21bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
22bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook/**
23bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Proxy stream that closes and discards the underlying stream as soon as the
24bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * end of input has been reached or when the stream is explicitly closed.
25bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Not even a reference to the underlying stream is kept after it has been
26bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * closed, so any allocated in-memory buffers can be freed even if the
27bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * client application still keeps a reference to the proxy stream.
28bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * <p>
29bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * This class is typically used to release any resources related to an open
30bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * stream as soon as possible even if the client application (by not explicitly
31bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * closing the stream when no longer needed) or the underlying stream (by not
32bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * releasing resources once the last byte has been read) do not do that.
33bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *
34bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @version $Id: AutoCloseInputStream.java 610010 2008-01-08 14:50:59Z niallp $
35bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @since Commons IO 1.4
36bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */
37bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookpublic class AutoCloseInputStream extends ProxyInputStream {
38bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
39bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
40bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Creates an automatically closing proxy for the given input stream.
41bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
42bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param in underlying input stream
43bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
44bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public AutoCloseInputStream(InputStream in) {
45bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        super(in);
46bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
47bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
48bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
49bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Closes the underlying input stream and replaces the reference to it
50bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * with a {@link ClosedInputStream} instance.
51bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * <p>
52bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * This method is automatically called by the read methods when the end
53bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * of input has been reached.
54bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * <p>
55bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Note that it is safe to call this method any number of times. The original
56bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * underlying input stream is closed and discarded only once when this
57bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * method is first called.
58bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
59bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @throws IOException if the underlying input stream can not be closed
60bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
61bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public void close() throws IOException {
62bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        in.close();
63bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        in = new ClosedInputStream();
64bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
65bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
66bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
67bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Reads and returns a single byte from the underlying input stream.
68bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * If the underlying stream returns -1, the {@link #close()} method is
69bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * called to automatically close and discard the stream.
70bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
71bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return next byte in the stream, or -1 if no more bytes are available
72bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @throws IOException if the stream could not be read or closed
73bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
74bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public int read() throws IOException {
75bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        int n = in.read();
76bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (n == -1) {
77bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            close();
78bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
79bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return n;
80bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
81bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
82bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
83bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Reads and returns bytes from the underlying input stream to the given
84bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * buffer. If the underlying stream returns -1, the {@link #close()} method
85bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * i called to automatically close and discard the stream.
86bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
87bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param b buffer to which bytes from the stream are written
88bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return number of bytes read, or -1 if no more bytes are available
89bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @throws IOException if the stream could not be read or closed
90bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
91bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public int read(byte[] b) throws IOException {
92bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        int n = in.read(b);
93bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (n == -1) {
94bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            close();
95bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
96bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return n;
97bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
98bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
99bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
100bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Reads and returns bytes from the underlying input stream to the given
101bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * buffer. If the underlying stream returns -1, the {@link #close()} method
102bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * i called to automatically close and discard the stream.
103bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
104bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param b buffer to which bytes from the stream are written
105bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param off start offset within the buffer
106bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param len maximum number of bytes to read
107bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return number of bytes read, or -1 if no more bytes are available
108bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @throws IOException if the stream could not be read or closed
109bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
110bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public int read(byte[] b, int off, int len) throws IOException {
111bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        int n = in.read(b, off, len);
112bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (n == -1) {
113bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            close();
114bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
115bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return n;
116bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
117bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
118bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
119bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Ensures that the stream is closed before it gets garbage-collected.
120bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * As mentioned in {@link #close()}, this is a no-op if the stream has
121bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * already been closed.
122bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @throws Throwable if an error occurs
123bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
124bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected void finalize() throws Throwable {
125bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        close();
126bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        super.finalize();
127bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
128bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
129bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook}
130