1 /* 2 * Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* @test 25 @bug 4150737 26 @summary Ensure that StreamTokenizer does not read any further ahead 27 than is absolutely necessary 28 */ 29 30 import java.io.ByteArrayInputStream; 31 import java.io.InputStream; 32 import java.io.InputStreamReader; 33 import java.io.Reader; 34 import java.io.StreamTokenizer; 35 import java.io.IOException; 36 37 38 public class ReadAhead { 39 40 41 /* An InputStream subclass that cannot read past a given limit */ 42 private static class LimitedInputStream extends InputStream { 43 44 private String input; 45 private int limit; /* Do not allow input[limit] to be read */ 46 private int next = 0; 47 LimitedInputStream(String input, int limit)48 public LimitedInputStream(String input, int limit) { 49 this.input = input; 50 this.limit = limit; 51 } 52 read()53 public int read() throws IOException { 54 if (next >= limit) 55 throw new IOException("Attempted to read too far in stream"); 56 return input.charAt(next++); 57 } 58 59 } 60 61 62 /* A Reader subclass that cannot read past a given limit */ 63 private static class LimitedReader extends Reader { 64 65 private String input; 66 private int limit; /* Do not allow input[limit] to be read */ 67 private int next = 0; 68 LimitedReader(String input, int limit)69 public LimitedReader(String input, int limit) { 70 this.input = input; 71 this.limit = limit; 72 } 73 read()74 public int read() throws IOException { 75 if (next >= limit) 76 throw new IOException("Attempted to read too far in stream"); 77 return input.charAt(next++); 78 } 79 read(char[] b, int off, int len)80 public int read(char[] b, int off, int len) throws IOException { 81 int top = off + len; 82 int i; 83 for (i = off; i < top; i++) { 84 int c = read(); 85 if (c < 0) break; 86 b[i] = (char)c; 87 } 88 return i - off; 89 } 90 close()91 public void close() { } 92 93 } 94 95 96 /* Interface for objects that can create new StreamTokenizers 97 with a given limited input */ 98 private static interface StreamTokenizerMaker { create(String input, int limit)99 public StreamTokenizer create(String input, int limit); 100 } 101 fail(String why)102 private static void fail(String why) throws Exception { 103 throw new Exception(why); 104 } 105 test(StreamTokenizer st)106 private static void test(StreamTokenizer st) throws Exception { 107 st.eolIsSignificant(true); 108 int tt = st.nextToken(); 109 if (tt != StreamTokenizer.TT_WORD) fail("expected TT_WORD"); 110 if (!st.sval.equals("foo")) fail("expected word token \"foo\""); 111 tt = st.nextToken(); 112 if (tt != StreamTokenizer.TT_EOL) fail("expected TT_EOL"); 113 } 114 test(StreamTokenizerMaker stm)115 private static void test(StreamTokenizerMaker stm) throws Exception { 116 test(stm.create("foo\nx", 4)); 117 test(stm.create("foo\r\nx", 4)); 118 } 119 120 main(String[] args)121 public static void main(String[] args) throws Exception { 122 123 /* InputStream case */ 124 test(new StreamTokenizerMaker() { 125 public StreamTokenizer create(String input, int limit) { 126 return new StreamTokenizer(new LimitedInputStream(input, limit)); 127 }}); 128 129 /* Reader case */ 130 test(new StreamTokenizerMaker() { 131 public StreamTokenizer create(String input, int limit) { 132 return new StreamTokenizer(new LimitedReader(input, limit)); 133 }}); 134 135 } 136 137 } 138