src/java.base/share/classes/java/io/FilterOutputStream.java

Print this page
rev 12234 : 8042377: BufferedWriter and FilteredOutputStream.close throw IAE if flush and close throw equal exceptions
Summary: Explcitly handle IOExceptions in FilteredOutputStream.close() instead of using try-with-resources approach.
Reviewed-by: XXX

*** 1,7 **** /* ! * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this --- 1,7 ---- /* ! * Copyright (c) 1994, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this
*** 23,32 **** --- 23,34 ---- * questions. */ package java.io; + import java.util.concurrent.atomic.AtomicBoolean; + /** * This class is the superclass of all classes that filter output * streams. These streams sit on top of an already existing output * stream (the <i>underlying</i> output stream) which it uses as its * basic sink of data, but possibly transforming the data along the
*** 39,56 **** * methods as well as provide additional methods and fields. * * @author Jonathan Payne * @since 1.0 */ ! public ! class FilterOutputStream extends OutputStream { /** * The underlying output stream to be filtered. */ protected OutputStream out; ! private boolean closed; /** * Creates an output stream filter built on top of the specified * underlying output stream. * --- 41,60 ---- * methods as well as provide additional methods and fields. * * @author Jonathan Payne * @since 1.0 */ ! public class FilterOutputStream extends OutputStream { /** * The underlying output stream to be filtered. */ protected OutputStream out; ! /** ! * Whether the stream is closed; initialized to false. ! */ ! private final AtomicBoolean closed = new AtomicBoolean(); /** * Creates an output stream filter built on top of the specified * underlying output stream. *
*** 73,82 **** --- 77,87 ---- * Implements the abstract <tt>write</tt> method of <tt>OutputStream</tt>. * * @param b the <code>byte</code>. * @exception IOException if an I/O error occurs. */ + @Override public void write(int b) throws IOException { out.write(b); } /**
*** 93,102 **** --- 98,108 ---- * * @param b the data to be written. * @exception IOException if an I/O error occurs. * @see java.io.FilterOutputStream#write(byte[], int, int) */ + @Override public void write(byte b[]) throws IOException { write(b, 0, b.length); } /**
*** 117,126 **** --- 123,133 ---- * @param off the start offset in the data. * @param len the number of bytes to write. * @exception IOException if an I/O error occurs. * @see java.io.FilterOutputStream#write(int) */ + @Override public void write(byte b[], int off, int len) throws IOException { if ((off | len | (b.length - (len + off)) | (off + len)) < 0) throw new IndexOutOfBoundsException(); for (int i = 0 ; i < len ; i++) {
*** 136,145 **** --- 143,153 ---- * calls the <code>flush</code> method of its underlying output stream. * * @exception IOException if an I/O error occurs. * @see java.io.FilterOutputStream#out */ + @Override public void flush() throws IOException { out.flush(); } /**
*** 153,166 **** * @exception IOException if an I/O error occurs. * @see java.io.FilterOutputStream#flush() * @see java.io.FilterOutputStream#out */ @SuppressWarnings("try") public void close() throws IOException { ! if (closed) ! return; ! closed = true; ! try (OutputStream ostream = out) { flush(); } } } --- 161,192 ---- * @exception IOException if an I/O error occurs. * @see java.io.FilterOutputStream#flush() * @see java.io.FilterOutputStream#out */ @SuppressWarnings("try") + @Override public void close() throws IOException { ! if (closed.compareAndSet(false, true)) { ! IOException flushException = null; ! ! try { flush(); + } catch (IOException e) { + flushException = e; + } finally { + try { + out.close(); + } catch (IOException closeException) { + if (flushException != null && + flushException != closeException) { + closeException.addSuppressed(flushException); + } + throw closeException; + } + } + + if (flushException != null) { + throw flushException; + } } } }