Class AbstractChunkTransformInputStream
- All Implemented Interfaces:
Closeable, AutoCloseable
This abstract class provides a framework for streaming transformations where
the input is processed in aligned blocks of inChunkSize bytes,
producing corresponding output blocks of outChunkSize bytes.
Subclasses implement the transformation logic in
transform(byte[], int, int, byte[]) and handle any trailing input in
doFinal(byte[], int, int, byte[], int).
Design and invariants
- Input bytes are read from the wrapped
InputStreamintoinBuf, preferably in multiples ofinChunkSize. transform(byte[], int, int, byte[])is invoked for all complete chunks. Its contract is to consumeinChunks * inChunkSizebytes frominand produce contiguous output bytes intoout.- If the final read yields a partial chunk smaller than
inChunkSize,doFinal(byte[], int, int, byte[], int)is invoked to process the remainder and emit any trailer (e.g., padding block or authentication tag). - Output bytes are staged in
outBufand consumed byread()andread(byte[], int, int).
Buffer sizing and finalization headroom
The primary constructor sizes both input and output buffers to
chunks * inChunkSize and chunks * outChunkSize, respectively.
An overloaded constructor adds finalizationOutputChunks to the
output-side capacity only, resulting in
outChunkSize * (chunks + finalizationOutputChunks). This headroom
guarantees that the last doFinal(...) call can emit trailer bytes
(for example, a padding block or AEAD tag) even when the steady-state output
window is full.
Typical values when outChunkSize == 16 (AES-sized):
- No padding modes (e.g., AES/CBC/NOPADDING):
finalizationOutputChunks = 0. - Padding modes (e.g., AES/CBC/PKCS5PADDING):
1to cover a full padding block. - AEAD modes (e.g., AES/GCM/NOPADDING with 16-byte tag):
2to cover tail bytes (up to 15) plus the tag (commonly 16).
Thread-safety
Instances are not thread-safe. If a single instance is shared across threads, external synchronization is required.Example
// Example subclass wiring (pseudocode)
final class MyCipherStream extends AbstractChunkTransformInputStream {
private final Cipher cipher;
MyCipherStream(InputStream in, Cipher c) {
super(in, 16, 16, 256, 2); // +2 output chunks headroom (e.g., AES-GCM)
this.cipher = c;
}
@Override protected int transform(byte[] src, int off, int chunks, byte[] dst) throws IOException {
try {
return cipher.update(src, off, chunks * 16, dst, 0);
} catch (ShortBufferException e) {
throw new IOException(e);
}
}
@Override protected int doFinal(byte[] src, int off, int len, byte[] dst, int dstOff) throws IOException {
try {
int out = 0;
if (len > 0) { out = cipher.update(src, off, len, dst, dstOff); dstOff += out; }
out += cipher.doFinal(dst, dstOff);
return out;
} catch (GeneralSecurityException | ShortBufferException e) {
throw new IOException(e);
}
}
}
- Author:
- Leo Galambos
- Since:
- 1.0
-
Field Summary
FieldsModifier and TypeFieldDescriptionprotected booleanFlag indicating that end-of-stream has been reached.protected final byte[]Input buffer storing data read from the upstream stream.protected final intSize of one logical input chunk.protected intNumber of valid bytes currently ininBuf.protected byte[]Output buffer storing transformed bytes awaiting consumption.protected final intSize of one logical output chunk.protected intNumber of valid bytes currently inoutBuf.protected intCurrent read position withinoutBuf.Fields inherited from class FilterInputStream
in -
Constructor Summary
ConstructorsModifierConstructorDescriptionprotectedAbstractChunkTransformInputStream(InputStream upstream, int inChunkSize, int outChunkSize, int chunks) Constructs a new chunk-transforming input stream with symmetric input and output capacities.protectedAbstractChunkTransformInputStream(InputStream upstream, int inChunkSize, int outChunkSize, int chunks, int finalizationOutputChunks) Constructs a new chunk-transforming input stream with extra output headroom for finalization. -
Method Summary
Modifier and TypeMethodDescriptionprotected abstract intdoFinal(byte[] in, int inOff, int len, byte[] out, int outOff) Finalizes the transformation with an optional trailing incomplete chunk.intread()Reads the next transformed byte.intread(byte[] b) Reads transformed bytes into the given array.intread(byte[] b, int off, int len) Reads up tolentransformed bytes into the target buffer.protected abstract inttransform(byte[] in, int inOff, int inChunks, byte[] out) Transforms one or more full input chunks into output bytes.Methods inherited from class FilterInputStream
available, close, mark, markSupported, reset, skipMethods inherited from class InputStream
nullInputStream, readAllBytes, readNBytes, readNBytes, skipNBytes, transferTo
-
Field Details
-
inBuf
protected final byte[] inBufInput buffer storing data read from the upstream stream. -
outBuf
protected byte[] outBufOutput buffer storing transformed bytes awaiting consumption. -
inLen
protected int inLenNumber of valid bytes currently ininBuf. -
outPtr
protected int outPtrCurrent read position withinoutBuf. -
outLen
protected int outLenNumber of valid bytes currently inoutBuf. -
eofSeen
protected boolean eofSeenFlag indicating that end-of-stream has been reached. -
inChunkSize
protected final int inChunkSizeSize of one logical input chunk. -
outChunkSize
protected final int outChunkSizeSize of one logical output chunk.
-
-
Constructor Details
-
AbstractChunkTransformInputStream
protected AbstractChunkTransformInputStream(InputStream upstream, int inChunkSize, int outChunkSize, int chunks) Constructs a new chunk-transforming input stream with symmetric input and output capacities.The input buffer is sized to
inChunkSize * chunksand the output buffer tooutChunkSize * chunks. No extra output headroom is reserved for finalization.- Parameters:
upstream- the underlying input streaminChunkSize- size of input chunks expected by the transform (must be > 1)outChunkSize- size of output chunks produced by the transform (must be > 0)chunks- number of chunks buffered at once (must be > 0)- Throws:
IllegalArgumentException- if a size is outside its documented range or a buffer size overflows
-
AbstractChunkTransformInputStream
protected AbstractChunkTransformInputStream(InputStream upstream, int inChunkSize, int outChunkSize, int chunks, int finalizationOutputChunks) Constructs a new chunk-transforming input stream with extra output headroom for finalization.The input buffer is sized to
inChunkSize * chunks. The output buffer is sized tooutChunkSize * (chunks + finalizationOutputChunks)so that the last call todoFinal(byte[], int, int, byte[], int)can emit trailer bytes even when the steady-state output region is full.- Parameters:
upstream- the underlying input streaminChunkSize- size of input chunks expected by the transform (must be > 1)outChunkSize- size of output chunks produced by the transform (must be > 0)chunks- number of chunks buffered at once for steady-state (must be > 0)finalizationOutputChunks- number of extra output chunks reserved for finalization (must be >= 0)- Throws:
IllegalArgumentException- if a size is outside its documented range or a buffer size overflows
-
-
Method Details
-
transform
Transforms one or more full input chunks into output bytes.- Parameters:
in- buffer containing input datainOff- offset ininwhere chunks begininChunks- number of complete input chunks availableout- destination buffer for transformed bytes- Returns:
- number of bytes written to
out - Throws:
IOException- if transformation fails
-
doFinal
protected abstract int doFinal(byte[] in, int inOff, int len, byte[] out, int outOff) throws IOException Finalizes the transformation with an optional trailing incomplete chunk.Invoked at EOF if the last read produced fewer than
inChunkSizebytes. Implementations may perform padding, compute an authentication tag, or flush any provider-internal state. TheoutOffargument specifies where to start writing the final bytes inout.- Parameters:
in- buffer containing the final partial chunk (may be empty)inOff- offset of the partial datalen- number of available bytes (<inChunkSize)out- destination buffer for transformed bytesoutOff- offset inoutwhere bytes should be written- Returns:
- number of bytes written to
out - Throws:
IOException- if finalization fails or the provider reports an error
-
read
Reads the next transformed byte.- Overrides:
readin classFilterInputStream- Returns:
- the next byte as an unsigned int in the range
0-255, or-1if end-of-stream has been reached - Throws:
IOException- if an I/O error occurs
-
read
Reads transformed bytes into the given array.This implementation delegates to
read(byte[], int, int).- Overrides:
readin classFilterInputStream- Parameters:
b- target buffer- Returns:
- number of bytes read, or
-1at EOF - Throws:
IOException- if an I/O error occurs
-
read
Reads up tolentransformed bytes into the target buffer.Blocks until at least one byte is available or EOF is reached.
- Overrides:
readin classFilterInputStream- Parameters:
b- target bufferoff- offset inbwhere data should be storedlen- maximum number of bytes to read- Returns:
- number of bytes read, or
-1if EOF and no data returned - Throws:
IOException- if an I/O error occurs
-