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 * 017 */ 018 019 package org.apache.commons.exec; 020 021 import org.apache.commons.exec.util.DebugUtils; 022 023 import java.io.IOException; 024 import java.io.InputStream; 025 import java.io.OutputStream; 026 027 /** 028 * Copies all data from an input stream to an output stream. 029 */ 030 public class StreamPumper implements Runnable { 031 032 /** the default size of the internal buffer for copying the streams */ 033 private static final int DEFAULT_SIZE = 1024; 034 035 /** the input stream to pump from */ 036 private final InputStream is; 037 038 /** the output stream to pmp into */ 039 private final OutputStream os; 040 041 /** the size of the internal buffer for copying the streams */ 042 private final int size; 043 044 /** was the end of the stream reached */ 045 private boolean finished; 046 047 /** close the output stream when exhausted */ 048 private final boolean closeWhenExhausted; 049 050 /** 051 * Create a new stream pumper. 052 * 053 * @param is input stream to read data from 054 * @param os output stream to write data to. 055 * @param closeWhenExhausted if true, the output stream will be closed when the input is exhausted. 056 */ 057 public StreamPumper(final InputStream is, final OutputStream os, 058 final boolean closeWhenExhausted) { 059 this.is = is; 060 this.os = os; 061 this.size = DEFAULT_SIZE; 062 this.closeWhenExhausted = closeWhenExhausted; 063 } 064 065 /** 066 * Create a new stream pumper. 067 * 068 * @param is input stream to read data from 069 * @param os output stream to write data to. 070 * @param closeWhenExhausted if true, the output stream will be closed when the input is exhausted. 071 * @param size the size of the internal buffer for copying the streams 072 */ 073 public StreamPumper(final InputStream is, final OutputStream os, 074 final boolean closeWhenExhausted, final int size) { 075 this.is = is; 076 this.os = os; 077 this.size = (size > 0 ? size : DEFAULT_SIZE); 078 this.closeWhenExhausted = closeWhenExhausted; 079 } 080 081 /** 082 * Create a new stream pumper. 083 * 084 * @param is input stream to read data from 085 * @param os output stream to write data to. 086 */ 087 public StreamPumper(final InputStream is, final OutputStream os) { 088 this(is, os, false); 089 } 090 091 /** 092 * Copies data from the input stream to the output stream. Terminates as 093 * soon as the input stream is closed or an error occurs. 094 */ 095 public void run() { 096 synchronized (this) { 097 // Just in case this object is reused in the future 098 finished = false; 099 } 100 101 final byte[] buf = new byte[this.size]; 102 103 int length; 104 try { 105 while ((length = is.read(buf)) > 0) { 106 os.write(buf, 0, length); 107 } 108 } catch (Exception e) { 109 // nothing to do - happens quite often with watchdog 110 } finally { 111 if (closeWhenExhausted) { 112 try { 113 os.close(); 114 } catch (IOException e) { 115 String msg = "Got exception while closing exhausted output stream"; 116 DebugUtils.handleException(msg ,e); 117 } 118 } 119 synchronized (this) { 120 finished = true; 121 notifyAll(); 122 } 123 } 124 } 125 126 /** 127 * Tells whether the end of the stream has been reached. 128 * 129 * @return true is the stream has been exhausted. 130 */ 131 public synchronized boolean isFinished() { 132 return finished; 133 } 134 135 /** 136 * This method blocks until the stream pumper finishes. 137 * 138 * @see #isFinished() 139 */ 140 public synchronized void waitFor() throws InterruptedException { 141 while (!isFinished()) { 142 wait(); 143 } 144 } 145 }