001: /*BEGIN_COPYRIGHT_BLOCK
002: *
003: * Copyright (c) 2001-2007, JavaPLT group at Rice University (javaplt@rice.edu)
004: * All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions are met:
008: * * Redistributions of source code must retain the above copyright
009: * notice, this list of conditions and the following disclaimer.
010: * * Redistributions in binary form must reproduce the above copyright
011: * notice, this list of conditions and the following disclaimer in the
012: * documentation and/or other materials provided with the distribution.
013: * * Neither the names of DrJava, the JavaPLT group, Rice University, nor the
014: * names of its contributors may be used to endorse or promote products
015: * derived from this software without specific prior written permission.
016: *
017: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
018: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
019: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
020: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
021: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
022: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
023: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
024: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
025: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
026: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
027: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
028: *
029: * This software is Open Source Initiative approved Open Source Software.
030: * Open Source Initative Approved is a trademark of the Open Source Initiative.
031: *
032: * This file is part of DrJava. Download the current version of this project
033: * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
034: *
035: * END_COPYRIGHT_BLOCK*/
036:
037: package edu.rice.cs.util;
038:
039: import java.io.*;
040: import java.util.ArrayList;
041:
042: /** Redirects requests for input through the abstract method _getInput().
043: * @version $Id: InputStreamRedirector.java 4255 2007-08-28 19:17:37Z mgricken $
044: */
045: public abstract class InputStreamRedirector extends InputStream {
046: /** Buffer that stores the current set of bytes.
047: * TODO: perhaps this should use an array for efficiency
048: * This is only used as a char queue.
049: */
050: protected ArrayList<Character> _buffer;
051:
052: /** Constructs a new InputStreamRedirector. */
053: public InputStreamRedirector() {
054: _buffer = new ArrayList<Character>(60);
055: }
056:
057: /** This method gets called whenever input is requested from the stream and
058: * nothing is currently available. Subclasses should return the appropriate
059: * input to feed to the input stream. When using a readLine() method, be sure
060: * to append a newline to the end of the input.
061: * @return the input to the stream, not the empty string
062: */
063: protected abstract String _getInput() throws IOException;
064:
065: /** Reads a single "line" of input into the buffer, i.e. makes a single call
066: * to _getInput() and puts the result into the buffer.
067: * @throws IOException if _getInput() returns the empty string
068: */
069: private void _readInputIntoBuffer() throws IOException {
070: String input = _getInput();
071: if (input.equals(""))
072: throw new IOException(
073: "_getInput() must return non-empty input!");
074:
075: for (int i = 0; i < input.length(); i++) {
076: _buffer.add(new Character(input.charAt(i)));
077: }
078: }
079:
080: /** Tries to fill b with bytes from the user, prompting for input only if the stream is already empty.
081: * @param b the byte array to fill
082: * @return the number of bytes successfully read
083: */
084: public synchronized int read(byte[] b) throws IOException {
085: return read(b, 0, b.length);
086: }
087:
088: /** Tries to fill b with bytes from the user, prompting for input only if the stream is already empty.
089: * @param b the byte array to fill
090: * @param off the offset in the byte array
091: * @param len the number of characters to try to read
092: * @return the number of bytes successfully read
093: */
094: public synchronized int read(byte[] b, int off, int len)
095: throws IOException {
096: int numRead = 0;
097: if (available() == 0)
098: _readInputIntoBuffer();
099:
100: for (int i = off; i < off + len; i++) {
101: if (available() == 0)
102: break;
103: else {
104: b[i] = (byte) _buffer.remove(0).charValue();
105: numRead++;
106: }
107: }
108: return numRead;
109: }
110:
111: /** Overrides the read() in PipedInputStream so that if the stream is empty, it asks for more input from _getInput().
112: * @return the next character in the stream
113: * @throws IOException if an I/O exception
114: */
115: public synchronized int read() throws IOException {
116: if (available() == 0)
117: _readInputIntoBuffer();
118: return _buffer.remove(0).charValue();
119: }
120:
121: /** @return the number of characters available in this stream. */
122: public int available() {
123: return _buffer.size();
124: }
125: }
|