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 */ 017package org.apache.commons.io.input; 018 019import static org.apache.commons.io.IOUtils.EOF; 020 021import java.io.IOException; 022import java.io.InputStream; 023 024import org.apache.commons.io.build.AbstractStreamBuilder; 025 026/** 027 * Proxy stream that closes and discards the underlying stream as soon as the end of input has been reached or when the stream is explicitly closed. Not even a 028 * reference to the underlying stream is kept after it has been closed, so any allocated in-memory buffers can be freed even if the client application still 029 * keeps a reference to the proxy stream. 030 * <p> 031 * This class is typically used to release any resources related to an open stream as soon as possible even if the client application (by not explicitly closing 032 * the stream when no longer needed) or the underlying stream (by not releasing resources once the last byte has been read) do not do that. 033 * </p> 034 * <p> 035 * To build an instance, use {@link Builder}. 036 * </p> 037 * 038 * @since 1.4 039 * @see Builder 040 */ 041public class AutoCloseInputStream extends ProxyInputStream { 042 043 // @formatter:off 044 /** 045 * Builds a new {@link AutoCloseInputStream} instance. 046 * 047 * <p> 048 * For example: 049 * </p> 050 * <pre>{@code 051 * AutoCloseInputStream s = AutoCloseInputStream.builder() 052 * .setPath(path) 053 * .get();} 054 * </pre> 055 * <pre>{@code 056 * AutoCloseInputStream s = AutoCloseInputStream.builder() 057 * .setInputStream(inputStream) 058 * .get();} 059 * </pre> 060 * 061 * @see #get() 062 * @since 2.13.0 063 */ 064 // @formatter:on 065 public static class Builder extends AbstractStreamBuilder<AutoCloseInputStream, Builder> { 066 067 /** 068 * Builds a new {@link AutoCloseInputStream}. 069 * <p> 070 * You must set input that supports {@link #getInputStream()}, otherwise, this method throws an exception. 071 * </p> 072 * <p> 073 * This builder use the following aspects: 074 * </p> 075 * <ul> 076 * <li>{@link #getInputStream()}</li> 077 * </ul> 078 * 079 * @return a new instance. 080 * @throws IllegalStateException if the {@code origin} is {@code null}. 081 * @throws UnsupportedOperationException if the origin cannot be converted to an {@link InputStream}. 082 * @throws IOException if an I/O error occurs. 083 * @see #getInputStream() 084 */ 085 @SuppressWarnings("resource") // Caller closes 086 @Override 087 public AutoCloseInputStream get() throws IOException { 088 return new AutoCloseInputStream(getInputStream()); 089 } 090 091 } 092 093 /** 094 * Constructs a new {@link Builder}. 095 * 096 * @return a new {@link Builder}. 097 * @since 2.12.0 098 */ 099 public static Builder builder() { 100 return new Builder(); 101 } 102 103 /** 104 * Constructs an automatically closing proxy for the given input stream. 105 * 106 * @param in underlying input stream 107 * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()} 108 */ 109 @SuppressWarnings("resource") // ClosedInputStream.nonNull() doesn't allocate 110 @Deprecated 111 public AutoCloseInputStream(final InputStream in) { 112 super(ClosedInputStream.ifNull(in)); 113 } 114 115 /** 116 * Automatically closes the stream if the end of stream was reached. 117 * 118 * @param n number of bytes read, or -1 if no more bytes are available 119 * @throws IOException if the stream could not be closed 120 * @since 2.0 121 */ 122 @Override 123 protected void afterRead(final int n) throws IOException { 124 if (n == EOF) { 125 close(); 126 } 127 } 128 129 /** 130 * Closes the underlying input stream and replaces the reference to it with a {@link ClosedInputStream} instance. 131 * <p> 132 * This method is automatically called by the read methods when the end of input has been reached. 133 * </p> 134 * <p> 135 * Note that it is safe to call this method any number of times. The original underlying input stream is closed and discarded only once when this method is 136 * first called. 137 * </p> 138 * 139 * @throws IOException if the underlying input stream can not be closed 140 */ 141 @Override 142 public void close() throws IOException { 143 super.close(); 144 in = ClosedInputStream.INSTANCE; 145 } 146 147 /** 148 * Ensures that the stream is closed before it gets garbage-collected. As mentioned in {@link #close()}, this is a no-op if the stream has already been 149 * closed. 150 * 151 * @throws Throwable if an error occurs 152 */ 153 @Override 154 protected void finalize() throws Throwable { 155 close(); 156 super.finalize(); 157 } 158 159}