summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--harmony-tests/src/test/java/org/apache/harmony/tests/java/io/FilterOutputStreamTest.java41
-rw-r--r--ojluni/src/main/java/java/io/FilterOutputStream.java52
2 files changed, 90 insertions, 3 deletions
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/io/FilterOutputStreamTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/io/FilterOutputStreamTest.java
index 666955d8ca..cc5b91b771 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/io/FilterOutputStreamTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/io/FilterOutputStreamTest.java
@@ -59,6 +59,47 @@ public class FilterOutputStreamTest extends TestCase {
}
/**
+ * java.io.FilterOutputStream#close_flushthrows()
+ */
+ public void test_close_flushthrows() throws IOException {
+ class FakeOutputStream extends OutputStream {
+
+ public int closedCount;
+
+ @Override
+ public void close() throws IOException {
+ super.close();
+ closedCount++;
+ }
+
+ @Override
+ public void flush() throws IOException {
+ super.flush();
+ throw new IOException("FakeOutputStream#flush() mocked exception");
+ }
+
+ @Override
+ public void write(int b) throws IOException {
+ }
+ }
+
+ FakeOutputStream fos = new FakeOutputStream();
+ os = new FilterOutputStream(fos);
+ os.write(42);
+
+ try {
+ os.close();
+ }
+ catch (IOException e) {
+ }
+ assertEquals("Underlying stream's close() called even if flush() throws", 1,
+ fos.closedCount);
+
+ os.close();
+ assertEquals("Underlying stream's close() called exactly once", 1, fos.closedCount);
+ }
+
+ /**
* java.io.FilterOutputStream#flush()
*/
public void test_flush() throws IOException {
diff --git a/ojluni/src/main/java/java/io/FilterOutputStream.java b/ojluni/src/main/java/java/io/FilterOutputStream.java
index 209e63b77c..89f5ef529b 100644
--- a/ojluni/src/main/java/java/io/FilterOutputStream.java
+++ b/ojluni/src/main/java/java/io/FilterOutputStream.java
@@ -48,6 +48,12 @@ class FilterOutputStream extends OutputStream {
*/
protected OutputStream out;
+ // Android-added: Integrate OpenJDK 9 fix for double-close. http://b/122733269.
+ /**
+ * Whether the stream is closed; implicitly initialized to false.
+ */
+ private boolean closed;
+
/**
* Creates an output stream filter built on top of the specified
* underlying output stream.
@@ -144,18 +150,58 @@ class FilterOutputStream extends OutputStream {
* Closes this output stream and releases any system resources
* associated with the stream.
* <p>
- * The <code>close</code> method of <code>FilterOutputStream</code>
- * calls its <code>flush</code> method, and then calls the
- * <code>close</code> method of its underlying output stream.
+ * When not already closed, the {@code close} method of {@code
+ * FilterOutputStream} calls its {@code flush} method, and then
+ * calls the {@code close} method of its underlying output stream.
*
* @exception IOException if an I/O error occurs.
* @see java.io.FilterOutputStream#flush()
* @see java.io.FilterOutputStream#out
*/
+ // BEGIN Android-changed: Integrate OpenJDK 9 fix for double-close. http://b/122733269.
+ /*
@SuppressWarnings("try")
public void close() throws IOException {
try (OutputStream ostream = out) {
flush();
}
}
+ */
+ @Override
+ public void close() throws IOException {
+ if (closed) {
+ return;
+ }
+ closed = true;
+
+ Throwable flushException = null;
+ try {
+ flush();
+ } catch (Throwable e) {
+ flushException = e;
+ throw e;
+ } finally {
+ if (flushException == null) {
+ out.close();
+ } else {
+ try {
+ out.close();
+ } catch (Throwable closeException) {
+ // evaluate possible precedence of flushException over closeException
+ if ((flushException instanceof ThreadDeath) &&
+ !(closeException instanceof ThreadDeath)) {
+ flushException.addSuppressed(closeException);
+ throw (ThreadDeath) flushException;
+ }
+
+ if (flushException != closeException) {
+ closeException.addSuppressed(flushException);
+ }
+
+ throw closeException;
+ }
+ }
+ }
+ }
+ // END Android-changed: Integrate OpenJDK 9 fix for double-close. http://b/122733269.
}