1 2 package ch.ethz.ssh2; 3 4 import java.io.IOException ; 5 import java.io.InputStream ; 6 7 34 35 public class StreamGobbler extends InputStream 36 { 37 class GobblerThread extends Thread 38 { 39 public void run() 40 { 41 byte[] buff = new byte[8192]; 42 43 while (true) 44 { 45 try 46 { 47 int avail = is.read(buff); 48 49 synchronized (synchronizer) 50 { 51 if (avail <= 0) 52 { 53 isEOF = true; 54 synchronizer.notifyAll(); 55 break; 56 } 57 58 int space_available = buffer.length - write_pos; 59 60 if (space_available < avail) 61 { 62 63 64 int unread_size = write_pos - read_pos; 65 int need_space = unread_size + avail; 66 67 byte[] new_buffer = buffer; 68 69 if (need_space > buffer.length) 70 { 71 int inc = need_space / 3; 72 inc = (inc < 256) ? 256 : inc; 73 inc = (inc > 8192) ? 8192 : inc; 74 new_buffer = new byte[need_space + inc]; 75 } 76 77 if (unread_size > 0) 78 System.arraycopy(buffer, read_pos, new_buffer, 0, unread_size); 79 80 buffer = new_buffer; 81 82 read_pos = 0; 83 write_pos = unread_size; 84 } 85 86 System.arraycopy(buff, 0, buffer, write_pos, avail); 87 write_pos += avail; 88 89 synchronizer.notifyAll(); 90 } 91 } 92 catch (IOException e) 93 { 94 synchronized (synchronizer) 95 { 96 exception = e; 97 synchronizer.notifyAll(); 98 break; 99 } 100 } 101 } 102 } 103 } 104 105 private InputStream is; 106 private GobblerThread t; 107 108 private Object synchronizer = new Object (); 109 110 private boolean isEOF = false; 111 private boolean isClosed = false; 112 private IOException exception = null; 113 114 private byte[] buffer = new byte[2048]; 115 private int read_pos = 0; 116 private int write_pos = 0; 117 118 public StreamGobbler(InputStream is) 119 { 120 this.is = is; 121 t = new GobblerThread(); 122 t.setDaemon(true); 123 t.start(); 124 } 125 126 public int read() throws IOException 127 { 128 synchronized (synchronizer) 129 { 130 if (isClosed) 131 throw new IOException ("This StreamGobbler is closed."); 132 133 while (read_pos == write_pos) 134 { 135 if (exception != null) 136 throw exception; 137 138 if (isEOF) 139 return -1; 140 141 try 142 { 143 synchronizer.wait(); 144 } 145 catch (InterruptedException e) 146 { 147 } 148 } 149 150 int b = buffer[read_pos++] & 0xff; 151 152 return b; 153 } 154 } 155 156 public int available() throws IOException 157 { 158 synchronized (synchronizer) 159 { 160 if (isClosed) 161 throw new IOException ("This StreamGobbler is closed."); 162 163 return write_pos - read_pos; 164 } 165 } 166 167 public int read(byte[] b) throws IOException 168 { 169 return read(b, 0, b.length); 170 } 171 172 public void close() throws IOException 173 { 174 synchronized (synchronizer) 175 { 176 if (isClosed) 177 return; 178 isClosed = true; 179 isEOF = true; 180 synchronizer.notifyAll(); 181 is.close(); 182 } 183 } 184 185 public int read(byte[] b, int off, int len) throws IOException 186 { 187 if (b == null) 188 throw new NullPointerException (); 189 190 if ((off < 0) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0) || (off > b.length)) 191 throw new IndexOutOfBoundsException (); 192 193 if (len == 0) 194 return 0; 195 196 synchronized (synchronizer) 197 { 198 if (isClosed) 199 throw new IOException ("This StreamGobbler is closed."); 200 201 while (read_pos == write_pos) 202 { 203 if (exception != null) 204 throw exception; 205 206 if (isEOF) 207 return -1; 208 209 try 210 { 211 synchronizer.wait(); 212 } 213 catch (InterruptedException e) 214 { 215 } 216 } 217 218 int avail = write_pos - read_pos; 219 220 avail = (avail > len) ? len : avail; 221 222 System.arraycopy(buffer, read_pos, b, off, avail); 223 224 read_pos += avail; 225 226 return avail; 227 } 228 } 229 } 230 | Popular Tags |