Package com.martiansoftware.nailgun
Class NGInputStream
- java.lang.Object
-
- java.io.InputStream
-
- java.io.FilterInputStream
-
- com.martiansoftware.nailgun.NGInputStream
-
- All Implemented Interfaces:
java.io.Closeable
,java.lang.AutoCloseable
public class NGInputStream extends java.io.FilterInputStream implements java.io.Closeable
A FilterInputStream that is able to read the chunked stdin stream from a NailGun client.
-
-
Field Summary
Fields Modifier and Type Field Description private boolean
clientConnected
private java.util.Set<NGClientListener>
clientListeners
private java.io.DataInputStream
din
private boolean
eof
private java.util.Set<NGHeartbeatListener>
heartbeatListeners
private static java.util.logging.Logger
LOG
private byte[]
oneByteBuffer
private java.util.concurrent.ExecutorService
orchestratorExecutor
private java.io.DataOutputStream
out
private java.util.concurrent.ExecutorService
readExecutor
private int
remaining
private boolean
started
private java.io.InputStream
stdin
private static long
TERMINATION_TIMEOUT_MS
-
Constructor Summary
Constructors Constructor Description NGInputStream(java.io.DataInputStream in, java.io.DataOutputStream out, int heartbeatTimeoutMillis)
Creates a new NGInputStream wrapping the specified InputStream.
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description void
addClientListener(NGClientListener listener)
Registers a new NGClientListener to be called on client disconnection or calls the listeners clientDisconnected method if the client has already disconnected to avoid races.void
addHeartbeatListener(NGHeartbeatListener listener)
int
available()
void
close()
Cancel the thread reading from the NailGun client and close underlying input streamboolean
isClientConnected()
boolean
markSupported()
private void
notifyClientListeners()
Calls clientDisconnected method on all registered NGClientListeners.int
read()
int
read(byte[] b)
int
read(byte[] b, int offset, int length)
private void
readChunk()
Reads a NailGun chunk header from the underlying InputStream.private java.io.InputStream
readPayload(java.io.InputStream in, int len)
Reads a NailGun chunk payload fromFilterInputStream.in
and returns an InputStream that reads from that chunk.void
removeAllClientListeners()
Do not notify anymore about client disconnectsvoid
removeClientListener(NGClientListener listener)
void
removeHeartbeatListener(NGHeartbeatListener listener)
private void
sendSendInput()
private void
setClientDisconnected()
Notify threads waiting in read() on either EOF chunk read or client disconnection.private void
setEof()
Notify threads waiting in read() on either EOF chunk read or client disconnection.private static void
terminateExecutor(java.util.concurrent.ExecutorService service, java.lang.String which)
-
-
-
Field Detail
-
LOG
private static final java.util.logging.Logger LOG
-
orchestratorExecutor
private final java.util.concurrent.ExecutorService orchestratorExecutor
-
readExecutor
private final java.util.concurrent.ExecutorService readExecutor
-
din
private final java.io.DataInputStream din
-
stdin
private java.io.InputStream stdin
-
eof
private boolean eof
-
clientConnected
private boolean clientConnected
-
remaining
private int remaining
-
oneByteBuffer
private byte[] oneByteBuffer
-
out
private final java.io.DataOutputStream out
-
started
private boolean started
-
clientListeners
private final java.util.Set<NGClientListener> clientListeners
-
heartbeatListeners
private final java.util.Set<NGHeartbeatListener> heartbeatListeners
-
TERMINATION_TIMEOUT_MS
private static final long TERMINATION_TIMEOUT_MS
- See Also:
- Constant Field Values
-
-
Constructor Detail
-
NGInputStream
public NGInputStream(java.io.DataInputStream in, java.io.DataOutputStream out, int heartbeatTimeoutMillis)
Creates a new NGInputStream wrapping the specified InputStream. Also sets up a timer to periodically consume heartbeats sent from the client and call registered NGClientListeners if a client disconnection is detected.- Parameters:
in
- the InputStream to wrapout
- the OutputStream to which SENDINPUT chunks should be sentheartbeatTimeoutMillis
- the interval between heartbeats before considering the client disconnected
-
-
Method Detail
-
notifyClientListeners
private void notifyClientListeners()
Calls clientDisconnected method on all registered NGClientListeners.
-
close
public void close() throws java.io.IOException
Cancel the thread reading from the NailGun client and close underlying input stream- Specified by:
close
in interfacejava.lang.AutoCloseable
- Specified by:
close
in interfacejava.io.Closeable
- Overrides:
close
in classjava.io.FilterInputStream
- Throws:
java.io.IOException
-
terminateExecutor
private static void terminateExecutor(java.util.concurrent.ExecutorService service, java.lang.String which)
-
readPayload
private java.io.InputStream readPayload(java.io.InputStream in, int len) throws java.io.IOException
Reads a NailGun chunk payload fromFilterInputStream.in
and returns an InputStream that reads from that chunk.- Parameters:
in
- the InputStream to read the chunk payload from.len
- the size of the payload chunk read from the chunkHeader.- Returns:
- an InputStream containing the read data.
- Throws:
java.io.IOException
- if thrown by the underlying InputStreamjava.io.EOFException
- if EOF is reached by underlying stream before the payload has been read.
-
readChunk
private void readChunk() throws java.io.IOException
Reads a NailGun chunk header from the underlying InputStream.- Throws:
java.io.EOFException
- if underlying stream / socket is closed which happens on client disconnectionjava.io.IOException
- if thrown by the underlying InputStream, or if an unexpected NailGun chunk type is encountered.
-
setEof
private void setEof()
Notify threads waiting in read() on either EOF chunk read or client disconnection.
-
setClientDisconnected
private void setClientDisconnected()
Notify threads waiting in read() on either EOF chunk read or client disconnection.
-
available
public int available() throws java.io.IOException
- Overrides:
available
in classjava.io.FilterInputStream
- Throws:
java.io.IOException
- See Also:
InputStream.available()
-
markSupported
public boolean markSupported()
- Overrides:
markSupported
in classjava.io.FilterInputStream
- See Also:
InputStream.markSupported()
-
read
public int read() throws java.io.IOException
- Overrides:
read
in classjava.io.FilterInputStream
- Throws:
java.io.IOException
- See Also:
InputStream.read()
-
read
public int read(byte[] b) throws java.io.IOException
- Overrides:
read
in classjava.io.FilterInputStream
- Throws:
java.io.IOException
- See Also:
InputStream.read(byte[])
-
read
public int read(byte[] b, int offset, int length) throws java.io.IOException
- Overrides:
read
in classjava.io.FilterInputStream
- Throws:
java.io.IOException
- See Also:
InputStream.read(byte[], int, int)
-
sendSendInput
private void sendSendInput() throws java.io.IOException
- Throws:
java.io.IOException
-
isClientConnected
public boolean isClientConnected()
- Returns:
- true if interval since last read is less than heartbeat timeout interval.
-
addClientListener
public void addClientListener(NGClientListener listener)
Registers a new NGClientListener to be called on client disconnection or calls the listeners clientDisconnected method if the client has already disconnected to avoid races.- Parameters:
listener
- theNGClientListener
to be notified of client events.
-
removeClientListener
public void removeClientListener(NGClientListener listener)
- Parameters:
listener
- theNGClientListener
to no longer be notified of client events.
-
removeAllClientListeners
public void removeAllClientListeners()
Do not notify anymore about client disconnects
-
addHeartbeatListener
public void addHeartbeatListener(NGHeartbeatListener listener)
- Parameters:
listener
- theNGHeartbeatListener
to be notified of client events.
-
removeHeartbeatListener
public void removeHeartbeatListener(NGHeartbeatListener listener)
- Parameters:
listener
- theNGClientListener
to no longer be notified of client events.
-
-