You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2012/02/17 21:49:39 UTC
svn commit: r1245754 - in /commons/proper/io/trunk/src: changes/changes.xml
main/java/org/apache/commons/io/output/TeeOutputStream.java
test/java/org/apache/commons/io/output/TeeOutputStreamTest.java
Author: ggregory
Date: Fri Feb 17 20:49:39 2012
New Revision: 1245754
URL: http://svn.apache.org/viewvc?rev=1245754&view=rev
Log:
[IO-303] TeeOutputStream fails executing branch.close() when main.close() raised an exception.
Modified:
commons/proper/io/trunk/src/changes/changes.xml
commons/proper/io/trunk/src/main/java/org/apache/commons/io/output/TeeOutputStream.java
commons/proper/io/trunk/src/test/java/org/apache/commons/io/output/TeeOutputStreamTest.java
Modified: commons/proper/io/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/io/trunk/src/changes/changes.xml?rev=1245754&r1=1245753&r2=1245754&view=diff
==============================================================================
--- commons/proper/io/trunk/src/changes/changes.xml (original)
+++ commons/proper/io/trunk/src/changes/changes.xml Fri Feb 17 20:49:39 2012
@@ -40,6 +40,9 @@ The <action> type attribute can be add,u
<body>
<release version="2.2" date="TBA">
+ <action dev="ggregory" type="add" issue="IO-303" due-to="ggregory">
+ TeeOutputStream does not call branch.close() when main.close() throws an exception
+ </action>
<action dev="ggregory" type="add" issue="IO-301" due-to="kaykay.unique">
Add IOUtils.closeQuietly(Selector) necessary
</action>
Modified: commons/proper/io/trunk/src/main/java/org/apache/commons/io/output/TeeOutputStream.java
URL: http://svn.apache.org/viewvc/commons/proper/io/trunk/src/main/java/org/apache/commons/io/output/TeeOutputStream.java?rev=1245754&r1=1245753&r2=1245754&view=diff
==============================================================================
--- commons/proper/io/trunk/src/main/java/org/apache/commons/io/output/TeeOutputStream.java (original)
+++ commons/proper/io/trunk/src/main/java/org/apache/commons/io/output/TeeOutputStream.java Fri Feb 17 20:49:39 2012
@@ -36,7 +36,7 @@ public class TeeOutputStream extends Pro
* @param out the main OutputStream
* @param branch the second OutputStream
*/
- public TeeOutputStream( OutputStream out, OutputStream branch ) {
+ public TeeOutputStream(OutputStream out, OutputStream branch) {
super(out);
this.branch = branch;
}
@@ -87,12 +87,24 @@ public class TeeOutputStream extends Pro
}
/**
- * Closes both streams.
- * @throws IOException if an I/O error occurs
+ * Closes both output streams.
+ *
+ * If closing the main output stream throws an exception, attempt to close the branch output stream.
+ *
+ * If closing the main and branch output streams both throw exceptions, which exceptions is thrown by this method is
+ * currently unspecified and subject to change.
+ *
+ * @throws IOException
+ * if an I/O error occurs
*/
@Override
- public void close() throws IOException {
- super.close();
+ public void close() throws IOException {
+ try {
+ super.close();
+ } catch (IOException e) {
+ this.branch.close();
+ throw e;
+ }
this.branch.close();
}
Modified: commons/proper/io/trunk/src/test/java/org/apache/commons/io/output/TeeOutputStreamTest.java
URL: http://svn.apache.org/viewvc/commons/proper/io/trunk/src/test/java/org/apache/commons/io/output/TeeOutputStreamTest.java?rev=1245754&r1=1245753&r2=1245754&view=diff
==============================================================================
--- commons/proper/io/trunk/src/test/java/org/apache/commons/io/output/TeeOutputStreamTest.java (original)
+++ commons/proper/io/trunk/src/test/java/org/apache/commons/io/output/TeeOutputStreamTest.java Fri Feb 17 20:49:39 2012
@@ -16,12 +16,12 @@
*/
package org.apache.commons.io.output;
-
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import junit.framework.TestCase;
+import org.junit.Assert;
/**
* @version $Revision$ $Date$
@@ -29,37 +29,88 @@ import junit.framework.TestCase;
public class TeeOutputStreamTest extends TestCase {
+ private static class ExceptionOnCloseByteArrayOutputStream extends ByteArrayOutputStream {
+
+ public void close() throws IOException {
+ throw new IOException();
+ }
+ }
+
+ private static class RecordCloseByteArrayOutputStream extends ByteArrayOutputStream {
+
+ boolean closed;
+
+ public void close() throws IOException {
+ super.close();
+ closed = true;
+ }
+ }
+
public TeeOutputStreamTest(String name) {
super(name);
}
+ /**
+ * Tests that the branch {@code OutputStream} is closed when closing the main {@code OutputStream} throws an
+ * exception on {@link TeeOutputStream#close()}.
+ */
+ public void testCloseBranchIOException() {
+ ByteArrayOutputStream badOs = new ExceptionOnCloseByteArrayOutputStream();
+ RecordCloseByteArrayOutputStream goodOs = new RecordCloseByteArrayOutputStream();
+ TeeOutputStream tos = new TeeOutputStream(goodOs, badOs);
+ try {
+ tos.close();
+ Assert.fail("Expected " + IOException.class.getName());
+ } catch (IOException e) {
+ Assert.assertTrue(goodOs.closed);
+ }
+ }
+
+ /**
+ * Tests that the main {@code OutputStream} is closed when closing the branch {@code OutputStream} throws an
+ * exception on {@link TeeOutputStream#close()}.
+ */
+ public void testCloseMainIOException() {
+ ByteArrayOutputStream badOs = new ExceptionOnCloseByteArrayOutputStream();
+ RecordCloseByteArrayOutputStream goodOs = new RecordCloseByteArrayOutputStream();
+ TeeOutputStream tos = new TeeOutputStream(badOs, goodOs);
+ try {
+ tos.close();
+ Assert.fail("Expected " + IOException.class.getName());
+ } catch (IOException e) {
+ Assert.assertTrue(goodOs.closed);
+ }
+ }
+
public void testTee() throws IOException {
ByteArrayOutputStream baos1 = new ByteArrayOutputStream();
ByteArrayOutputStream baos2 = new ByteArrayOutputStream();
TeeOutputStream tos = new TeeOutputStream(baos1, baos2);
- for(int i = 0; i < 20; i++) {
+ for (int i = 0; i < 20; i++) {
tos.write(i);
}
- assertByteArrayEquals("TeeOutputStream.write(int)", baos1.toByteArray(), baos2.toByteArray() );
+ assertByteArrayEquals("TeeOutputStream.write(int)", baos1.toByteArray(), baos2.toByteArray());
byte[] array = new byte[10];
- for(int i = 20; i < 30; i++) {
- array[i-20] = (byte)i;
+ for (int i = 20; i < 30; i++) {
+ array[i - 20] = (byte) i;
}
tos.write(array);
- assertByteArrayEquals("TeeOutputStream.write(byte[])", baos1.toByteArray(), baos2.toByteArray() );
+ assertByteArrayEquals("TeeOutputStream.write(byte[])", baos1.toByteArray(), baos2.toByteArray());
- for(int i = 25; i < 35; i++) {
- array[i-25] = (byte)i;
+ for (int i = 25; i < 35; i++) {
+ array[i - 25] = (byte) i;
}
tos.write(array, 5, 5);
- assertByteArrayEquals("TeeOutputStream.write(byte[], int, int)", baos1.toByteArray(), baos2.toByteArray() );
+ assertByteArrayEquals("TeeOutputStream.write(byte[], int, int)", baos1.toByteArray(), baos2.toByteArray());
+ tos.flush();
+ tos.close();
}
private void assertByteArrayEquals(String msg, byte[] array1, byte[] array2) {
- assertEquals(msg+": array size mismatch", array1.length, array2.length);
- for(int i=0; i<array1.length; i++) {
- assertEquals(msg+": array[ " + i + "] mismatch", array1[i], array2[i]);
+ assertEquals(msg + ": array size mismatch", array1.length, array2.length);
+ for (int i = 0; i < array1.length; i++) {
+ assertEquals(msg + ": array[ " + i + "] mismatch", array1[i], array2[i]);
}
}