CharWrapperTester.java revision e98fbf8686c5289bf03fe5c3de7ff82d3a77104d
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.IOException; 24e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughesimport java.io.Writer; 25e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 26e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes/** 27e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * Tests behaviour common to wrapping and filtering implementations of {@link 28e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * Writer}. 29e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes */ 30e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughespublic abstract class CharWrapperTester { 31e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 32e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes private boolean throwsExceptions = true; 33e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 34e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes /** 35e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * Creates a new output stream that receives one stream of chars, optionally 36e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * transforms it, and emits another stream of chars to {@code delegate}. 37e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes */ 38e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes public abstract Writer create(Writer delegate) throws Exception; 39e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 40e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes /** 41e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * Decodes the chars received by the delegate into their original form: the 42e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * chars originally received by this wrapper. 43e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes */ 44e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes public abstract char[] decode(char[] delegateChars) throws Exception; 45e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 46e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes /** 47e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * Configures whether the writer is expected to throw exceptions when an 48e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * error is encountered. Classes like {@code PrintWriter} report errors via 49e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * an API method instead. 50e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes */ 51e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes public CharWrapperTester setThrowsExceptions(boolean throwsExceptions) { 52e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes this.throwsExceptions = throwsExceptions; 53e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes return this; 54e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 55e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 56e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes public final TestSuite createTests() { 57e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes TestSuite result = new TestSuite(); 58e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes result.addTest(new WrapperSinkTester() 59e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes .setThrowsExceptions(throwsExceptions) 60e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes .createTests()); 61e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 62e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes if (throwsExceptions) { 63e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes result.addTest(new WrapperTestCase("wrapperTestFlushThrowsViaFlush")); 64e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes result.addTest(new WrapperTestCase("wrapperTestFlushThrowsViaClose")); 65e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes result.addTest(new WrapperTestCase("wrapperTestCloseThrows")); 66e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } else { 67e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes result.addTest(new WrapperTestCase("wrapperTestFlushThrowsViaFlushSuppressed")); 68e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes result.addTest(new WrapperTestCase("wrapperTestFlushThrowsViaCloseSuppressed")); 69e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes result.addTest(new WrapperTestCase("wrapperTestCloseThrowsSuppressed")); 70e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 71e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 72e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes return result; 73e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 74e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 75e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes @Override public String toString() { 76e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes return getClass().getName(); 77e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 78e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 79e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes private class WrapperSinkTester extends CharSinkTester { 80e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes private ClosableStringWriter delegate; 81e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 82e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes @Override public Writer create() throws Exception { 83e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes delegate = new ClosableStringWriter(); 84e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes return CharWrapperTester.this.create(delegate); 85e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 86e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 87e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes @Override public char[] getChars() throws Exception { 88e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes return decode(delegate.buffer.toString().toCharArray()); 89e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 90e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 91e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes @Override public String toString() { 92e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes return CharWrapperTester.this.toString(); 93e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 94e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 95e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 96e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes public class WrapperTestCase extends TestCase { 97e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 98e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes private WrapperTestCase(String name) { 99e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes super(name); 100e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 101e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 102e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes @Override public String getName() { 103e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes return CharWrapperTester.this.toString() + ":" + super.getName(); 104e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 105e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 106e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes public void wrapperTestFlushThrowsViaFlushSuppressed() throws Exception { 107e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes FailOnFlushWriter delegate = new FailOnFlushWriter(); 108e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes Writer o = create(delegate); 109e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes o.write("BUT"); 110e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes o.write("TERS"); 111e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes o.flush(); 112e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes assertTrue(delegate.flushed); 113e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 114e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 115e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes public void wrapperTestFlushThrowsViaCloseSuppressed() throws Exception { 116e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes FailOnFlushWriter delegate = new FailOnFlushWriter(); 117e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes Writer o = create(delegate); 118e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes o.write("BUT"); 119e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes o.write("TERS"); 120e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes o.close(); 121e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes assertTrue(delegate.flushed); 122e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 123e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 124e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes public void wrapperTestFlushThrowsViaFlush() throws Exception { 125e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes FailOnFlushWriter delegate = new FailOnFlushWriter(); 126e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 127e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes Writer o = create(delegate); 128e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes try { 129e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes // any of these is permitted to flush 130e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes o.write("BUT"); 131e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes o.write("TERS"); 132e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes o.flush(); 133e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes assertTrue(delegate.flushed); 134e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes fail("flush exception ignored"); 135e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } catch (IOException expected) { 136e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes assertEquals("Flush failed" , expected.getMessage()); 137e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 138e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 139e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 140e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes public void wrapperTestFlushThrowsViaClose() throws Exception { 141e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes FailOnFlushWriter delegate = new FailOnFlushWriter(); 142e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 143e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes Writer o = create(delegate); 144e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes try { 145e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes // any of these is permitted to flush 146e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes o.write("BUT"); 147e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes o.write("TERS"); 148e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes o.close(); 149e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes assertTrue(delegate.flushed); 150e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes fail("flush exception ignored"); 151e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } catch (IOException expected) { 152e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes assertEquals("Flush failed" , expected.getMessage()); 153e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 154e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 155e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes try { 156e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes o.write("BARK"); 157e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes fail("expected already closed exception"); 158e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } catch (IOException expected) { 159e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 160e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 161e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 162e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes public void wrapperTestCloseThrows() throws Exception { 163e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes FailOnCloseWriter delegate = new FailOnCloseWriter(); 164e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes Writer o = create(delegate); 165e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes try { 166e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes o.close(); 167e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes assertTrue(delegate.closed); 168e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes fail("close exception ignored"); 169e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } catch (IOException expected) { 170e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes assertEquals("Close failed" , expected.getMessage()); 171e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 172e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 173e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 174e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes public void wrapperTestCloseThrowsSuppressed() throws Exception { 175e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes FailOnCloseWriter delegate = new FailOnCloseWriter(); 176e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes Writer o = create(delegate); 177e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes o.close(); 178e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes assertTrue(delegate.closed); 179e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 180e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 181e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes // adding a new test? Don't forget to update createTests(). 182e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 183e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 184e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes /** 185e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * A custom Writer that respects the closed state. The built-in StringWriter 186e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * doesn't respect close(), which makes testing wrapped streams difficult. 187e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes */ 188e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes private static class ClosableStringWriter extends Writer { 189e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes private final StringBuilder buffer = new StringBuilder(); 190e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes private boolean closed = false; 191e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 192e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes @Override public void close() throws IOException { 193e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes closed = true; 194e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 195e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 196e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes @Override public void flush() throws IOException {} 197e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 198e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes @Override public void write(char[] buf, int offset, int count) throws IOException { 199e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes if (closed) { 200e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes throw new IOException(); 201e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 202e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes buffer.append(buf, offset, count); 203e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 204e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 205e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 206e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes private static class FailOnFlushWriter extends Writer { 207e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes boolean flushed = false; 208e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes boolean closed = false; 209e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 210e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes @Override public void write(char[] buf, int offset, int count) throws IOException { 211e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes if (closed) { 212e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes throw new IOException("Already closed"); 213e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 214e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 215e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 216e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes @Override public void close() throws IOException { 217e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes closed = true; 218e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes flush(); 219e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 220e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 221e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes @Override public void flush() throws IOException { 222e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes if (!flushed) { 223e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes flushed = true; 224e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes throw new IOException("Flush failed"); 225e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 226e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 227e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 228e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 229e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes private static class FailOnCloseWriter extends Writer { 230e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes boolean closed = false; 231e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 232e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes @Override public void flush() throws IOException {} 233e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 234e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes @Override public void write(char[] buf, int offset, int count) throws IOException {} 235e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 236e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes @Override public void close() throws IOException { 237e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes closed = true; 238e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes throw new IOException("Close failed"); 239e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 240e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 241e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes}