package aQute.remote.agent;
import java.io.IOException;
import java.io.InputStream;
/**
* An filter stream that takes a string from the supervisor and then provides it
* as a read to the user of this Input Stream. It also dispatches the text to an
* original stream.It does not use Piped*Stream because they turned hard to
* break. This implementation uses a ring buffer.
*/
public class RedirectInput extends InputStream {
private InputStream org;
private byte[] ring = new byte[65536];
private int in, out;
/**
* Create a redirector input stream with an original input stream
*
* @param in the original
*/
public RedirectInput(InputStream in) throws IOException {
this.org = in;
}
/**
* Create a redirector without an original
*/
public RedirectInput() {}
/**
* Get the original inputstream, potentially null
*
* @return null or the original input stream
*/
public InputStream getOrg() {
return org;
}
/**
* Provide the string that should be treated as input for the running code.
*
* @param s the string
*/
public synchronized void add(String s) throws IOException {
byte[] bytes = s.getBytes();
for (int i = 0; i < bytes.length; i++) {
write(bytes[i]);
}
}
/**
* Write to the ring buffer
*/
private void write(byte b) {
synchronized (ring) {
ring[in] = b;
in = (in + 1) % ring.length;
if (in == out) {
// skip oldest output
out = (out + 1) % ring.length;
}
ring.notifyAll();
}
}
public void close() {
// ignore
}
/**
* Read a byte from the input buffer. We will be fully interruptible, in the
* case of an interrupt we return -1 (eof)
*/
@Override
public int read() throws IOException {
System.out.flush();
synchronized (ring) {
while (in == out) {
try {
ring.wait(400);
} catch (InterruptedException e) {
return -1;
}
}
int c = 0xFF & ring[out];
out = (out + 1) % ring.length;
return c;
}
}
/**
* And the read for a larger buffer
*/
@Override
public int read(byte[] buffer, int offset, int length) throws IOException {
int n = 0;
for (int i = offset; i < length; i++) {
int c = read();
if (c < 0)
break;
buffer[i] = (byte) (0xFF & c);
n++;
if (c == '\n')
break;
}
return n;
}
@Override
public int read(byte[] buffer) throws IOException {
return read(buffer, 0, buffer.length);
}
}