001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 * 
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 * 
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.io.output;
018
019import java.io.IOException;
020import java.io.OutputStream;
021
022/**
023 * Classic splitter of OutputStream. Named after the unix 'tee' 
024 * command. It allows a stream to be branched off so there 
025 * are now two streams.
026 *
027 * @version $Id: TeeOutputStream.java 1686503 2015-06-19 21:32:13Z sebb $
028 */
029public class TeeOutputStream extends ProxyOutputStream {
030
031    /** the second OutputStream to write to */
032    protected OutputStream branch; //TODO consider making this private
033
034    /**
035     * Constructs a TeeOutputStream.
036     * @param out the main OutputStream
037     * @param branch the second OutputStream
038     */
039    public TeeOutputStream(final OutputStream out, final OutputStream branch) {
040        super(out);
041        this.branch = branch;
042    }
043
044    /**
045     * Write the bytes to both streams.
046     * @param b the bytes to write
047     * @throws IOException if an I/O error occurs
048     */
049    @Override
050    public synchronized void write(final byte[] b) throws IOException {
051        super.write(b);
052        this.branch.write(b);
053    }
054
055    /**
056     * Write the specified bytes to both streams.
057     * @param b the bytes to write
058     * @param off The start offset
059     * @param len The number of bytes to write
060     * @throws IOException if an I/O error occurs
061     */
062    @Override
063    public synchronized void write(final byte[] b, final int off, final int len) throws IOException {
064        super.write(b, off, len);
065        this.branch.write(b, off, len);
066    }
067
068    /**
069     * Write a byte to both streams.
070     * @param b the byte to write
071     * @throws IOException if an I/O error occurs
072     */
073    @Override
074    public synchronized void write(final int b) throws IOException {
075        super.write(b);
076        this.branch.write(b);
077    }
078
079    /**
080     * Flushes both streams.
081     * @throws IOException if an I/O error occurs
082     */
083    @Override
084    public void flush() throws IOException {
085        super.flush();
086        this.branch.flush();
087    }
088
089    /**
090     * Closes both output streams.
091     * 
092     * If closing the main output stream throws an exception, attempt to close the branch output stream.
093     * 
094     * If closing the main and branch output streams both throw exceptions, which exceptions is thrown by this method is
095     * currently unspecified and subject to change.
096     * 
097     * @throws IOException
098     *             if an I/O error occurs
099     */
100    @Override
101    public void close() throws IOException {
102        try {
103            super.close();
104        } finally {
105            this.branch.close();
106        }
107    }
108
109}