001package com.randomnoun.common.io;
002
003import java.io.IOException;
004import java.io.OutputStream;
005
006/**
007 * An outputstream which mimics the 'tee' unix utility. 
008 * It writes to two outputStreams at the same time
009 */
010public class TeeOutputStream extends OutputStream {
011
012        /** The OutputStream */
013        protected OutputStream out;
014        
015    /** The second OutputStream to write to. */
016    protected OutputStream branch;
017
018    /**
019     * Constructs a TeeOutputStream.
020     *
021     * @param out    the main OutputStream
022     * @param branch the second OutputStream
023     */
024    public TeeOutputStream(final OutputStream out, final OutputStream branch) {
025        this.out = out;
026        this.branch = branch;
027    }
028
029    /**
030     * Writes the bytes to both streams.
031     *
032     * @param b the bytes to write
033     * @throws IOException if an I/O error occurs.
034     */
035    @Override
036    public synchronized void write(final byte[] b) throws IOException {
037        out.write(b);
038        branch.write(b);
039    }
040
041    /**
042     * Writes the specified bytes to both streams.
043     *
044     * @param b   the bytes to write
045     * @param off The start offset
046     * @param len The number of bytes to write
047     * @throws IOException if an I/O error occurs.
048     */
049    @Override
050    public synchronized void write(final byte[] b, final int off, final int len) throws IOException {
051        out.write(b, off, len);
052        branch.write(b, off, len);
053    }
054
055    /**
056     * Writes a byte to both streams.
057     *
058     * @param b the byte to write
059     * @throws IOException if an I/O error occurs.
060     */
061    @Override
062    public synchronized void write(final int b) throws IOException {
063        out.write(b);
064        branch.write(b);
065    }
066
067    /**
068     * Flushes both streams.
069     *
070     * @throws IOException if an I/O error occurs.
071     */
072    @Override
073    public void flush() throws IOException {
074        out.flush();
075        branch.flush();
076    }
077
078    /**
079     * Closes both output streams.
080     * 
081     * <p>
082     * If closing the main output stream throws an exception, attempt to close the branch output stream.
083     * </p>
084     *
085     * <p>
086     * If closing the main and branch output streams both throw exceptions, which exceptions is thrown by this method is
087     * currently unspecified and subject to change.
088     * </p>
089     *
090     * @throws IOException if an I/O error occurs.
091     */
092    @Override
093    public void close() throws IOException {
094        try {
095            out.close();
096        } finally {
097            branch.close();
098        }
099    }
100
101}