1e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes/* 2e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * Licensed to the Apache Software Foundation (ASF) under one or more 3e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * contributor license agreements. See the NOTICE file distributed with 4e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * this work for additional information regarding copyright ownership. 5e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * The ASF licenses this file to You under the Apache License, Version 2.0 6e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * (the "License"); you may not use this file except in compliance with 7e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * the License. You may obtain a copy of the License at 8e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * 9e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 10e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * 11e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * Unless required by applicable law or agreed to in writing, software 12e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 13e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * See the License for the specific language governing permissions and 15e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * limitations under the License. 16e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes */ 17e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 18e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughespackage org.apache.harmony.testframework; 19e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 20e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughesimport junit.framework.TestCase; 21e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughesimport junit.framework.TestSuite; 22e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 23e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughesimport java.io.ByteArrayOutputStream; 24e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughesimport java.io.IOException; 25e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughesimport java.io.OutputStream; 26e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 27e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes/** 28e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * Tests behaviour common to wrapping and filtering implementations of {@link 29e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * OutputStream}. 30e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes */ 31e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughespublic abstract class WrapperTester { 32e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 33e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes private boolean throwsExceptions = true; 34e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 35e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes /** 36e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * Creates a new output stream that receives one stream of bytes, optionally 37e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * transforms it, and emits another stream of bytes to {@code delegate}. 38e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes */ 39e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes public abstract OutputStream create(OutputStream delegate) throws Exception; 40e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 41e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes /** 42e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * Decodes the bytes received by the delegate into their original form: the 43e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * bytes originally received by this wrapper. 44e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes */ 45e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes public abstract byte[] decode(byte[] delegateBytes) throws Exception; 46e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 47e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes /** 48e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * Configures whether the stream is expected to throw exceptions when an 49e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * error is encountered. Classes like {@code PrintStream} report errors via 50e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * an API method instead. 51e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes */ 52e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes public WrapperTester setThrowsExceptions(boolean throwsExceptions) { 53e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes this.throwsExceptions = throwsExceptions; 54e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes return this; 55e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 56e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 57e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes public final TestSuite createTests() { 58e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes TestSuite result = new TestSuite(); 59e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes result.addTest(new WrapperSinkTester() 60e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes .setThrowsExceptions(throwsExceptions) 61e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes .createTests()); 62e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 63e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes if (throwsExceptions) { 64e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes result.addTest(new WrapperTestCase("wrapperTestFlushThrowsViaFlush")); 65e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes result.addTest(new WrapperTestCase("wrapperTestFlushThrowsViaClose")); 66e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes result.addTest(new WrapperTestCase("wrapperTestCloseThrows")); 67e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } else { 68e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes result.addTest(new WrapperTestCase("wrapperTestFlushThrowsViaFlushSuppressed")); 69e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes result.addTest(new WrapperTestCase("wrapperTestFlushThrowsViaCloseSuppressed")); 70e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes result.addTest(new WrapperTestCase("wrapperTestCloseThrowsSuppressed")); 71e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 72e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 73e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes return result; 74e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 75e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 76e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes @Override public String toString() { 77e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes return getClass().getName(); 78e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 79e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 80e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes private class WrapperSinkTester extends SinkTester { 81e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes private ClosableByteArrayOutputStream delegate; 82e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 83e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes @Override public OutputStream create() throws Exception { 84e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes delegate = new ClosableByteArrayOutputStream(); 85e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes return WrapperTester.this.create(delegate); 86e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 87e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 88e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes @Override public byte[] getBytes() throws Exception { 89e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes return WrapperTester.this.decode(delegate.bytesOut.toByteArray()); 90e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 91e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 92e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes @Override public String toString() { 93e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes return WrapperTester.this.toString(); 94e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 95e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 96e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 97e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes public class WrapperTestCase extends TestCase { 98e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 99e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes private WrapperTestCase(String name) { 100e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes super(name); 101e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 102e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 103e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes @Override public String getName() { 104e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes return WrapperTester.this.toString() + ":" + super.getName(); 105e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 106e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 107e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes public void wrapperTestFlushThrowsViaFlushSuppressed() throws Exception { 108e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes FailOnFlushOutputStream delegate = new FailOnFlushOutputStream(); 109e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes OutputStream o = create(delegate); 110e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes o.write(new byte[] { 8, 6, 7, 5 }); 111e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes o.write(new byte[] { 3, 0, 9 }); 112e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes o.flush(); 113e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes assertTrue(delegate.flushed); 114e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 115e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 116e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes public void wrapperTestFlushThrowsViaCloseSuppressed() throws Exception { 117e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes FailOnFlushOutputStream delegate = new FailOnFlushOutputStream(); 118e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes OutputStream o = create(delegate); 119e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes o.write(new byte[] { 8, 6, 7, 5 }); 120e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes o.write(new byte[] { 3, 0, 9 }); 121e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes o.close(); 122e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes assertTrue(delegate.flushed); 123e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 124e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 125e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes public void wrapperTestFlushThrowsViaFlush() throws Exception { 126e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes FailOnFlushOutputStream delegate = new FailOnFlushOutputStream(); 127e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 128e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes OutputStream o = create(delegate); 129e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes try { 130e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes // any of these is permitted to flush 131e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes o.write(new byte[] { 8, 6, 7, 5 }); 132e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes o.write(new byte[] { 3, 0, 9 }); 133e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes o.flush(); 134e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes assertTrue(delegate.flushed); 135e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes fail("flush exception ignored"); 136e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } catch (IOException expected) { 137e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes assertEquals("Flush failed" , expected.getMessage()); 138e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 139e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 140e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 141e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes public void wrapperTestFlushThrowsViaClose() throws Exception { 142e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes FailOnFlushOutputStream delegate = new FailOnFlushOutputStream(); 143e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 144e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes OutputStream o = create(delegate); 145e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes try { 146e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes // any of these is permitted to flush 147e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes o.write(new byte[] { 8, 6, 7, 5 }); 148e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes o.write(new byte[] { 3, 0, 9 }); 149e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes o.close(); 150e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes assertTrue(delegate.flushed); 151e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes fail("flush exception ignored"); 152e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } catch (IOException expected) { 153e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes assertEquals("Flush failed" , expected.getMessage()); 154e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 155e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 156e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes try { 157e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes o.write(new byte[] { 4, 4, 5 }); 158e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes fail("expected already closed exception"); 159e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } catch (IOException expected) { 160e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 161e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 162e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 163e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes public void wrapperTestCloseThrows() throws Exception { 164e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes FailOnCloseOutputStream delegate = new FailOnCloseOutputStream(); 165e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes OutputStream o = create(delegate); 166e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes try { 167e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes o.close(); 168e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes assertTrue(delegate.closed); 169e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes fail("close exception ignored"); 170e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } catch (IOException expected) { 171e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes assertEquals("Close failed" , expected.getMessage()); 172e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 173e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 174e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 175e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes public void wrapperTestCloseThrowsSuppressed() throws Exception { 176e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes FailOnCloseOutputStream delegate = new FailOnCloseOutputStream(); 177e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes OutputStream o = create(delegate); 178e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes o.close(); 179e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes assertTrue(delegate.closed); 180e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 181e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 182e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes // adding a new test? Don't forget to update createTests(). 183e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 184e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 185e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes private static class ClosableByteArrayOutputStream extends OutputStream { 186e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes private final ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(); 187e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes private boolean closed = false; 188e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 189e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes @Override public void close() throws IOException { 190e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes closed = true; 191e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 192e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 193e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes @Override public void write(int oneByte) throws IOException { 194e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes if (closed) { 195e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes throw new IOException(); 196e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 197e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes bytesOut.write(oneByte); 198e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 199e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 200e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 201e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes private static class FailOnFlushOutputStream extends OutputStream { 202e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes boolean flushed = false; 203e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes boolean closed = false; 204e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 205e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes @Override public void write(int oneByte) throws IOException { 206e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes if (closed) { 207e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes throw new IOException("Already closed"); 208e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 209e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 210e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 211e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes @Override public void close() throws IOException { 212e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes closed = true; 213e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes flush(); 214e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 215e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 216e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes @Override public void flush() throws IOException { 217e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes if (!flushed) { 218e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes flushed = true; 219e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes throw new IOException("Flush failed"); 220e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 221e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 222e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 223e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 224e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes private static class FailOnCloseOutputStream extends ByteArrayOutputStream { 225e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes boolean closed = false; 226e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 227e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes @Override public void close() throws IOException { 228e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes closed = true; 229e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes throw new IOException("Close failed"); 230e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 231e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 232e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes} 233