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]);
         }
     }