001: /*
002: * Copyright 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:
018: //package org.apache.tools.ant.util;
019: package org.mmbase.util;
020:
021: import java.io.*;
022:
023: /**
024: * Oddly enough, Java does not provide this itself. Stolen from Ant code.
025: *
026: * Adapts a <code>Reader</code> as an <code>InputStream</code>.
027: * Adapted from <CODE>StringInputStream</CODE>.
028: *
029: * @since MMBase-1.8.2
030: * @version $Id: ReaderInputStream.java,v 1.2 2007/02/24 21:57:50 nklasens Exp $
031: */
032:
033: public class ReaderInputStream extends InputStream {
034:
035: /** Source Reader */
036: private Reader in;
037:
038: private String encoding = System.getProperty("file.encoding");
039:
040: private byte[] slack;
041:
042: private int begin;
043:
044: /**
045: * Construct a <CODE>ReaderInputStream</CODE>
046: * for the specified <CODE>Reader</CODE>.
047: *
048: * @param reader <CODE>Reader</CODE>. Must not be <code>null</code>.
049: */
050: public ReaderInputStream(Reader reader) {
051: in = reader;
052: }
053:
054: /**
055: * Construct a <CODE>ReaderInputStream</CODE>
056: * for the specified <CODE>Reader</CODE>,
057: * with the specified encoding.
058: *
059: * @param reader non-null <CODE>Reader</CODE>.
060: * @param encoding non-null <CODE>String</CODE> encoding.
061: */
062: public ReaderInputStream(Reader reader, String encoding) {
063: this (reader);
064: if (encoding == null) {
065: throw new IllegalArgumentException(
066: "encoding must not be null");
067: } else {
068: this .encoding = encoding;
069: }
070: }
071:
072: /**
073: * Reads from the <CODE>Reader</CODE>, returning the same value.
074: *
075: * @return the value of the next character in the <CODE>Reader</CODE>.
076: *
077: * @exception IOException if the original <code>Reader</code> fails to be read
078: */
079: public synchronized int read() throws IOException {
080: if (in == null) {
081: throw new IOException("Stream Closed");
082: }
083:
084: byte result;
085: if (slack != null && begin < slack.length) {
086: result = slack[begin];
087: if (++begin == slack.length) {
088: slack = null;
089: }
090: } else {
091: byte[] buf = new byte[1];
092: if (read(buf, 0, 1) <= 0) {
093: result = -1;
094: } else {
095: result = buf[0];
096: }
097: }
098:
099: if (result < -1) {
100: result += 256;
101: }
102:
103: return result;
104: }
105:
106: /**
107: * Reads from the <code>Reader</code> into a byte array
108: *
109: * @param b the byte array to read into
110: * @param off the offset in the byte array
111: * @param len the length in the byte array to fill
112: * @return the actual number read into the byte array, -1 at
113: * the end of the stream
114: * @exception IOException if an error occurs
115: */
116: public synchronized int read(byte[] b, int off, int len)
117: throws IOException {
118: if (in == null) {
119: throw new IOException("Stream Closed");
120: }
121:
122: while (slack == null) {
123: char[] buf = new char[len]; // might read too much
124: int n = in.read(buf);
125: if (n == -1) {
126: return -1;
127: }
128: if (n > 0) {
129: slack = new String(buf, 0, n).getBytes(encoding);
130: begin = 0;
131: }
132: }
133:
134: if (len > slack.length - begin) {
135: len = slack.length - begin;
136: }
137:
138: System.arraycopy(slack, begin, b, off, len);
139:
140: if ((begin += len) >= slack.length) {
141: slack = null;
142: }
143:
144: return len;
145: }
146:
147: /**
148: * Marks the read limit of the StringReader.
149: *
150: * @param limit the maximum limit of bytes that can be read before the
151: * mark position becomes invalid
152: */
153: public synchronized void mark(final int limit) {
154: try {
155: in.mark(limit);
156: } catch (IOException ioe) {
157: throw new RuntimeException(ioe.getMessage());
158: }
159: }
160:
161: /**
162: * @return the current number of bytes ready for reading
163: * @exception IOException if an error occurs
164: */
165: public synchronized int available() throws IOException {
166: if (in == null) {
167: throw new IOException("Stream Closed");
168: }
169: if (slack != null) {
170: return slack.length - begin;
171: }
172: if (in.ready()) {
173: return 1;
174: } else {
175: return 0;
176: }
177: }
178:
179: /**
180: * @return false - mark is not supported
181: */
182: public boolean markSupported() {
183: return false; // would be imprecise
184: }
185:
186: /**
187: * Resets the StringReader.
188: *
189: * @exception IOException if the StringReader fails to be reset
190: */
191: public synchronized void reset() throws IOException {
192: if (in == null) {
193: throw new IOException("Stream Closed");
194: }
195: slack = null;
196: in.reset();
197: }
198:
199: /**
200: * Closes the Stringreader.
201: *
202: * @exception IOException if the original StringReader fails to be closed
203: */
204: public synchronized void close() throws IOException {
205: in.close();
206: slack = null;
207: in = null;
208: }
209:
210: public static void main(String[] args) throws IOException {
211: ReaderInputStream is = new ReaderInputStream(new StringReader(
212: args[0]), "UTF-8");
213: while (true) {
214: int b = is.read();
215: if (b <= 0)
216: break;
217: System.out.println("" + b);
218: }
219: }
220: }
|