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 tests.support; 19e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 20e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughesimport java.io.IOException; 21e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughesimport java.io.Reader; 22e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 23e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughespublic class Support_StringReader extends Reader { 248d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath private String str; 258d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath 268d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath private int markpos = -1; 278d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath 288d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath private int pos = 0; 298d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath 308d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath private int count; 318d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath 328d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath /** 338d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * Construct a StringReader on the String <code>str</code>. The size of 348d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * the reader is set to the <code>length()</code> of the String and the 358d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * Object to synchronize access through is set to <code>str</code>. 368d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * 378d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * @param str the String to filter reads on. 388d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath */ 398d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath public Support_StringReader(String str) { 408d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath super(str); 418d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath this.str = str; 428d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath this.count = str.length(); 438d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } 448d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath 458d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath /** 468d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * This method closes this StringReader. Once it is closed, you can no 478d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * longer read from it. Only the first invocation of this method has any 488d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * effect. 498d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath */ 508d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath @Override 51e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes public void close() { 528d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath synchronized (lock) { 538d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath if (isOpen()) { 54e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes str = null; 55e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 568d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } 578d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } 588d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath 598d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath /** 608d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * Answer a boolean indicating whether or not this StringReader is open. 618d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath */ 628d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath private boolean isOpen() { 638d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath return str != null; 648d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } 658d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath 668d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath /** 678d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * Set a Mark position in this Reader. The parameter <code>readLimit</code> 688d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * is ignored for StringReaders. Sending reset() will reposition the reader 698d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * back to the marked position provided the mark has not been invalidated. 708d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * 718d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * @param readlimit ignored for StringReaders. 728d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * @throws java.io.IOException If an error occurs attempting mark this StringReader. 738d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath */ 748d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath @Override 75e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes public void mark(int readLimit) throws IOException { 768d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath if (readLimit >= 0) { 778d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath synchronized (lock) { 788d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath if (isOpen()) { 79e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes markpos = pos; 80e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } else { 81e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes throw new IOException("StringReader is closed"); 82e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 838d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } 848d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } else { 85e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes throw new IllegalArgumentException(); 86e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 878d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } 888d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath 898d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath /** 908d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * Answers a boolean indicating whether or not this StringReader supports 918d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * mark() and reset(). This method always returns true. 928d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * 938d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * @return <code>true</code> if mark() and reset() are supported, 948d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * <code>false</code> otherwise. This implementation always 958d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * returns <code>true</code>. 968d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath */ 978d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath @Override 98e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes public boolean markSupported() { 998d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath return true; 1008d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } 1018d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath 1028d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath /** 1038d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * Reads a single character from this StringReader and returns the result as 1048d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * an int. The 2 higher-order bytes are set to 0. If the end of reader was 1058d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * encountered then return -1. 1068d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * 1078d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * @return the character read or -1 if end of reader. 1088d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * @throws java.io.IOException If the StringReader is already closed. 1098d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath */ 1108d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath @Override 111e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes public int read() throws IOException { 1128d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath synchronized (lock) { 1138d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath if (isOpen()) { 1148d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath if (pos != count) { 115e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes return str.charAt(pos++); 116e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 1178d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath return -1; 1188d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } 119e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes throw new IOException("StringReader is closed"); 1208d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } 1218d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } 1228d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath 1238d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath /** 1248d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * Reads at most <code>count</code> characters from this StringReader and 1258d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * stores them at <code>offset</code> in the character array 1268d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * <code>buf</code>. Returns the number of characters actually read or -1 1278d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * if the end of reader was encountered. 1288d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * 1298d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * @param buf character array to store the read characters 1308d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * @param offset offset in buf to store the read characters 1318d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * @param count maximum number of characters to read 1328d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * @return the number of characters read or -1 if end of reader. 1338d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * @throws java.io.IOException If the StringReader is closed. 1348d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath */ 1358d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath @Override 136e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes public int read(char buf[], int offset, int count) throws IOException { 1378d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath // avoid int overflow 1388d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath if (0 <= offset && offset <= buf.length && 0 <= count 1398d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath && count <= buf.length - offset) { 1408d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath synchronized (lock) { 1418d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath if (isOpen()) { 1428d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath if (pos == this.count) { 143e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes return -1; 144e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 1458d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath int end = pos + count > this.count ? this.count : pos 1468d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath + count; 1478d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath str.getChars(pos, end, buf, offset); 1488d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath int read = end - pos; 1498d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath pos = end; 1508d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath return read; 1518d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } 152e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes throw new IOException("StringReader is closed"); 1538d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } 1548d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } 155e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes throw new ArrayIndexOutOfBoundsException(); 1568d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } 1578d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath 1588d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath /** 1598d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * Answers a <code>boolean</code> indicating whether or not this 1608d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * StringReader is ready to be read without blocking. If the result is 1618d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * <code>true</code>, the next <code>read()</code> will not block. If 1628d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * the result is <code>false</code> this Reader may or may not block when 1638d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * <code>read()</code> is sent. The implementation in StringReader always 1648d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * returns <code>true</code> even when it has been closed. 1658d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * 1668d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * @return <code>true</code> if the receiver will not block when 1678d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * <code>read()</code> is called, <code>false</code> if unknown 1688d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * or blocking will occur. 1698d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * @throws java.io.IOException If an IO error occurs. 1708d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath */ 1718d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath @Override 172e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes public boolean ready() throws IOException { 1738d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath synchronized (lock) { 1748d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath if (isOpen()) { 175e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes return true; 176e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 1778d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath throw new IOException("StringReader is closed"); 1788d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } 1798d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } 1808d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath 1818d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath /** 1828d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * Reset this StringReader's position to the last <code>mark()</code> 1838d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * location. Invocations of <code>read()/skip()</code> will occur from 1848d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * this new location. If this Reader was not marked, the StringReader is 1858d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * reset to the beginning of the String. 1868d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * 1878d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * @throws java.io.IOException If this StringReader has already been closed. 1888d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath */ 1898d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath @Override 190e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes public void reset() throws IOException { 1918d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath synchronized (lock) { 1928d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath if (isOpen()) { 193e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes pos = markpos != -1 ? markpos : 0; 194e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } else { 195e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes throw new IOException("StringReader is closed"); 196e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 1978d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } 1988d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } 1998d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath 2008d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath /** 2018d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * Skips <code>count</code> number of characters in this StringReader. 2028d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * Subsequent <code>read()</code>'s will not return these characters 2038d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * unless <code>reset()</code> is used. 2048d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * 2058d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * @param count The number of characters to skip. 2068d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * @return the number of characters actually skipped. 2078d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * @throws java.io.IOException If this StringReader has already been closed. 2088d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath */ 2098d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath @Override 210e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes public long skip(long count) throws IOException { 2118d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath synchronized (lock) { 2128d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath if (isOpen()) { 2138d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath if (count <= 0) { 214e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes return 0; 215e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes } 2168d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath long skipped = 0; 2178d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath if (count < this.count - pos) { 2188d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath pos = pos + (int) count; 2198d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath skipped = count; 2208d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } else { 2218d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath skipped = this.count - pos; 2228d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath pos = this.count; 2238d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } 2248d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath return skipped; 2258d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } 226e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes throw new IOException("StringReader is closed"); 2278d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } 2288d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } 229e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes} 230