1bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook/*
2bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Licensed to the Apache Software Foundation (ASF) under one or more
3bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * contributor license agreements.  See the NOTICE file distributed with
4bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * this work for additional information regarding copyright ownership.
5bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * The ASF licenses this file to You under the Apache License, Version 2.0
6bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * (the "License"); you may not use this file except in compliance with
7bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * the License.  You may obtain a copy of the License at
8bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *
9bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *      http://www.apache.org/licenses/LICENSE-2.0
10bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *
11bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Unless required by applicable law or agreed to in writing, software
12bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * distributed under the License is distributed on an "AS IS" BASIS,
13bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * See the License for the specific language governing permissions and
15bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * limitations under the License.
16bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */
17bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookpackage org.apache.commons.io.input;
18bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
19bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport java.io.IOException;
20bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport java.io.InputStream;
21bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport java.io.OutputStream;
22bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
23bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook/**
24bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * InputStream proxy that transparently writes a copy of all bytes read
25bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * from the proxied stream to a given OutputStream. Using {@link #skip(long)}
26bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * or {@link #mark(int)}/{@link #reset()} on the stream will result on some
27bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * bytes from the input stream being skipped or duplicated in the output
28bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * stream.
29bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * <p>
30bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * The proxied input stream is closed when the {@link #close()} method is
31bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * called on this proxy. It is configurable whether the associated output
32bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * stream will also closed.
33bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *
34bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @version $Id: TeeInputStream.java 587913 2007-10-24 15:47:30Z niallp $
35bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @since Commons IO 1.4
36bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */
37bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookpublic class TeeInputStream extends ProxyInputStream {
38bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
39bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
40bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * The output stream that will receive a copy of all bytes read from the
41bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * proxied input stream.
42bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
43bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private final OutputStream branch;
44bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
45bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
46bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Flag for closing also the associated output stream when this
47bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * stream is closed.
48bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
49bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private final boolean closeBranch;
50bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
51bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
52bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Creates a TeeInputStream that proxies the given {@link InputStream}
53bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * and copies all read bytes to the given {@link OutputStream}. The given
54bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * output stream will not be closed when this stream gets closed.
55bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
56bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param input input stream to be proxied
57bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param branch output stream that will receive a copy of all bytes read
58bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
59bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public TeeInputStream(InputStream input, OutputStream branch) {
60bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        this(input, branch, false);
61bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
62bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
63bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
64bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Creates a TeeInputStream that proxies the given {@link InputStream}
65bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * and copies all read bytes to the given {@link OutputStream}. The given
66bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * output stream will be closed when this stream gets closed if the
67bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * closeBranch parameter is <code>true</code>.
68bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
69bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param input input stream to be proxied
70bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param branch output stream that will receive a copy of all bytes read
71bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param closeBranch flag for closing also the output stream when this
72bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *                    stream is closed
73bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
74bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public TeeInputStream(
75bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            InputStream input, OutputStream branch, boolean closeBranch) {
76bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        super(input);
77bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        this.branch = branch;
78bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        this.closeBranch = closeBranch;
79bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
80bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
81bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
82bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Closes the proxied input stream and, if so configured, the associated
83bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * output stream. An exception thrown from one stream will not prevent
84bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * closing of the other stream.
85bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
86bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @throws IOException if either of the streams could not be closed
87bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
88bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public void close() throws IOException {
89bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        try {
90bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            super.close();
91bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        } finally {
92bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            if (closeBranch) {
93bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                branch.close();
94bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            }
95bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
96bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
97bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
98bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
99bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Reads a single byte from the proxied input stream and writes it to
100bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * the associated output stream.
101bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
102bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return next byte from the stream, or -1 if the stream has ended
103bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @throws IOException if the stream could not be read (or written)
104bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
105bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public int read() throws IOException {
106bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        int ch = super.read();
107bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (ch != -1) {
108bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            branch.write(ch);
109bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
110bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return ch;
111bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
112bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
113bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
114bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Reads bytes from the proxied input stream and writes the read bytes
115bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * to the associated output stream.
116bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
117bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param bts byte buffer
118bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param st start offset within the buffer
119bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param end maximum number of bytes to read
120bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return number of bytes read, or -1 if the stream has ended
121bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @throws IOException if the stream could not be read (or written)
122bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
123bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public int read(byte[] bts, int st, int end) throws IOException {
124bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        int n = super.read(bts, st, end);
125bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (n != -1) {
126bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            branch.write(bts, st, n);
127bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
128bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return n;
129bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
130bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
131bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
132bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Reads bytes from the proxied input stream and writes the read bytes
133bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * to the associated output stream.
134bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
135bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param bts byte buffer
136bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return number of bytes read, or -1 if the stream has ended
137bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @throws IOException if the stream could not be read (or written)
138bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
139bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public int read(byte[] bts) throws IOException {
140bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        int n = super.read(bts);
141bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (n != -1) {
142bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            branch.write(bts, 0, n);
143bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
144bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return n;
145bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
146bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
147bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook}
148