001: /*
002: * Copyright 1999,2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.apache.jasper.xmlparser;
018:
019: import java.io.InputStream;
020: import java.io.IOException;
021: import java.io.Reader;
022: import org.apache.jasper.compiler.Localizer;
023:
024: /**
025: * A simple ASCII byte reader. This is an optimized reader for reading
026: * byte streams that only contain 7-bit ASCII characters.
027: *
028: * @author Andy Clark, IBM
029: *
030: * @version $Id: ASCIIReader.java,v 1.3 2004/03/17 19:23:05 luehe Exp $
031: */
032: public class ASCIIReader extends Reader {
033:
034: //
035: // Constants
036: //
037:
038: /** Default byte buffer size (2048). */
039: public static final int DEFAULT_BUFFER_SIZE = 2048;
040:
041: //
042: // Data
043: //
044:
045: /** Input stream. */
046: protected InputStream fInputStream;
047:
048: /** Byte buffer. */
049: protected byte[] fBuffer;
050:
051: //
052: // Constructors
053: //
054:
055: /**
056: * Constructs an ASCII reader from the specified input stream
057: * and buffer size.
058: *
059: * @param inputStream The input stream.
060: * @param size The initial buffer size.
061: */
062: public ASCIIReader(InputStream inputStream, int size) {
063: fInputStream = inputStream;
064: fBuffer = new byte[size];
065: }
066:
067: //
068: // Reader methods
069: //
070:
071: /**
072: * Read a single character. This method will block until a character is
073: * available, an I/O error occurs, or the end of the stream is reached.
074: *
075: * <p> Subclasses that intend to support efficient single-character input
076: * should override this method.
077: *
078: * @return The character read, as an integer in the range 0 to 127
079: * (<tt>0x00-0x7f</tt>), or -1 if the end of the stream has
080: * been reached
081: *
082: * @exception IOException If an I/O error occurs
083: */
084: public int read() throws IOException {
085: int b0 = fInputStream.read();
086: if (b0 > 0x80) {
087: throw new IOException(Localizer.getMessage(
088: "jsp.error.xml.invalidASCII", Integer.toString(b0)));
089: }
090: return b0;
091: } // read():int
092:
093: /**
094: * Read characters into a portion of an array. This method will block
095: * until some input is available, an I/O error occurs, or the end of the
096: * stream is reached.
097: *
098: * @param ch Destination buffer
099: * @param offset Offset at which to start storing characters
100: * @param length Maximum number of characters to read
101: *
102: * @return The number of characters read, or -1 if the end of the
103: * stream has been reached
104: *
105: * @exception IOException If an I/O error occurs
106: */
107: public int read(char ch[], int offset, int length)
108: throws IOException {
109: if (length > fBuffer.length) {
110: length = fBuffer.length;
111: }
112: int count = fInputStream.read(fBuffer, 0, length);
113: for (int i = 0; i < count; i++) {
114: int b0 = fBuffer[i];
115: if (b0 > 0x80) {
116: throw new IOException(Localizer.getMessage(
117: "jsp.error.xml.invalidASCII", Integer
118: .toString(b0)));
119: }
120: ch[offset + i] = (char) b0;
121: }
122: return count;
123: } // read(char[],int,int)
124:
125: /**
126: * Skip characters. This method will block until some characters are
127: * available, an I/O error occurs, or the end of the stream is reached.
128: *
129: * @param n The number of characters to skip
130: *
131: * @return The number of characters actually skipped
132: *
133: * @exception IOException If an I/O error occurs
134: */
135: public long skip(long n) throws IOException {
136: return fInputStream.skip(n);
137: } // skip(long):long
138:
139: /**
140: * Tell whether this stream is ready to be read.
141: *
142: * @return True if the next read() is guaranteed not to block for input,
143: * false otherwise. Note that returning false does not guarantee that the
144: * next read will block.
145: *
146: * @exception IOException If an I/O error occurs
147: */
148: public boolean ready() throws IOException {
149: return false;
150: } // ready()
151:
152: /**
153: * Tell whether this stream supports the mark() operation.
154: */
155: public boolean markSupported() {
156: return fInputStream.markSupported();
157: } // markSupported()
158:
159: /**
160: * Mark the present position in the stream. Subsequent calls to reset()
161: * will attempt to reposition the stream to this point. Not all
162: * character-input streams support the mark() operation.
163: *
164: * @param readAheadLimit Limit on the number of characters that may be
165: * read while still preserving the mark. After
166: * reading this many characters, attempting to
167: * reset the stream may fail.
168: *
169: * @exception IOException If the stream does not support mark(),
170: * or if some other I/O error occurs
171: */
172: public void mark(int readAheadLimit) throws IOException {
173: fInputStream.mark(readAheadLimit);
174: } // mark(int)
175:
176: /**
177: * Reset the stream. If the stream has been marked, then attempt to
178: * reposition it at the mark. If the stream has not been marked, then
179: * attempt to reset it in some way appropriate to the particular stream,
180: * for example by repositioning it to its starting point. Not all
181: * character-input streams support the reset() operation, and some support
182: * reset() without supporting mark().
183: *
184: * @exception IOException If the stream has not been marked,
185: * or if the mark has been invalidated,
186: * or if the stream does not support reset(),
187: * or if some other I/O error occurs
188: */
189: public void reset() throws IOException {
190: fInputStream.reset();
191: } // reset()
192:
193: /**
194: * Close the stream. Once a stream has been closed, further read(),
195: * ready(), mark(), or reset() invocations will throw an IOException.
196: * Closing a previously-closed stream, however, has no effect.
197: *
198: * @exception IOException If an I/O error occurs
199: */
200: public void close() throws IOException {
201: fInputStream.close();
202: } // close()
203:
204: } // class ASCIIReader
|