com.gc.iotools.stream.writer.inspection.WriterDumper.java Source code

Java tutorial

Introduction

Here is the source code for com.gc.iotools.stream.writer.inspection.WriterDumper.java

Source

package com.gc.iotools.stream.writer.inspection;

/*
 * Copyright (c) 2008, 2014 Gabriele Contini. This source code is released
 * under the BSD License.
 */
import java.io.FilterWriter;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;

/**
 * <p>
 * This class act as a filter, simply forwarding the calls to the
 * <code>Writer</code> passed in the constructor. Doing so it also keeps track
 * of the data written to the underlying stream. This is useful for logging
 * purposes.
 * </p>
 * <p>
 * <b>WARNING</b>: data written to this <code>Writer</code> are kept in
 * memory, so this class should be used when the maximum size of the character
 * data is known in advance, and it is "small" compared to memory size. In
 * case this is not possible this class should be instantiated limiting the
 * data that can be dumped {@link #WriterDumper(sink, maxDumpSize)}.
 * </p>
 * <p>
 * Usage:
 * </p>
 * 
 * <pre>
 *     Reader source=... //some data to be read.
 *   Writer destination1= new StringWriter();
 *
 *   WriterDumper dumper = new WriterDumper(destination1);
 *   org.apache.commons.io.IOUtils.copy(source, dumper);
 *   dumper.close();
 *   String data= dumper.getData();
 *   //at this point "data" and destination1.toString() contains the same string.
 * </pre>
 * 
 * @author dvd.smnt
 * @since 1.2.9
 * @version $Id$
 */
public class WriterDumper<T extends Writer> extends FilterWriter {
    /** Constant <code>INDEFINITE_SIZE=-1L</code> */
    public static final long INDEFINITE_SIZE = -1L;

    private long currentSize = 0;

    private final StringWriter dataDumpStream = new StringWriter();
    private boolean dumpEnabled = true;
    private final long maxDumpSize;

    /**
     * <p>
     * Constructor for WriterDumper. Completely record the stream for an
     * indefinite size into memory.
     * </p>
     * 
     * @param sink
     *            the underlying stream that must be dumped.
     */
    public WriterDumper(final T sink) {
        this(sink, -1);
    }

    /**
     * <p>
     * Constructor for WriterDumper.
     * </p>
     * 
     * @param sink
     *            the underlying stream that must be dumped.
     * @param maxDumpSize
     *            the maximum size of the dump.
     */
    public WriterDumper(final T sink, final long maxDumpSize) {
        super(sink);
        this.maxDumpSize = maxDumpSize;
    }

    /** {@inheritDoc} */
    @Override
    public void close() throws IOException {
        super.close();
    }

    /**
     * <p>
     * Allow to switch off the copy to the internal character buffer. The copy
     * is enabled by default.
     * </p>
     * 
     * @param enable
     *            a boolean.
     */
    public void enableDump(final boolean enable) {
        this.dumpEnabled = enable;
    }

    /**
     * <p>
     * Returns the data that was written until now to the internal character
     * buffer. This corresponds to the data written to the internal
     * <code>Writer</code> passed in the constructor if
     * <code>maxDumpSize</code> was not reach and data dump was not disabled
     * (calling <code>enableDump(false)</code>).
     * </p>
     * 
     * @return the data that was written until now to the Writer
     */
    public final String getData() {
        return this.dataDumpStream.toString();
    }

    /**
     * <p>
     * Returns the wrapped (original) <code>Writer</code> passed in the
     * constructor.
     * </p>
     * 
     * @return The original <code>Writer</code> passed in the constructor
     */
    @SuppressWarnings("unchecked")
    public final T getWrappedStream() {
        return (T) this.out;
    }

    private boolean maxSizeNotReached() {
        boolean result;
        if (this.maxDumpSize == INDEFINITE_SIZE) {
            result = true;
        } else {
            result = this.currentSize < this.maxDumpSize;
        }
        return result;
    }

    /** {@inheritDoc} */
    @Override
    public void write(final char[] b, final int off, final int len) throws IOException {
        this.out.write(b, off, len);
        if (this.dumpEnabled && maxSizeNotReached()) {
            int lenght;
            if (this.maxDumpSize == INDEFINITE_SIZE) {
                lenght = len;
            } else {
                lenght = (int) Math.min(len, this.maxDumpSize - this.currentSize);
            }
            this.currentSize += lenght;
            this.dataDumpStream.write(b, off, lenght);
        }
    }

    /** {@inheritDoc} */
    @Override
    public void write(final int b) throws IOException {
        super.write(b);
        if (this.dumpEnabled && maxSizeNotReached()) {
            this.dataDumpStream.write(b);
            this.currentSize++;
        }
    }
}