public class ProcessStream extends Stream
STDIO
pipes of a child process. This class can be used for
either the input pipe (STDIN
) or for both output pipes
(STDOUT and STDERR
) combined.
Due to the (Progress-driven) requirement that a single read return
any available data from both the standard output pipes, both pipes are
checked and read in series. The STDOUT
pipe is always
checked before STDERR
. This artificially makes the two
pipes appear as a single stream, however the approach is inherently
limited. If an entire line needs to be read it is critical that the
readLn()
is used, since this will be guaranteed to read the whole
line from a single stream. The readCh()
will always read from
STDOUT
as long as there are bytes available. However this
means that there is a natural race condition with STDERR
.
If at one moment STDOUT
has no bytes available for reading,
then a read will occur from STDERR
. If bytes arrive on
STDOUT
then the very next call to readCh
will
first read from STDOUT
even if there are bytes that arrived
previously on STDERR
. This may make the output appear in
a different order than expected.
A polling approach is used for all reading to implement the semantic of combining the two pipes.
This class does not support getting/setting the length or read/write position of this stream.
Modifier and Type | Class and Description |
---|---|
private class |
ProcessStream.InReader
Provides low level reader input support.
|
private class |
ProcessStream.InStream
Provides low level stream input support.
|
private static interface |
ProcessStream.IOHelper
Provides a simple, common interface to hide the differences between
streams and readers.
|
private class |
ProcessStream.OutStream
Provides low level stream output support.
|
private class |
ProcessStream.OutWriter
Provides low level writer output support.
|
private class |
ProcessStream.Waiter
Provides a simple mechanism to wait for the exit of a process on an
asynchronous basis (on a new thread dedicated to this wait).
|
Stream.PrintMode
Modifier and Type | Field and Description |
---|---|
private boolean |
broken
Determines whether an output error has occurred.
|
private ProcessStream.Waiter |
child
The child process babysitter.
|
private java.lang.String |
cset
Determines if there is any explicit charset to honor.
|
private ProcessStream.IOHelper |
err
The
STDERR from the child process. |
private ProcessStream.IOHelper |
in
The
STDIN from the child process. |
private ProcessStream.IOHelper |
out
The
STDOUT from the child process. |
private java.io.IOException |
storedException
Exception that was raised when the stream become broken.
|
private static java.lang.String |
UNSUPPORTED
Standard message for unsupported operations.
|
binary, convert, CR, DELIM, doneIn, doneOut, EOF, increment, LF, MODE_EXPORT, MODE_PUT_CONTROL, MODE_PUT_NORMAL, MODE_PUT_UNFORMATTED, NEWLINE, NEWLINE_LEN, PAGED_DEFAULT, PIPE_BROKEN_MESSAGE, SET_PAGED_DEFAULT, sourceCp, targetCp
Constructor and Description |
---|
ProcessStream()
Default constructor which creates an instance that implements the
standard character conversion.
|
Modifier and Type | Method and Description |
---|---|
void |
assign(Stream stream)
Assigns the internal stream reference to the given reference.
|
long |
available()
The number of bytes available to be immediately read without blocking.
|
void |
close()
Closes the stream and releases OS resources associated with it.
|
void |
closeIn()
Closes the input stream and releases OS resources associated with it.
|
void |
closeOut()
Closes the output stream and releases OS resources associated with it.
|
void |
connectIn(int pid,
java.io.OutputStream in)
Connects the
STDIN of the child process to this stream. |
void |
connectOut(int pid,
java.io.InputStream out,
java.io.InputStream err)
Connects the
STDOUT and STDERR of the child process to
this stream. |
long |
getLen()
The length of the stream in bytes.
|
long |
getPos()
The 0-based offset into the stream at which the next read or write will
occur.
|
boolean |
isIn()
State of the input side of the stream.
|
boolean |
isOut()
State of the output side of the stream.
|
private void |
makeBroken(java.io.IOException exc)
Mark the stream as broken and notify BufferSizeManager about it.
|
int |
peekCh()
Peeks at the character from the current read position in the stream (reads a character from
the current read position in the stream without incrementing stream read position.
|
private void |
raiseExceptionOnFlushIfNecessary()
Check whether we have exceeded the buffer size limit for the flush operations
and, if it is true, re-throw the exception that was raised when the stream
become broken.
|
private void |
raiseStopOnCloseIfNecessary()
Check whether we have exceeded the buffer size limit for the close operations
and, if it is true, display the error message and raise the STOP condition.
|
int |
readCh()
Read the raw integer value of a character from the current read
position in the stream.
|
java.lang.String |
readLn()
Read all characters from the current read position in the stream to the
next line separator (as determined by the
File.separator
or to the EOF . |
void |
setBroken()
Mark stream as broken and it will silently ignore I/O errors.
|
void |
setLen(long len)
Truncates or extends the stream to the specified length if this stream
supports such an operation.
|
void |
setPos(long pos)
Moves the current read/write position to the specified absolute 0-based
offset.
|
private void |
startWaiter(int pid)
Starts the child process monitor.
|
void |
write(byte[] data)
Write the given byte array to the output stream.
|
void |
write(byte[] data,
int off,
int len)
Write the specified range of bytes from the given byte array to the output stream.
|
void |
write(java.lang.String data)
Write the given string to the output stream.
|
void |
writeByte(byte b)
Write the given byte to the output stream.
|
void |
writeCh(char ch)
Write the given character to the output stream.
|
advancePage, afterWrite, assignDatum, cleanup, deleted, deregisterFooter, deregisterHeader, endOutput, endOutput, export, finished, flush, flushControlled, flushData, forcePageBreak, forcePageBreak, generateStringFormat, getAvailableLines, getControl, getConvert, getDelimiter, getDisplayMode, getEcho, getEffectivePageSize, getLength, getName, getNextLineNum, getPageNum, getPageSize, getPendingRowCount, getPosition, getPulseOnClose, getUnformatted, hasPageHeadersFooters, indexOfNewLine, isContiguous, isFreshPage, isSilent, isSuppressFormFeed, isTerm, isUnbuffered, isUnnamed, isValid, iterate, needsHeadersOutput, needsPageBreak, needsPageBreak, processFooters, processHeaders, processHeadersInt, processHeadersUncond, protectReads, protectWrites, pulseOutput, put, putControl, putField, putField, putField, putField, putField, putField, putField, putField, putField, putField, putField, putField, putField, putField, putField, putField, putField, putField, putField, putField, putField, putField, putField, putField, putField, putField, putField, putField, putField, putField, putLineEnd, putLineEnd, putNull, putNull, putSpace, putSpace, putUnformatted, putWorker, rawGetNextLineNum, rawGetPageNum, rawGetPageSize, rawIncrementNextLineNum, rawIncrementPageNum, rawNextLineNum, rawPageSize, rawResetNextLineNum, rawSetPageSize, readBlock, readChar, readChar, readChunk, readField, readField, readField, readField, readFieldWorker, readLine, readLineCleanup, registerAdvanceListener, registerCloseListener, registerFlushListener, registerFooter, registerHeader, registerPageBreakListener, resetCurrentLine, retry, setAppend, setBinary, setContiguous, setControl, setConvert, setConvertSource, setConvertSource, setConvertTarget, setConvertTarget, setDelimiter, setDelimiter, setEcho, setFont, setFont, setLandscape, setName, setPageSize, setPageSize, setPageSize, setPendingRowCount, setPortrait, setPosition, setPosition, setPulseOnClose, setUnbuffered, setUnformatted, setUnnamed, skipField, skipLoneHyphenInput, startOutput, writeBlock, writeControlled, writeControlledSpecial, writeField, writeField, writeField, writeField, writeField
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
initFailure
private static final java.lang.String UNSUPPORTED
private java.lang.String cset
private ProcessStream.IOHelper out
STDOUT
from the child process.private ProcessStream.IOHelper err
STDERR
from the child process.private ProcessStream.IOHelper in
STDIN
from the child process.private ProcessStream.Waiter child
private boolean broken
private java.io.IOException storedException
public ProcessStream()
public void connectIn(int pid, java.io.OutputStream in)
STDIN
of the child process to this stream.pid
- The ID of the child process that is reading our input.in
- The child process' STDIN
stream.public void connectOut(int pid, java.io.InputStream out, java.io.InputStream err)
STDOUT and STDERR
of the child process to
this stream.pid
- The ID of the child process that is generating output.out
- The child process' STDOUT
stream.err
- The child process' STDERR
stream.public void setBroken()
public long available() throws java.io.IOException
public long getPos() throws java.lang.UnsupportedOperationException, java.io.IOException
public void setPos(long pos) throws java.lang.UnsupportedOperationException, java.io.IOException
public long getLen() throws java.lang.UnsupportedOperationException, java.io.IOException
public void setLen(long len) throws java.lang.UnsupportedOperationException, java.io.IOException
public void writeCh(char ch) throws java.io.IOException
public void writeByte(byte b) throws java.io.IOException
public void write(java.lang.String data) throws java.io.IOException
public void write(byte[] data) throws java.io.IOException
public void write(byte[] data, int off, int len) throws java.io.IOException
write
in class Stream
data
- The data to be written.off
- Starting offset in data from which to read bytes to be written. Must be
non-negative and < data.length
.len
- Length of data to be written. Must be non-negative and <= (data.length
- offset)
.java.io.IOException
- If an I/O error occurs.public int peekCh()
peekCh()
and readCh()
will return the same value).
The underlying stream subclass determines the content of the result. Byte oriented streams such as pipes or files will return a byte while streams that generate keystrokes or characters may return a DBCS or Unicode character.
peekCh
in class Stream
EOF
.StopConditionException
- If any interruption occurs during I/O processing.public int readCh() throws StopConditionException
At this time, only a single byte will be read no matter what encoding is used by the underlying stream. This means that DBCS or Unicode encodings will not be properly handled.
readCh
in class Stream
EOF
.StopConditionException
- If any interruption occurs during I/O processing.public java.lang.String readLn() throws java.io.EOFException, java.io.IOException, java.lang.InterruptedException
File.separator
or to the EOF
. Any line separator character(s) and the
EOF
character are not returned.public void closeIn()
public void closeOut()
public void close()
public boolean isIn()
public boolean isOut()
public void assign(Stream stream) throws java.lang.UnsupportedOperationException
private void startWaiter(int pid)
pid
- The ID of the child process that is generating output.private void raiseExceptionOnFlushIfNecessary() throws java.io.IOException
java.io.IOException
- if we have exceeded the buffer size limit for the flush operations.private void raiseStopOnCloseIfNecessary() throws StopConditionException
StopConditionException
- if we have exceeded the buffer size limit for the close operations.private void makeBroken(java.io.IOException exc)
exc
- Exception because of which the stream became broken.