1 31 32 package org.apache.commons.httpclient; 33 34 import java.io.IOException ; 35 import java.io.InputStream ; 36 37 import org.apache.commons.logging.LogFactory; 38 import org.apache.commons.logging.Log; 39 40 52 public class ResponseInputStream extends InputStream { 53 54 56 57 public static final Log LOG = LogFactory.getLog(ResponseInputStream.class); 58 59 61 69 public ResponseInputStream(InputStream stream, boolean chunked, int contentLength) { 70 LOG.trace("enter ResponseInputStream(InputStream, boolean, int)"); 71 72 if (null == stream) { 73 throw new NullPointerException ("InputStream parameter is null"); 74 } 75 closed = false; 76 count = 0; 77 this.chunk = chunked; 78 this.contentLength = contentLength; 79 this.stream = stream; 80 } 81 82 91 public ResponseInputStream(InputStream stream, HttpMethod method) { 92 super(); 93 LOG.trace("enter ResponseInputStream(InputStream, HttpMethod)"); 94 95 if (null == stream) { 96 throw new NullPointerException ("InputStream parameter is null"); 97 } 98 99 if (null == method) { 100 throw new NullPointerException ("HttpMethod parameter is null"); 101 } 102 103 closed = false; 104 count = 0; 105 106 Header transferEncoding = method.getResponseHeader("transfer-encoding"); 108 if ((null != transferEncoding) && (transferEncoding.getValue(). 109 toLowerCase().indexOf("chunked") != -1)) { 110 chunk = true; 111 } 112 113 Header contentLengthHeader = method.getResponseHeader("content-length"); 115 if (null != contentLengthHeader) { 116 try { 117 this.contentLength = 118 Integer.parseInt(contentLengthHeader.getValue()); 119 } catch (NumberFormatException ignored) { 120 } 122 } 123 124 this.stream = stream; 125 } 126 127 128 130 133 private boolean closed = false; 134 135 138 private boolean chunk = false; 139 140 143 private boolean endChunk = false; 144 145 148 private byte[] buffer = null; 149 150 153 private int length = 0; 154 155 158 private int pos = 0; 159 160 163 private int count = 0; 164 165 169 private int contentLength = -1; 170 171 174 private InputStream stream = null; 175 176 178 188 public void close() throws IOException { 189 LOG.trace("enter ResponseInputStream.close()"); 190 196 197 if (!closed) { 199 try { 200 if (chunk) { 201 while (!endChunk) { 202 int b = read(); 203 if (b < 0) { 204 break; 205 } 206 } 207 } else { 208 if (length > 0) { 209 while (count < length) { 210 int b = read(); 211 if (b < 0) { 212 break; 213 } 214 } 215 } 216 } 217 } catch (java.io.IOException ex) { 218 throw ex; 219 } finally { 220 closed = true; 221 } 222 } 223 } 224 225 226 244 public int read(byte b[], int off, int len) 245 throws IOException { 246 LOG.trace("enter ResponseInputStream.read(byte, int, int)"); 247 248 int avail = length - pos; 249 if ((avail == 0) && (!fillBuffer())) { 250 return (-1); 251 } 252 253 avail = length - pos; 254 if (avail == 0) { 255 return (-1); 256 } 257 258 int toCopy = avail; 259 260 if (toCopy < 0) { 261 return (-1); 262 } 263 264 if (avail > len) { 265 toCopy = len; 266 } 267 System.arraycopy(buffer, pos, b, off, toCopy); 268 pos += toCopy; 269 return toCopy; 270 } 271 272 281 public int read() throws IOException { 282 LOG.trace("enter ResponseInputStream.read()"); 283 284 if (pos == length) { 285 if (!fillBuffer()) { 286 return (-1); 287 } 288 } 289 290 return (buffer[pos++] & 0xff); 291 292 } 293 294 296 297 304 private boolean fillBuffer() throws IOException { 305 LOG.trace("enter ResponseInputStream.fillBuffer()"); 306 307 if (closed) { 309 return false; 310 } 311 313 if (endChunk) { 314 return false; 315 } 316 317 if ((contentLength >= 0) && (count >= contentLength)) { 319 return false; } 321 322 pos = 0; 323 324 if (chunk) { 325 326 try { 327 String numberValue = readLineFromStream(); 328 if (numberValue == null) { 329 throw new NumberFormatException ("unable to find chunk length"); 330 } 331 332 length = Integer.parseInt(numberValue.trim(), 16); 333 } catch (NumberFormatException e) { 334 length = -1; 336 chunk = false; 337 endChunk = true; 338 closed = true; 339 return false; 340 } 341 342 if (length == 0) { 343 344 String trailingLine = readLineFromStream(); 346 while (!trailingLine.equals("")) { 347 trailingLine = readLineFromStream(); 348 } 349 endChunk = true; 350 return false; 351 352 } else { 353 354 if ((buffer == null) || (length > buffer.length)) { 355 buffer = new byte[length]; 356 } 357 358 360 int nbRead = 0; 361 int currentRead = 0; 362 363 while (nbRead < length) { 364 try { 365 currentRead = stream.read(buffer, nbRead, 366 length - nbRead); 367 } catch (Throwable t) { 368 LOG.debug("Exception thrown reading chunk from response", t); 369 throw new IOException (); 370 } 371 if (currentRead < 0) { 372 throw new IOException ("Not enough bytes read"); 373 } 374 nbRead += currentRead; 375 } 376 377 readLineFromStream(); 379 380 } 381 382 } else { 384 try { 385 if (buffer == null) { 386 buffer = new byte[4096]; 387 } 388 length = stream.read(buffer); 389 count += length; 390 } catch (Throwable t) { 391 LOG.debug("Exception thrown reading from response", t); 392 throw new IOException (t.getMessage()); 393 } 394 395 } 396 397 return true; 398 399 } 400 401 412 private String readLineFromStream() 413 throws IOException { 414 LOG.trace("enter ResponseInputStream.ReadLineFromStream()"); 415 416 StringBuffer sb = new StringBuffer (); 417 while (true) { 418 int ch = stream.read(); 419 if (ch < 0) { 420 if (sb.length() == 0) { 421 return (null); 422 } else { 423 break; 424 } 425 } else if (ch == '\r') { 426 continue; 427 } else if (ch == '\n') { 428 break; 429 } 430 sb.append((char) ch); 431 } 432 return (sb.toString()); 433 } 434 } 435 | Popular Tags |