1 /* 2 * Copyright (c) 1994, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.io; 27 28 /** 29 * This class is the superclass of all classes that filter output 30 * streams. These streams sit on top of an already existing output 31 * stream (the <i>underlying</i> output stream) which it uses as its 32 * basic sink of data, but possibly transforming the data along the 33 * way or providing additional functionality. 34 * <p> 35 * The class <code>FilterOutputStream</code> itself simply overrides 36 * all methods of <code>OutputStream</code> with versions that pass 37 * all requests to the underlying output stream. Subclasses of 38 * <code>FilterOutputStream</code> may further override some of these 39 * methods as well as provide additional methods and fields. 40 * 41 * @author Jonathan Payne 42 * @since 1.0 43 */ 44 public class FilterOutputStream extends OutputStream { 45 /** 46 * The underlying output stream to be filtered. 47 */ 48 protected OutputStream out; 49 50 /** 51 * Whether the stream is closed; implicitly initialized to false. 52 */ 53 private boolean closed; 54 55 /** 56 * Creates an output stream filter built on top of the specified 57 * underlying output stream. 58 * 59 * @param out the underlying output stream to be assigned to 60 * the field <tt>this.out</tt> for later use, or 61 * <code>null</code> if this instance is to be 62 * created without an underlying stream. 63 */ 64 public FilterOutputStream(OutputStream out) { 65 this.out = out; 66 } 67 68 /** 69 * Writes the specified <code>byte</code> to this output stream. 70 * <p> 71 * The <code>write</code> method of <code>FilterOutputStream</code> 72 * calls the <code>write</code> method of its underlying output stream, 73 * that is, it performs <tt>out.write(b)</tt>. 74 * <p> 75 * Implements the abstract <tt>write</tt> method of <tt>OutputStream</tt>. 76 * 77 * @param b the <code>byte</code>. 78 * @exception IOException if an I/O error occurs. 79 */ 80 @Override 81 public void write(int b) throws IOException { 82 out.write(b); 83 } 84 85 /** 86 * Writes <code>b.length</code> bytes to this output stream. 87 * <p> 88 * The <code>write</code> method of <code>FilterOutputStream</code> 89 * calls its <code>write</code> method of three arguments with the 90 * arguments <code>b</code>, <code>0</code>, and 91 * <code>b.length</code>. 92 * <p> 93 * Note that this method does not call the one-argument 94 * <code>write</code> method of its underlying stream with the single 95 * argument <code>b</code>. 96 * 97 * @param b the data to be written. 98 * @exception IOException if an I/O error occurs. 99 * @see java.io.FilterOutputStream#write(byte[], int, int) 100 */ 101 @Override 102 public void write(byte b[]) throws IOException { 103 write(b, 0, b.length); 104 } 105 106 /** 107 * Writes <code>len</code> bytes from the specified 108 * <code>byte</code> array starting at offset <code>off</code> to 109 * this output stream. 110 * <p> 111 * The <code>write</code> method of <code>FilterOutputStream</code> 112 * calls the <code>write</code> method of one argument on each 113 * <code>byte</code> to output. 114 * <p> 115 * Note that this method does not call the <code>write</code> method 116 * of its underlying input stream with the same arguments. Subclasses 117 * of <code>FilterOutputStream</code> should provide a more efficient 118 * implementation of this method. 119 * 120 * @param b the data. 121 * @param off the start offset in the data. 122 * @param len the number of bytes to write. 123 * @exception IOException if an I/O error occurs. 124 * @see java.io.FilterOutputStream#write(int) 125 */ 126 @Override 127 public void write(byte b[], int off, int len) throws IOException { 128 if ((off | len | (b.length - (len + off)) | (off + len)) < 0) 129 throw new IndexOutOfBoundsException(); 130 131 for (int i = 0 ; i < len ; i++) { 132 write(b[off + i]); 133 } 134 } 135 136 /** 137 * Flushes this output stream and forces any buffered output bytes 138 * to be written out to the stream. 139 * <p> 140 * The <code>flush</code> method of <code>FilterOutputStream</code> 141 * calls the <code>flush</code> method of its underlying output stream. 142 * 143 * @exception IOException if an I/O error occurs. 144 * @see java.io.FilterOutputStream#out 145 */ 146 @Override 147 public void flush() throws IOException { 148 out.flush(); 149 } 150 151 /** 152 * Closes this output stream and releases any system resources 153 * associated with the stream. 154 * <p> 155 * When not already closed, the {@code close} method of {@code 156 * FilterOutputStream} calls its {@code flush} method, and then 157 * calls the {@code close} method of its underlying output stream. 158 * 159 * @exception IOException if an I/O error occurs. 160 * @see java.io.FilterOutputStream#flush() 161 * @see java.io.FilterOutputStream#out 162 */ 163 @Override 164 public void close() throws IOException { 165 if (closed) { 166 return; 167 } 168 closed = true; 169 170 Throwable flushException = null; 171 try { 172 flush(); 173 } catch (Throwable e) { 174 flushException = e; 175 throw e; 176 } finally { 177 if (flushException == null) { 178 out.close(); 179 } else { 180 try { 181 out.close(); 182 } catch (Throwable closeException) { 183 // evaluate possible precedence of flushException over closeException 184 if ((flushException instanceof ThreadDeath) && 185 !(closeException instanceof ThreadDeath)) { 186 flushException.addSuppressed(closeException); 187 throw (ThreadDeath) flushException; 188 } 189 190 if (flushException != closeException) { 191 closeException.addSuppressed(flushException); 192 } 193 194 throw closeException; 195 } 196 } 197 } 198 } 199 }