in sshd-scp/src/main/java/org/apache/sshd/scp/server/InputStreamReader.java [223:296]
public int read(char[] buf, int offset, int length) throws IOException {
synchronized (lock) {
if (!isOpen()) {
throw new IOException("InputStreamReader is closed.");
}
if (offset < 0 || offset > buf.length - length || length < 0) {
throw new IndexOutOfBoundsException();
}
if (length == 0) {
return 0;
}
CharBuffer out = CharBuffer.wrap(buf, offset, length);
CoderResult result = CoderResult.UNDERFLOW;
// bytes.remaining() indicates number of bytes in buffer
// when 1-st time entered, it'll be equal to zero
boolean needInput = !bytes.hasRemaining();
while (out.position() == offset) {
// fill the buffer if needed
if (needInput) {
try {
if ((in.available() == 0)
&& (out.position() > offset)) {
// we could return the result without blocking read
break;
}
} catch (IOException e) {
// available didn't work so just try the read
}
int off = bytes.arrayOffset() + bytes.limit();
int was_red = in.read(bytes.array(), off, 1);
if (was_red == -1) {
endOfInput = true;
break;
} else if (was_red == 0) {
break;
}
bytes.limit(bytes.limit() + was_red);
}
// decode bytes
result = decoder.decode(bytes, out, false);
if (result.isUnderflow()) {
// compact the buffer if no space left
if (bytes.limit() == bytes.capacity()) {
bytes.compact();
bytes.limit(bytes.position());
bytes.position(0);
}
needInput = true;
} else {
break;
}
}
if (result == CoderResult.UNDERFLOW && endOfInput) {
result = decoder.decode(bytes, out, true);
decoder.flush(out);
decoder.reset();
}
if (result.isMalformed()) {
throw new MalformedInputException(result.length());
} else if (result.isUnmappable()) {
throw new UnmappableCharacterException(result.length());
}
return out.position() - offset == 0 ? -1 : out.position() - offset;
}
}