14fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy/*
24fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Licensed to the Apache Software Foundation (ASF) under one or more
34fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * contributor license agreements.  See the NOTICE file distributed with
44fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * this work for additional information regarding copyright ownership.
54fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The ASF licenses this file to You under the Apache License, Version 2.0
64fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * (the "License"); you may not use this file except in compliance with
74fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * the License.  You may obtain a copy of the License at
84fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy *
94fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy *      http://www.apache.org/licenses/LICENSE-2.0
104fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy *
114fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Unless required by applicable law or agreed to in writing, software
124fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * distributed under the License is distributed on an "AS IS" BASIS,
134fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
144fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * See the License for the specific language governing permissions and
154fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * limitations under the License.
164fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */
174fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedypackage org.apache.commons.io.input;
184fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
194fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedyimport java.io.IOException;
204fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedyimport java.io.InputStream;
214fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedyimport java.io.OutputStream;
224fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
234fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy/**
244fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * InputStream proxy that transparently writes a copy of all bytes read
254fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * from the proxied stream to a given OutputStream. Using {@link #skip(long)}
264fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * or {@link #mark(int)}/{@link #reset()} on the stream will result on some
274fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * bytes from the input stream being skipped or duplicated in the output
284fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * stream.
294fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p>
304fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The proxied input stream is closed when the {@link #close()} method is
314fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * called on this proxy. It is configurable whether the associated output
324fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * stream will also closed.
334fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy *
344fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @version $Id: TeeInputStream.java 587913 2007-10-24 15:47:30Z niallp $
354fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @since Commons IO 1.4
364fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */
374fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedypublic class TeeInputStream extends ProxyInputStream {
384fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
394fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    /**
404fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * The output stream that will receive a copy of all bytes read from the
414fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * proxied input stream.
424fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     */
434fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    private final OutputStream branch;
444fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
454fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    /**
464fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * Flag for closing also the associated output stream when this
474fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * stream is closed.
484fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     */
494fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    private final boolean closeBranch;
504fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
514fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    /**
524fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * Creates a TeeInputStream that proxies the given {@link InputStream}
534fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * and copies all read bytes to the given {@link OutputStream}. The given
544fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * output stream will not be closed when this stream gets closed.
554fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     *
564fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @param input input stream to be proxied
574fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @param branch output stream that will receive a copy of all bytes read
584fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     */
594fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    public TeeInputStream(InputStream input, OutputStream branch) {
604fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        this(input, branch, false);
614fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    }
624fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
634fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    /**
644fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * Creates a TeeInputStream that proxies the given {@link InputStream}
654fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * and copies all read bytes to the given {@link OutputStream}. The given
664fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * output stream will be closed when this stream gets closed if the
674fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * closeBranch parameter is <code>true</code>.
684fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     *
694fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @param input input stream to be proxied
704fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @param branch output stream that will receive a copy of all bytes read
714fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @param closeBranch flag for closing also the output stream when this
724fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     *                    stream is closed
734fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     */
744fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    public TeeInputStream(
754fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy            InputStream input, OutputStream branch, boolean closeBranch) {
764fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        super(input);
774fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        this.branch = branch;
784fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        this.closeBranch = closeBranch;
794fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    }
804fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
814fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    /**
824fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * Closes the proxied input stream and, if so configured, the associated
834fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * output stream. An exception thrown from one stream will not prevent
844fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * closing of the other stream.
854fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     *
864fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @throws IOException if either of the streams could not be closed
874fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     */
884fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    public void close() throws IOException {
894fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        try {
904fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy            super.close();
914fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        } finally {
924fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy            if (closeBranch) {
934fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                branch.close();
944fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy            }
954fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        }
964fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    }
974fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
984fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    /**
994fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * Reads a single byte from the proxied input stream and writes it to
1004fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * the associated output stream.
1014fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     *
1024fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @return next byte from the stream, or -1 if the stream has ended
1034fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @throws IOException if the stream could not be read (or written)
1044fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     */
1054fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    public int read() throws IOException {
1064fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        int ch = super.read();
1074fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        if (ch != -1) {
1084fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy            branch.write(ch);
1094fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        }
1104fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        return ch;
1114fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    }
1124fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
1134fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    /**
1144fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * Reads bytes from the proxied input stream and writes the read bytes
1154fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * to the associated output stream.
1164fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     *
1174fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @param bts byte buffer
1184fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @param st start offset within the buffer
1194fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @param end maximum number of bytes to read
1204fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @return number of bytes read, or -1 if the stream has ended
1214fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @throws IOException if the stream could not be read (or written)
1224fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     */
1234fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    public int read(byte[] bts, int st, int end) throws IOException {
1244fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        int n = super.read(bts, st, end);
1254fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        if (n != -1) {
1264fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy            branch.write(bts, st, n);
1274fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        }
1284fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        return n;
1294fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    }
1304fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
1314fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    /**
1324fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * Reads bytes from the proxied input stream and writes the read bytes
1334fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * to the associated output stream.
1344fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     *
1354fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @param bts byte buffer
1364fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @return number of bytes read, or -1 if the stream has ended
1374fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @throws IOException if the stream could not be read (or written)
1384fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     */
1394fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    public int read(byte[] bts) throws IOException {
1404fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        int n = super.read(bts);
1414fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        if (n != -1) {
1424fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy            branch.write(bts, 0, n);
1434fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        }
1444fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        return n;
1454fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    }
1464fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
1474fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy}
148