
com.gc.iotools.stream.writer.TeeWriter Maven / Gradle / Ivy
Show all versions of easystream Show documentation
package com.gc.iotools.stream.writer;
/*
* Copyright (c) 2008, 2015 Gabriele Contini. This source code is released
* under the BSD License.
*/
import java.io.IOException;
import java.io.Writer;
import java.util.Arrays;
/**
*
* Copies the data that is written to this class to the Writer(s)
* passed in the constructor. It also collect statistics on the operations
* done (time spent writing to the internal writers, amount of data written).
*
*
* Usage:
*
*
*
* InputStream source=... //some data to be read.
* StringWriter destination1= new StringWriter();
* StringWriter destination2= new StringWriter();
*
* TeeWriter tee = new TeeWriter(destination1,destination2);
* org.apache.commons.io.IOUtils.copy(source,tee);
* tee.close();
* //at this point both destination1 and destination2 contains the same characters.
*
*
* @author dvd.smnt
* @since 1.2.7
* @version $Id: TeeWriter.java 576 2015-03-28 00:03:33Z gcontini $
*/
public class TeeWriter extends Writer {
/**
* True
when {@link #close()} is invoked. Prevents data from
* being written to the destination Writer(s)
after
* {@link #close()} has been invoked.
*/
protected boolean closeCalled = false;
private final boolean[] copyEnabled;
/**
* The destination Writer(s)
where data is written.
*/
protected final Writer[] destinations;
private long size = 0;
private final long[] writeTime;
/**
*
* Creates a TeeWriter
and saves its arguments, the
* destinations
for later use.
*
*
* This constructor allow to specify multiple Writer
to which
* the data will be copied.
*
*
* @since 1.2.4
* @param destinations
* Data written to thisWriter
are copied to all
* the destinations
.
*/
public TeeWriter(final Writer... destinations) {
checkDestinations(destinations);
this.writeTime = new long[destinations.length];
this.destinations = destinations;
this.copyEnabled = new boolean[destinations.length];
Arrays.fill(this.copyEnabled, true);
}
private void checkDestinations(final Writer... destinations) {
if (destinations == null) {
throw new IllegalArgumentException(
"Destinations Writer can't be null");
}
if (destinations.length == 0) {
throw new IllegalArgumentException(
"At least one destination Writer must be specified");
}
for (final Writer destination : destinations) {
if (destination == null) {
throw new IllegalArgumentException(
"One of the Writers in the array is null");
}
}
}
/** {@inheritDoc} */
@Override
public void close() throws IOException {
if (!this.closeCalled) {
this.closeCalled = true;
for (int i = 0; i < this.destinations.length; i++) {
final Writer stream = this.destinations[i];
final long start = System.currentTimeMillis();
stream.close();
this.writeTime[i] += System.currentTimeMillis() - start;
}
}
}
/**
*
* Allow to switch off the copy to the underlying streams. Setting the
* parameter to false will disable the copy to all the underlying streams
* at once.
*
*
* If you need more fine grained control you should use
* {@link #enableCopy(boolean[])} .
*
*
* @since 1.2.9
* @param enable
* whether to copy or not the bytes to the underlying stream.
*/
public final void enableCopy(final boolean enable) {
Arrays.fill(this.copyEnabled, enable);
}
/**
*
* Allow to switch off the copy to the underlying streams, selectively
* enabling or disabling copy on some specific stream.
*
*
* The copy is enabled by default. Each element in the array correspond to
* an OutputStream
passed in the constructor. If the
* correspondent element in the array passed as a parameter is set to
* true
the copy will be enabled.It can be invoked multiple
* times.
*
*
* @since 1.2.9
* @param enable
* whether to copy or not the bytes to the underlying stream.
*/
public final void enableCopy(final boolean[] enable) {
if (enable == null) {
throw new IllegalArgumentException("Enable array can't be null");
}
if (enable.length != this.copyEnabled.length) {
throw new IllegalArgumentException("Enable array must be of "
+ "the same size of the OutputStream array passed "
+ "in the constructor. Array size [" + enable.length
+ "] streams [" + this.copyEnabled.length + "]");
}
for (int i = 0; i < enable.length; i++) {
this.copyEnabled[i] = enable[i];
}
}
/** {@inheritDoc} */
@Override
public void flush() throws IOException {
if (!this.closeCalled) {
for (int i = 0; i < this.destinations.length; i++) {
final Writer stream = this.destinations[i];
final long start = System.currentTimeMillis();
stream.flush();
this.writeTime[i] += System.currentTimeMillis() - start;
}
}
}
/**
*
* This method returns the size in bytes of the data written to this
* Writer. It can be used to collect statistics on the write operations.
*
*
* @return size in bytes of the data written to the Writers
.
*/
public final long getSize() {
return this.size;
}
/**
*
* Return the time spent writing to the destination Writer(s)
* in milliseconds.
*
*
* The returned array has one element for each Writer
passed
* in the constructor.
*
*
* @return time spent writing on the destination Writers
.
*/
public long[] getWriteTime() {
return this.writeTime;
}
/** {@inheritDoc} */
@Override
public void write(final char[] b) throws IOException {
if (b == null) {
throw new NullPointerException("Array of bytes can't be null");
}
if (!this.closeCalled) {
for (int i = 0; i < this.destinations.length; i++) {
if (this.copyEnabled[i]) {
final Writer stream = this.destinations[i];
final long start = System.currentTimeMillis();
stream.write(b);
this.writeTime[i] += System.currentTimeMillis() - start;
}
}
this.size += b.length;
}
}
/** {@inheritDoc} */
@Override
public void write(final char[] b, final int off, final int len)
throws IOException {
if (b == null) {
throw new NullPointerException("Array of bytes can't be null");
}
if (!this.closeCalled) {
for (int i = 0; i < this.destinations.length; i++) {
if (this.copyEnabled[i]) {
final Writer stream = this.destinations[i];
final long start = System.currentTimeMillis();
stream.write(b, off, len);
this.writeTime[i] += System.currentTimeMillis() - start;
}
}
this.size += len;
}
}
/** {@inheritDoc} */
@Override
public void write(final int b) throws IOException {
if (!this.closeCalled) {
for (int i = 0; i < this.destinations.length; i++) {
if (this.copyEnabled[i]) {
final Writer stream = this.destinations[i];
final long start = System.currentTimeMillis();
stream.write(b);
this.writeTime[i] += System.currentTimeMillis() - start;
}
}
this.size++;
}
}
}