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;
+ }
}
}
}