GuardedOutputStream.java

package tools.jackson.core.io;

import java.io.IOException;
import java.io.OutputStream;
import java.util.Objects;

/**
 * {@link OutputStream} wrapper that forwards written content, but never flushes or
 * closes the underlying stream; writes after {@link #close()} fail.
 *<p>
 * Used by textual format backends that wrap the caller's {@link OutputStream} in a
 * {@link java.io.Writer} of their own, which buffers content and only hands it over
 * when flushed or closed. That {@code Writer} therefore has to be flushed by
 * {@link tools.jackson.core.JsonGenerator#flush()} and closed by
 * {@link tools.jackson.core.JsonGenerator#close()} regardless of
 * {@link tools.jackson.core.StreamWriteFeature#FLUSH_PASSED_TO_STREAM} and
 * {@link tools.jackson.core.StreamWriteFeature#AUTO_CLOSE_TARGET} -- but doing so must
 * not flush or close the caller's stream. Whether that is to be done is decided by
 * the generator, when flushed or closed (since those features may be changed on the
 * generator after construction): generator needs to keep a separate reference to
 * the caller's stream for this purpose.
 *
 * @since 3.3
 */
public class GuardedOutputStream extends OutputStream
{
    private final OutputStream _out;

    private boolean _closed;

    public GuardedOutputStream(OutputStream out) {
        _out = Objects.requireNonNull(out, "Cannot pass `null` OutputStream");
    }

    @Override
    public void write(int b) throws IOException {
        _verifyOpen();
        _out.write(b);
    }

    @Override
    public void write(byte[] b) throws IOException {
        _verifyOpen();
        _out.write(b, 0, b.length);
    }

    @Override
    public void write(byte[] b, int off, int len) throws IOException {
        _verifyOpen();
        _out.write(b, off, len);
    }

    @Override
    public void flush() {
        // Deliberately does NOT flush the stream we wrap
    }

    @Override
    public void close() {
        // Deliberately does NOT close (nor flush) the stream we wrap; but
        // must not pass any further writes to it either
        _closed = true;
    }

    private void _verifyOpen() throws IOException {
        if (_closed) {
            throw new IOException("Stream closed");
        }
    }
}