001: // copied as permitted by license
002: /*
003: * Copyright 2004 The Apache Software Foundation.
004: *
005: * Licensed under the Apache License, Version 2.0 (the "License");
006: * you may not use this file except in compliance with the License.
007: * You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018: package org.cougaar.util;
019:
020: //package org.apache.tools.ant.util;
021:
022: import java.io.IOException;
023: import java.io.InputStream;
024: import java.io.Reader;
025: import org.cougaar.bootstrap.SystemProperties;
026:
027: /**
028: * Adapts a <code>Reader</code> as an <code>InputStream</code>.
029: * Adapted from <CODE>StringInputStream</CODE>.
030: * @author Apache Software Foundation
031: */
032: public class ReaderInputStream extends InputStream {
033:
034: /** Source Reader */
035: private Reader in;
036:
037: private String encoding = SystemProperties
038: .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: }
095: result = buf[0];
096: }
097:
098: if (result < -1) {
099: result += 256;
100: }
101:
102: return result;
103: }
104:
105: /**
106: * Reads from the <code>Reader</code> into a byte array
107: *
108: * @param b the byte array to read into
109: * @param off the offset in the byte array
110: * @param len the length in the byte array to fill
111: * @return the actual number read into the byte array, -1 at
112: * the end of the stream
113: * @exception IOException if an error occurs
114: */
115: public synchronized int read(byte[] b, int off, int len)
116: throws IOException {
117: if (in == null) {
118: throw new IOException("Stream Closed");
119: }
120:
121: while (slack == null) {
122: char[] buf = new char[len]; // might read too much
123: int n = in.read(buf);
124: if (n == -1) {
125: return -1;
126: }
127: if (n > 0) {
128: slack = new String(buf, 0, n).getBytes(encoding);
129: begin = 0;
130: }
131: }
132:
133: if (len > slack.length - begin) {
134: len = slack.length - begin;
135: }
136:
137: System.arraycopy(slack, begin, b, off, len);
138:
139: if ((begin += len) >= slack.length) {
140: slack = null;
141: }
142:
143: return len;
144: }
145:
146: /**
147: * Marks the read limit of the StringReader.
148: *
149: * @param limit the maximum limit of bytes that can be read before the
150: * mark position becomes invalid
151: */
152: public synchronized void mark(final int limit) {
153: try {
154: in.mark(limit);
155: } catch (IOException ioe) {
156: throw new RuntimeException(ioe.getMessage());
157: }
158: }
159:
160: /**
161: * @return the current number of bytes ready for reading
162: * @exception IOException if an error occurs
163: */
164: public synchronized int available() throws IOException {
165: if (in == null) {
166: throw new IOException("Stream Closed");
167: }
168: if (slack != null) {
169: return slack.length - begin;
170: }
171: if (in.ready()) {
172: return 1;
173: } else {
174: return 0;
175: }
176: }
177:
178: /**
179: * @return false - mark is not supported
180: */
181: public boolean markSupported() {
182: return false; // would be imprecise
183: }
184:
185: /**
186: * Resets the StringReader.
187: *
188: * @exception IOException if the StringReader fails to be reset
189: */
190: public synchronized void reset() throws IOException {
191: if (in == null) {
192: throw new IOException("Stream Closed");
193: }
194: slack = null;
195: in.reset();
196: }
197:
198: /**
199: * Closes the Stringreader.
200: *
201: * @exception IOException if the original StringReader fails to be closed
202: */
203: public synchronized void close() throws IOException {
204: in.close();
205: slack = null;
206: in = null;
207: }
208: }
|