001: /*
002:
003: ============================================================================
004: The Apache Software License, Version 1.1
005: ============================================================================
006:
007: Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved.
008:
009: Redistribution and use in source and binary forms, with or without modifica-
010: tion, are permitted provided that the following conditions are met:
011:
012: 1. Redistributions of source code must retain the above copyright notice,
013: this list of conditions and the following disclaimer.
014:
015: 2. Redistributions in binary form must reproduce the above copyright notice,
016: this list of conditions and the following disclaimer in the documentation
017: and/or other materials provided with the distribution.
018:
019: 3. The end-user documentation included with the redistribution, if any, must
020: include the following acknowledgment: "This product includes software
021: developed by the Apache Software Foundation (http://www.apache.org/)."
022: Alternately, this acknowledgment may appear in the software itself, if
023: and wherever such third-party acknowledgments normally appear.
024:
025: 4. The names "Batik" and "Apache Software Foundation" must not be
026: used to endorse or promote products derived from this software without
027: prior written permission. For written permission, please contact
028: apache@apache.org.
029:
030: 5. Products derived from this software may not be called "Apache", nor may
031: "Apache" appear in their name, without prior written permission of the
032: Apache Software Foundation.
033:
034: THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
035: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
036: FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
037: APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
038: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
039: DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
040: OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
041: ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
042: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
043: THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
044:
045: This software consists of voluntary contributions made by many individuals
046: on behalf of the Apache Software Foundation. For more information on the
047: Apache Software Foundation, please see <http://www.apache.org/>.
048:
049: */
050:
051: package org.apache.batik.util.io;
052:
053: import java.io.IOException;
054: import java.io.InputStream;
055: import java.io.Reader;
056: import java.util.HashMap;
057: import java.util.Map;
058:
059: import org.apache.batik.util.EncodingUtilities;
060:
061: /**
062: * This class represents a NormalizingReader which handles streams of
063: * bytes.
064: *
065: * @author <a href="mailto:stephane@hillion.org">Stephane Hillion</a>
066: * @version $Id$
067: */
068: public class StreamNormalizingReader extends NormalizingReader {
069:
070: /**
071: * The char decoder.
072: */
073: protected CharDecoder charDecoder;
074:
075: /**
076: * The next char.
077: */
078: protected int nextChar = -1;
079:
080: /**
081: * The current line in the stream.
082: */
083: protected int line = 1;
084:
085: /**
086: * The current column in the stream.
087: */
088: protected int column;
089:
090: /**
091: * Creates a new NormalizingReader. The encoding is assumed to be
092: * ISO-8859-1.
093: * @param is The input stream to decode.
094: */
095: public StreamNormalizingReader(InputStream is) throws IOException {
096: this (is, null);
097: }
098:
099: /**
100: * Creates a new NormalizingReader.
101: * @param is The input stream to decode.
102: * @param enc The standard encoding name. A null encoding means
103: * ISO-8859-1.
104: */
105: public StreamNormalizingReader(InputStream is, String enc)
106: throws IOException {
107: if (enc == null) {
108: enc = "ISO-8859-1";
109: }
110: charDecoder = createCharDecoder(is, enc);
111: }
112:
113: /**
114: * Creates a new NormalizingReader.
115: * @param r The reader to wrap.
116: */
117: public StreamNormalizingReader(Reader r) throws IOException {
118: charDecoder = new GenericDecoder(r);
119: }
120:
121: /**
122: * This constructor is intended for use by subclasses.
123: */
124: protected StreamNormalizingReader() {
125: }
126:
127: /**
128: * Read a single character. This method will block until a
129: * character is available, an I/O error occurs, or the end of the
130: * stream is reached.
131: */
132: public int read() throws IOException {
133: int result = nextChar;
134: if (result != -1) {
135: nextChar = -1;
136: if (result == 13) {
137: column = 0;
138: line++;
139: } else {
140: column++;
141: }
142: return result;
143: }
144: result = charDecoder.readChar();
145: switch (result) {
146: case 13:
147: column = 0;
148: line++;
149: int c = charDecoder.readChar();
150: if (c == 10) {
151: return 10;
152: }
153: nextChar = c;
154: return 10;
155:
156: case 10:
157: column = 0;
158: line++;
159: }
160: return result;
161: }
162:
163: /**
164: * Returns the current line in the stream.
165: */
166: public int getLine() {
167: return line;
168: }
169:
170: /**
171: * Returns the current column in the stream.
172: */
173: public int getColumn() {
174: return column;
175: }
176:
177: /**
178: * Close the stream.
179: */
180: public void close() throws IOException {
181: charDecoder.dispose();
182: charDecoder = null;
183: }
184:
185: /**
186: * Creates the CharDecoder mapped with the given encoding name.
187: */
188: protected CharDecoder createCharDecoder(InputStream is, String enc)
189: throws IOException {
190: CharDecoderFactory cdf = (CharDecoderFactory) charDecoderFactories
191: .get(enc.toUpperCase());
192: if (cdf != null) {
193: return cdf.createCharDecoder(is);
194: }
195: String e = EncodingUtilities.javaEncoding(enc);
196: if (e == null) {
197: e = enc;
198: }
199: return new GenericDecoder(is, e);
200: }
201:
202: /**
203: * The CharDecoder factories map.
204: */
205: protected final static Map charDecoderFactories = new HashMap(11);
206: static {
207: CharDecoderFactory cdf = new ASCIIDecoderFactory();
208: charDecoderFactories.put("ASCII", cdf);
209: charDecoderFactories.put("US-ASCII", cdf);
210: charDecoderFactories.put("ISO-8859-1",
211: new ISO_8859_1DecoderFactory());
212: charDecoderFactories.put("UTF-8", new UTF8DecoderFactory());
213: charDecoderFactories.put("UTF-16", new UTF16DecoderFactory());
214: }
215:
216: /**
217: * Represents a CharDecoder factory.
218: */
219: protected interface CharDecoderFactory {
220: CharDecoder createCharDecoder(InputStream is)
221: throws IOException;
222: }
223:
224: /**
225: * To create an ASCIIDecoder.
226: */
227: protected static class ASCIIDecoderFactory implements
228: CharDecoderFactory {
229: public CharDecoder createCharDecoder(InputStream is)
230: throws IOException {
231: return new ASCIIDecoder(is);
232: }
233: }
234:
235: /**
236: * To create an ISO_8859_1Decoder.
237: */
238: protected static class ISO_8859_1DecoderFactory implements
239: CharDecoderFactory {
240: public CharDecoder createCharDecoder(InputStream is)
241: throws IOException {
242: return new ISO_8859_1Decoder(is);
243: }
244: }
245:
246: /**
247: * To create a UTF8Decoder.
248: */
249: protected static class UTF8DecoderFactory implements
250: CharDecoderFactory {
251: public CharDecoder createCharDecoder(InputStream is)
252: throws IOException {
253: return new UTF8Decoder(is);
254: }
255: }
256:
257: /**
258: * To create a UTF16Decoder.
259: */
260: protected static class UTF16DecoderFactory implements
261: CharDecoderFactory {
262: public CharDecoder createCharDecoder(InputStream is)
263: throws IOException {
264: return new UTF16Decoder(is);
265: }
266: }
267: }
|