1 28 29 package HTTPClient; 30 31 import java.io.IOException ; 32 import java.io.EOFException ; 33 import java.io.InterruptedIOException ; 34 import java.io.InputStream ; 35 import java.io.ByteArrayInputStream ; 36 import java.net.URL ; 37 import java.util.Date ; 38 import java.util.Enumeration ; 39 40 41 51 52 public class HTTPResponse implements GlobalConstants, HTTPClientModuleConstants 53 { 54 55 private HTTPClientModule[] modules; 56 57 58 private int timeout; 59 60 61 private Request request = null; 62 63 64 private Response response = null; 65 66 67 private HttpOutputStream out_stream = null; 68 69 70 private InputStream inp_stream; 71 72 73 private int StatusCode; 74 75 76 private String ReasonLine; 77 78 79 private String Version; 80 81 82 private URI OriginalURI = null; 83 84 85 private URI EffectiveURI = null; 86 87 88 private CIHashtable Headers = null; 89 90 91 private CIHashtable Trailers = null; 92 93 94 private int ContentLength = -1; 95 96 97 private byte[] Data = null; 98 99 100 private boolean initialized = false; 101 102 103 private boolean got_trailers = false; 104 105 106 private boolean aborted = false; 107 108 109 private String method = null; 110 111 112 114 120 HTTPResponse(HTTPClientModule[] modules, int timeout, Request orig) 121 { 122 this.modules = modules; 123 this.timeout = timeout; 124 try 125 { 126 this.OriginalURI = new URI(orig.getConnection().getProtocol(), 127 orig.getConnection().getHost(), 128 orig.getConnection().getPort(), 129 orig.getRequestURI()); 130 } 131 catch (ParseException pe) 132 { } 133 this.method = orig.getMethod(); 134 } 135 136 137 141 void set(Request req, Response resp) 142 { 143 this.request = req; 144 this.response = resp; 145 resp.http_resp = this; 146 resp.timeout = timeout; 147 this.aborted = resp.final_resp; 148 } 149 150 151 155 void set(Request req, HttpOutputStream out_stream) 156 { 157 this.request = req; 158 this.out_stream = out_stream; 159 } 160 161 162 164 177 public final int getStatusCode() throws IOException , ModuleException 178 { 179 if (!initialized) handleResponse(); 180 return StatusCode; 181 } 182 183 189 public final String getReasonLine() throws IOException , ModuleException 190 { 191 if (!initialized) handleResponse(); 192 return ReasonLine; 193 } 194 195 201 public final String getVersion() throws IOException , ModuleException 202 { 203 if (!initialized) handleResponse(); 204 return Version; 205 } 206 207 216 public final String getServer() throws IOException , ModuleException 217 { 218 if (!initialized) handleResponse(); 219 return getHeader("Server"); 220 } 221 222 223 228 public final URI getOriginalURI() 229 { 230 return OriginalURI; 231 } 232 233 234 245 public final URL getEffectiveURL() throws IOException , ModuleException 246 { 247 if (!initialized) handleResponse(); 248 if (EffectiveURI != null) 249 return EffectiveURI.toURL(); 250 return null; 251 } 252 253 254 264 public final URI getEffectiveURI() throws IOException , ModuleException 265 { 266 if (!initialized) handleResponse(); 267 if (EffectiveURI != null) 268 return EffectiveURI; 269 return OriginalURI; 270 } 271 272 273 281 public String getHeader(String hdr) throws IOException , ModuleException 282 { 283 if (!initialized) handleResponse(); 284 return (String ) Headers.get(hdr.trim()); 285 } 286 287 298 public int getHeaderAsInt(String hdr) 299 throws IOException , ModuleException, NumberFormatException 300 { 301 return Integer.parseInt(getHeader(hdr)); 302 } 303 304 318 public Date getHeaderAsDate(String hdr) 319 throws IOException , IllegalArgumentException , ModuleException 320 { 321 String raw_date = getHeader(hdr); 322 if (raw_date == null) return null; 323 324 if (raw_date.toUpperCase().indexOf("GMT") == -1) 326 raw_date += " GMT"; 327 328 Date date; 329 330 try 331 { date = new Date (raw_date); } 332 catch (IllegalArgumentException iae) 333 { 334 long time; 336 try 337 { time = Long.parseLong(raw_date); } 338 catch (NumberFormatException nfe) 339 { throw iae; } if (time < 0) time = 0; 341 date = new Date (time * 1000L); 342 } 343 344 return date; 345 } 346 347 353 public Enumeration listHeaders() throws IOException , ModuleException 354 { 355 if (!initialized) handleResponse(); 356 return Headers.keys(); 357 } 358 359 360 371 public String getTrailer(String trailer) throws IOException , ModuleException 372 { 373 if (!got_trailers) getTrailers(); 374 return (String ) Trailers.get(trailer.trim()); 375 } 376 377 388 public int getTrailerAsInt(String trailer) 389 throws IOException , ModuleException, NumberFormatException 390 { 391 return Integer.parseInt(getTrailer(trailer)); 392 } 393 394 408 public Date getTrailerAsDate(String trailer) 409 throws IOException , IllegalArgumentException , ModuleException 410 { 411 String raw_date = getTrailer(trailer); 412 if (raw_date == null) return null; 413 414 if (raw_date.toUpperCase().indexOf("GMT") == -1) 416 raw_date += " GMT"; 417 418 Date date; 419 420 try 421 { date = new Date (raw_date); } 422 catch (IllegalArgumentException iae) 423 { 424 long time; 426 try 427 { time = Long.parseLong(raw_date); } 428 catch (NumberFormatException nfe) 429 { throw iae; } if (time < 0) time = 0; 431 date = new Date (time * 1000L); 432 } 433 434 return date; 435 } 436 437 443 public Enumeration listTrailers() throws IOException , ModuleException 444 { 445 if (!got_trailers) getTrailers(); 446 return Trailers.keys(); 447 } 448 449 450 471 public synchronized byte[] getData() throws IOException , ModuleException 472 { 473 if (!initialized) handleResponse(); 474 475 if (Data == null) 476 { 477 try 478 { readResponseData(inp_stream); } 479 catch (InterruptedIOException ie) { 481 throw ie; 482 } 483 catch (IOException ioe) 484 { 485 if (DebugResp) 486 { 487 System.err.println("HResp: (\"" + method + " " + 488 OriginalURI.getPath() + "\")"); 489 System.err.print(" "); 490 ioe.printStackTrace(); 491 } 492 try { inp_stream.close(); } catch (Exception e) { } 493 throw ioe; 494 } 495 496 inp_stream.close(); 497 } 498 499 return Data; 500 } 501 502 512 public synchronized InputStream getInputStream() 513 throws IOException , ModuleException 514 { 515 if (!initialized) handleResponse(); 516 517 if (Data == null) 518 return inp_stream; 519 else 520 { 521 getData(); return new ByteArrayInputStream (Data); 523 } 524 } 525 526 527 532 public String toString() 533 { 534 if (!initialized) 535 { 536 try 537 { handleResponse(); } 538 catch (Exception e) 539 { 540 if (DebugResp && !(e instanceof InterruptedIOException )) 541 { 542 System.err.println("HResp: (\"" + method + " " + 543 OriginalURI.getPath() + "\")"); 544 System.err.print(" "); 545 e.printStackTrace(); 546 } 547 return "Failed to read headers: " + e; 548 } 549 } 550 551 String nl = System.getProperty("line.separator", "\n"); 552 553 StringBuffer str = new StringBuffer (Version); 554 str.append(' '); 555 str.append(StatusCode); 556 str.append(' '); 557 str.append(ReasonLine); 558 str.append(nl); 559 560 if (EffectiveURI != null) 561 { 562 str.append("Effective-URI: "); 563 str.append(EffectiveURI); 564 str.append(nl); 565 } 566 567 Enumeration hdr_list = Headers.keys(); 568 while (hdr_list.hasMoreElements()) 569 { 570 String hdr = (String ) hdr_list.nextElement(); 571 str.append(hdr); 572 str.append(": "); 573 str.append(Headers.get(hdr)); 574 str.append(nl); 575 } 576 577 return str.toString(); 578 } 579 580 581 583 584 HTTPClientModule[] getModules() 585 { 586 return modules; 587 } 588 589 590 600 synchronized boolean handleResponse() throws IOException , ModuleException 601 { 602 if (initialized) return false; 603 604 605 606 607 if (out_stream != null) 608 { 609 response = out_stream.getResponse(); 610 response.http_resp = this; 611 out_stream = null; 612 } 613 614 615 616 617 doModules: while (true) 618 { 619 620 Phase1: for (int idx=0; idx<modules.length && !aborted; idx++) 621 { 622 try 623 { modules[idx].responsePhase1Handler(response, request); } 624 catch (RetryException re) 625 { 626 if (re.restart) 627 continue doModules; 628 else 629 throw re; 630 } 631 } 632 633 Phase2: for (int idx=0; idx<modules.length && !aborted; idx++) 634 { 635 int sts = modules[idx].responsePhase2Handler(response, request); 636 switch (sts) 637 { 638 case RSP_CONTINUE: break; 640 641 case RSP_RESTART: idx = -1; 643 continue doModules; 644 645 case RSP_SHORTCIRC: break doModules; 647 648 case RSP_REQUEST: case RSP_NEWCON_REQ: response.getInputStream().close(); 651 if (handle_trailers) invokeTrailerHandlers(true); 652 if (request.internal_subrequest) return true; 653 request.getConnection(). 654 handleRequest(request, this, response, true); 655 if (initialized) break doModules; 656 657 idx = -1; 658 continue doModules; 659 660 case RSP_SEND: case RSP_NEWCON_SND: response.getInputStream().close(); 663 if (handle_trailers) invokeTrailerHandlers(true); 664 if (request.internal_subrequest) return true; 665 request.getConnection(). 666 handleRequest(request, this, response, false); 667 idx = -1; 668 continue doModules; 669 670 default: throw new Error ("HTTPClient Internal Error: invalid status"+ 672 " " + sts + " returned by module " + 673 modules[idx].getClass().getName()); 674 } 675 } 676 677 Phase3: for (int idx=0; idx<modules.length && !aborted; idx++) 678 { 679 modules[idx].responsePhase3Handler(response, request); 680 } 681 682 break doModules; 683 } 684 685 686 response.getStatusCode(); 687 688 689 if (!request.internal_subrequest) 690 init(response); 691 692 if (handle_trailers) 693 invokeTrailerHandlers(false); 694 695 return false; 696 } 697 698 699 704 void init(Response resp) 705 { 706 if (initialized) return; 707 708 this.StatusCode = resp.StatusCode; 709 this.ReasonLine = resp.ReasonLine; 710 this.Version = resp.Version; 711 this.EffectiveURI = resp.EffectiveURI; 712 this.ContentLength = resp.ContentLength; 713 this.Headers = resp.Headers; 714 this.inp_stream = resp.inp_stream; 715 this.Data = resp.Data; 716 initialized = true; 717 } 718 719 720 private boolean handle_trailers = false; 721 private boolean trailers_handled = false; 722 723 731 void invokeTrailerHandlers(boolean force) 732 throws IOException , ModuleException 733 { 734 if (trailers_handled) return; 735 736 if (!force && !initialized) 737 { 738 handle_trailers = true; 739 return; 740 } 741 742 for (int idx=0; idx<modules.length && !aborted; idx++) 743 { 744 modules[idx].trailerHandler(response, request); 745 } 746 747 trailers_handled = true; 748 } 749 750 751 755 void markAborted() 756 { 757 aborted = true; 758 } 759 760 761 764 private synchronized void getTrailers() throws IOException , ModuleException 765 { 766 if (got_trailers) return; 767 if (!initialized) handleResponse(); 768 769 response.getTrailer("Any"); 770 Trailers = response.Trailers; 771 got_trailers = true; 772 773 invokeTrailerHandlers(false); 774 } 775 776 777 784 private void readResponseData(InputStream inp) 785 throws IOException , ModuleException 786 { 787 if (ContentLength == 0) 788 return; 789 790 if (Data == null) 791 Data = new byte[0]; 792 793 794 796 int off = Data.length; 797 798 try 799 { 800 if (getHeader("Content-Length") != null) 802 { 803 int rcvd = 0; 804 Data = new byte[ContentLength]; 805 806 do 807 { 808 off += rcvd; 809 rcvd = inp.read(Data, off, ContentLength-off); 810 } while (rcvd != -1 && off+rcvd < ContentLength); 811 812 824 } 825 else 826 { 827 int inc = 1000, 828 rcvd = 0; 829 830 do 831 { 832 off += rcvd; 833 Data = Util.resizeArray(Data, off+inc); 834 } while ((rcvd = inp.read(Data, off, inc)) != -1); 835 836 Data = Util.resizeArray(Data, off); 837 } 838 } 839 catch (IOException ioe) 840 { 841 Data = Util.resizeArray(Data, off); 842 throw ioe; 843 } 844 finally 845 { 846 try 847 { inp.close(); } 848 catch (IOException ioe) 849 { } 850 } 851 } 852 853 854 int getTimeout() 855 { 856 return timeout; 857 } 858 } 859 860 | Popular Tags |