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