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