1 7 package winstone; 8 9 import java.io.IOException ; 10 import java.io.PrintWriter ; 11 import java.io.UnsupportedEncodingException ; 12 import java.io.Writer ; 13 import java.text.DateFormat ; 14 import java.text.SimpleDateFormat ; 15 import java.util.ArrayList ; 16 import java.util.Date ; 17 import java.util.Iterator ; 18 import java.util.List ; 19 import java.util.Locale ; 20 import java.util.Map ; 21 import java.util.StringTokenizer ; 22 import java.util.TimeZone ; 23 24 import javax.servlet.ServletOutputStream ; 25 import javax.servlet.http.Cookie ; 26 import javax.servlet.http.HttpServletResponse ; 27 28 35 public class WinstoneResponse implements HttpServletResponse { 36 private static final DateFormat HTTP_DF = new SimpleDateFormat ( 37 "EEE, dd MMM yyyy HH:mm:ss z", Locale.US); 38 private static final DateFormat VERSION0_DF = new SimpleDateFormat ( 39 "EEE, dd-MMM-yy HH:mm:ss z", Locale.US); 40 static { 41 HTTP_DF.setTimeZone(TimeZone.getTimeZone("GMT")); 42 VERSION0_DF.setTimeZone(TimeZone.getTimeZone("GMT")); 43 } 44 45 static final String CONTENT_LENGTH_HEADER = "Content-Length"; 46 static final String CONTENT_TYPE_HEADER = "Content-Type"; 47 48 static final String CONTENT_LANGUAGE_HEADER = "Content-Language"; 50 static final String KEEP_ALIVE_HEADER = "Connection"; 51 static final String ENCODING_HEADER = "Transfer-Encoding"; 52 static final String KEEP_ALIVE_OPEN = "Keep-Alive"; 53 static final String KEEP_ALIVE_CLOSE = "Close"; 54 static final String DATE_HEADER = "Date"; 55 static final String SERVER_HEADER = "Server"; 56 static final String LOCATION_HEADER = "Location"; 57 static final String OUT_COOKIE_HEADER1 = "Set-Cookie"; 58 static final String OUT_COOKIE_HEADER2 = "Set-Cookie2"; 59 static final String X_POWERED_BY_HEADER = "X-Powered-By"; 60 static final String POWERED_BY_WINSTONE = "Servlet/2.4 (Winstone/0.8)"; 61 62 private int statusCode; 63 private WinstoneRequest req; 64 private WebAppConfiguration webAppConfig; 65 private WinstoneOutputStream outputStream; 66 private PrintWriter outputWriter; 67 68 private List headers; 69 private String explicitEncoding; 70 private String implicitEncoding; 71 private List cookies; 72 73 private Locale locale; 74 private String protocol; 75 private String reqKeepAliveHeader; 76 private Integer errorStatusCode; 77 78 81 public WinstoneResponse() { 82 83 this.headers = new ArrayList (); 84 this.cookies = new ArrayList (); 85 86 this.statusCode = SC_OK; 87 this.locale = null; this.explicitEncoding = null; 89 this.protocol = null; 90 this.reqKeepAliveHeader = null; 91 } 92 93 96 public void cleanUp() { 97 this.req = null; 98 this.webAppConfig = null; 99 this.outputStream = null; 100 this.outputWriter = null; 101 this.headers.clear(); 102 this.cookies.clear(); 103 this.protocol = null; 104 this.reqKeepAliveHeader = null; 105 106 this.statusCode = SC_OK; 107 this.errorStatusCode = null; 108 this.locale = null; this.explicitEncoding = null; 110 this.implicitEncoding = null; 111 } 112 113 private String getEncodingFromLocale(Locale loc) { 114 String localeString = loc.getLanguage() + "_" + loc.getCountry(); 115 Map encMap = this.webAppConfig.getLocaleEncodingMap(); 116 Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES, 117 "WinstoneResponse.LookForLocaleEncoding", 118 new String [] {localeString, encMap + ""}); 119 120 String fullMatch = (String ) encMap.get(localeString); 121 if (fullMatch != null) { 122 Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES, 123 "WinstoneResponse.FoundLocaleEncoding", fullMatch); 124 return fullMatch; 125 } else { 126 localeString = loc.getLanguage(); 127 Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES, 128 "WinstoneResponse.LookForLocaleEncoding", 129 new String [] {localeString, encMap + ""}); 130 String match = (String ) encMap.get(localeString); 131 if (match != null) { 132 Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES, 133 "WinstoneResponse.FoundLocaleEncoding", match); 134 } 135 return match; 136 } 137 } 138 139 public void setErrorStatusCode(int statusCode) { 140 this.errorStatusCode = new Integer (statusCode); 141 this.statusCode = statusCode; 142 } 143 144 public WinstoneOutputStream getWinstoneOutputStream() { 145 return this.outputStream; 146 } 147 148 public void setOutputStream(WinstoneOutputStream outData) { 149 this.outputStream = outData; 150 } 151 152 public void setWebAppConfig(WebAppConfiguration webAppConfig) { 153 this.webAppConfig = webAppConfig; 154 } 155 156 public String getProtocol() { 157 return this.protocol; 158 } 159 160 public void setProtocol(String protocol) { 161 this.protocol = protocol; 162 } 163 164 public void extractRequestKeepAliveHeader(WinstoneRequest req) { 165 this.reqKeepAliveHeader = req.getHeader(KEEP_ALIVE_HEADER); 166 } 167 168 public List getHeaders() { 169 return this.headers; 170 } 171 172 public List getCookies() { 173 return this.cookies; 174 } 175 176 public WinstoneRequest getRequest() { 177 return this.req; 178 } 179 180 public void setRequest(WinstoneRequest req) { 181 this.req = req; 182 } 183 184 public void startIncludeBuffer() { 185 this.outputStream.startIncludeBuffer(); 186 } 187 188 public void finishIncludeBuffer() throws IOException { 189 if (isIncluding()) { 190 if (this.outputWriter != null) { 191 this.outputWriter.flush(); 192 } 193 this.outputStream.finishIncludeBuffer(); 194 } 195 } 196 197 public void clearIncludeStackForForward() throws IOException { 198 this.outputStream.clearIncludeStackForForward(); 199 } 200 201 protected static String getCharsetFromContentTypeHeader(String type, StringBuffer remainder) { 202 if (type == null) { 203 return null; 204 } 205 StringTokenizer st = new StringTokenizer (type, ";"); 207 String localEncoding = null; 208 while (st.hasMoreTokens()) { 209 String clause = st.nextToken().trim(); 210 if (clause.startsWith("charset=")) 211 localEncoding = clause.substring(8); 212 else { 213 if (remainder.length() > 0) { 214 remainder.append(";"); 215 } 216 remainder.append(clause); 217 } 218 } 219 if ((localEncoding == null) || 220 !localEncoding.startsWith("\"") || 221 !localEncoding.endsWith("\"")) { 222 return localEncoding; 223 } else { 224 return localEncoding.substring(1, localEncoding.length() - 1); 225 } 226 } 227 228 231 public void validateHeaders() { 232 String lengthHeader = getHeader(CONTENT_LENGTH_HEADER); 234 if ((lengthHeader == null) && (this.statusCode >= 300)) { 235 int bodyBytes = this.outputStream.getOutputStreamLength(); 236 if (getBufferSize() > bodyBytes) { 237 Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES, 238 "WinstoneResponse.ForcingContentLength", "" + bodyBytes); 239 forceHeader(CONTENT_LENGTH_HEADER, "" + bodyBytes); 240 lengthHeader = getHeader(CONTENT_LENGTH_HEADER); 241 } 242 } 243 244 forceHeader(KEEP_ALIVE_HEADER, !closeAfterRequest() ? KEEP_ALIVE_OPEN : KEEP_ALIVE_CLOSE); 245 String contentType = getHeader(CONTENT_TYPE_HEADER); 246 if (this.statusCode != SC_MOVED_TEMPORARILY) { 247 if (contentType == null) { 248 forceHeader(CONTENT_TYPE_HEADER, "text/html;charset=" + getCharacterEncoding()); 250 } else if (contentType.startsWith("text/")) { 251 StringBuffer remainder = new StringBuffer (); 253 getCharsetFromContentTypeHeader(contentType, remainder); 254 forceHeader(CONTENT_TYPE_HEADER, remainder.toString() + ";charset=" + getCharacterEncoding()); 255 } 256 } 257 if (getHeader(DATE_HEADER) == null) { 258 forceHeader(DATE_HEADER, formatHeaderDate(new Date ())); 259 } 260 if (getHeader(X_POWERED_BY_HEADER) == null) { 261 forceHeader(X_POWERED_BY_HEADER, POWERED_BY_WINSTONE); 262 } 263 if (this.locale != null) { 264 String lang = this.locale.getLanguage(); 265 if ((this.locale.getCountry() != null) && !this.locale.getCountry().equals("")) { 266 lang = lang + "-" + this.locale.getCountry(); 267 } 268 forceHeader(CONTENT_LANGUAGE_HEADER, lang); 269 } 270 271 if (req.getWebAppConfig() == null) { 274 return; 275 } 276 HostConfiguration hostConfig = req.getHostGroup().getHostByName(req.getServerName()); 278 for (Iterator i = req.getCurrentSessionIds().keySet().iterator(); i.hasNext(); ) { 279 String prefix = (String ) i.next(); 280 String sessionId = (String ) req.getCurrentSessionIds().get(prefix); 281 WebAppConfiguration ownerContext = hostConfig.getWebAppByURI(prefix); 282 if (ownerContext != null) { 283 WinstoneSession session = ownerContext.getSessionById(sessionId, true); 284 if ((session != null) && session.isNew()) { 285 session.setIsNew(false); 286 Cookie cookie = new Cookie (WinstoneSession.SESSION_COOKIE_NAME, session.getId()); 287 cookie.setMaxAge(-1); 288 cookie.setSecure(req.isSecure()); 289 cookie.setVersion(0); cookie.setPath(req.getWebAppConfig().getContextPath().equals("") ? "/" 291 : req.getWebAppConfig().getContextPath()); 292 this.cookies.add(cookie); } 294 } 295 } 296 297 for (Iterator i = req.getRequestedSessionIds().keySet().iterator(); i.hasNext(); ) { 299 String prefix = (String ) i.next(); 300 String sessionId = (String ) req.getRequestedSessionIds().get(prefix); 301 if (!req.getCurrentSessionIds().containsKey(prefix)) { 302 Cookie cookie = new Cookie (WinstoneSession.SESSION_COOKIE_NAME, sessionId); 303 cookie.setMaxAge(0); cookie.setSecure(req.isSecure()); 305 cookie.setVersion(0); cookie.setPath(prefix.equals("") ? "/" : prefix); 307 this.cookies.add(cookie); } 309 } 310 311 Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES, "WinstoneResponse.HeadersPreCommit", 312 this.headers + ""); 313 } 314 315 318 public String writeCookie(Cookie cookie) throws IOException { 319 320 Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES, "WinstoneResponse.WritingCookie", cookie + ""); 321 StringBuffer out = new StringBuffer (); 322 323 if (cookie.getVersion() >= 1) 325 out.append(OUT_COOKIE_HEADER1).append(": "); else 327 out.append(OUT_COOKIE_HEADER1).append(": "); 328 329 if (cookie.getVersion() == 0) 331 out.append(cookie.getName()).append("=").append(cookie.getValue()); 332 else { 333 out.append(cookie.getName()).append("="); 334 quote(cookie.getValue(), out); 335 } 336 337 if (cookie.getVersion() >= 1) { 338 out.append("; Version=1"); 339 if (cookie.getDomain() != null) { 340 out.append("; Domain="); 341 quote(cookie.getDomain(), out); 342 } 343 if (cookie.getSecure()) 344 out.append("; Secure"); 345 346 if (cookie.getMaxAge() >= 0) 347 out.append("; Max-Age=").append(cookie.getMaxAge()); 348 else 349 out.append("; Discard"); 350 if (cookie.getPath() != null) { 351 out.append("; Path="); 352 quote(cookie.getPath(), out); 353 } 354 } else { 355 if (cookie.getDomain() != null) { 356 out.append("; Domain="); 357 out.append(cookie.getDomain()); 358 } 359 if (cookie.getMaxAge() > 0) { 360 long expiryMS = System.currentTimeMillis() 361 + (1000 * (long) cookie.getMaxAge()); 362 String expiryDate = null; 363 synchronized (VERSION0_DF) { 364 expiryDate = VERSION0_DF.format(new Date (expiryMS)); 365 } 366 out.append("; Expires=").append(expiryDate); 367 } else if (cookie.getMaxAge() == 0) { 368 String expiryDate = null; 369 synchronized (VERSION0_DF) { 370 expiryDate = VERSION0_DF.format(new Date (5000)); 371 } 372 out.append("; Expires=").append(expiryDate); 373 } 374 if (cookie.getPath() != null) 375 out.append("; Path=").append(cookie.getPath()); 376 if (cookie.getSecure()) 377 out.append("; Secure"); 378 } 379 return out.toString(); 380 } 381 382 private static String formatHeaderDate(Date dateIn) { 383 String date = null; 384 synchronized (HTTP_DF) { 385 date = HTTP_DF.format(dateIn); 386 } 387 return date; 388 } 389 390 394 protected void quote(String value, StringBuffer out) { 395 if (value.startsWith("\"") && value.endsWith("\"")) { 396 out.append(value); 397 } else { 398 boolean containsSpecial = false; 399 for (int n = 0; n < value.length(); n++) { 400 char thisChar = value.charAt(n); 401 if ((thisChar < 32) || (thisChar >= 127) 402 || (specialCharacters.indexOf(thisChar) != -1)) { 403 containsSpecial = true; 404 break; 405 } 406 } 407 if (containsSpecial) 408 out.append('"').append(value).append('"'); 409 else 410 out.append(value); 411 } 412 } 413 414 final String specialCharacters = "()<>@,;:\\\"/[]?={} \t"; 415 416 420 public boolean closeAfterRequest() { 421 String inKeepAliveHeader = this.reqKeepAliveHeader; 422 String outKeepAliveHeader = getHeader(KEEP_ALIVE_HEADER); 423 boolean hasContentLength = (getHeader(CONTENT_LENGTH_HEADER) != null); 424 if (this.protocol.startsWith("HTTP/0")) 425 return true; 426 else if ((inKeepAliveHeader == null) && (outKeepAliveHeader == null)) 427 return this.protocol.equals("HTTP/1.0") ? true : !hasContentLength; 428 else if (outKeepAliveHeader != null) 429 return outKeepAliveHeader.equalsIgnoreCase(KEEP_ALIVE_CLOSE) || !hasContentLength; 430 else if (inKeepAliveHeader != null) 431 return inKeepAliveHeader.equalsIgnoreCase(KEEP_ALIVE_CLOSE) || !hasContentLength; 432 else 433 return false; 434 } 435 436 public void flushBuffer() throws IOException { 438 if (this.outputWriter != null) { 439 this.outputWriter.flush(); 440 } 441 this.outputStream.flush(); 442 } 443 444 public void setBufferSize(int size) { 445 this.outputStream.setBufferSize(size); 446 } 447 448 public int getBufferSize() { 449 return this.outputStream.getBufferSize(); 450 } 451 452 public String getCharacterEncoding() { 453 String enc = getCurrentEncoding(); 454 return (enc == null ? "ISO-8859-1" : enc); 455 } 456 457 public void setCharacterEncoding(String encoding) { 458 if ((this.outputWriter == null) && !isCommitted()) { 459 Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES, "WinstoneResponse.SettingEncoding", encoding); 460 this.explicitEncoding = encoding; 461 correctContentTypeHeaderEncoding(encoding); 462 } 463 } 464 465 private void correctContentTypeHeaderEncoding(String encoding) { 466 String contentType = getContentType(); 467 if (contentType != null) { 468 StringBuffer remainderHeader = new StringBuffer (); 469 getCharsetFromContentTypeHeader(contentType, remainderHeader); 470 if (remainderHeader.length() != 0) { 471 forceHeader(CONTENT_TYPE_HEADER, remainderHeader + ";charset=" + encoding); 472 } 473 } 474 } 475 476 public String getContentType() { 477 return getHeader(CONTENT_TYPE_HEADER); 478 } 479 480 public void setContentType(String type) { 481 setHeader(CONTENT_TYPE_HEADER, type); 482 } 483 484 public Locale getLocale() { 485 return this.locale == null ? Locale.getDefault() : this.locale; 486 } 487 488 private boolean isIncluding() { 489 return this.outputStream.isIncluding(); 490 } 491 492 public void setLocale(Locale loc) { 493 if (isIncluding()) { 494 return; 495 } else if (isCommitted()) { 496 Logger.log(Logger.WARNING, Launcher.RESOURCES, 497 "WinstoneResponse.SetLocaleTooLate"); 498 } else { 499 if ((this.outputWriter == null) && (this.explicitEncoding == null)) { 500 String localeEncoding = getEncodingFromLocale(loc); 501 if (localeEncoding != null) { 502 this.implicitEncoding = localeEncoding; 503 correctContentTypeHeaderEncoding(localeEncoding); 504 } 505 } 506 this.locale = loc; 507 } 508 } 509 510 public ServletOutputStream getOutputStream() throws IOException { 511 Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES, "WinstoneResponse.GetOutputStream"); 512 return this.outputStream; 513 } 514 515 public PrintWriter getWriter() throws IOException { 516 Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES, "WinstoneResponse.GetWriter"); 517 if (this.outputWriter != null) 518 return this.outputWriter; 519 else { 520 this.outputWriter = new WinstoneResponseWriter(this.outputStream, this); 521 return this.outputWriter; 522 } 523 } 524 525 public boolean isCommitted() { 526 return this.outputStream.isCommitted(); 527 } 528 529 public void reset() { 530 if (!isIncluding()) { 531 resetBuffer(); 532 this.statusCode = SC_OK; 533 this.headers.clear(); 534 this.cookies.clear(); 535 } 536 } 537 538 public void resetBuffer() { 539 if (!isIncluding()) { 540 if (isCommitted()) 541 throw new IllegalStateException (Launcher.RESOURCES 542 .getString("WinstoneResponse.ResponseCommitted")); 543 544 this.outputStream.setDisregardMode(true); 546 547 if (this.outputWriter != null) { 548 this.outputWriter.flush(); 549 } 550 551 this.outputStream.setDisregardMode(false); 552 this.outputStream.reset(); 553 } 554 } 555 556 public void setContentLength(int len) { 557 setIntHeader(CONTENT_LENGTH_HEADER, len); 558 } 559 560 public void addCookie(Cookie cookie) { 562 if (!isIncluding()) { 563 this.cookies.add(cookie); 564 } 565 } 566 567 public boolean containsHeader(String name) { 568 for (int n = 0; n < this.headers.size(); n++) 569 if (((String ) this.headers.get(n)).startsWith(name)) 570 return true; 571 return false; 572 } 573 574 public void addDateHeader(String name, long date) { 575 addHeader(name, formatHeaderDate(new Date (date))); 576 } 578 public void addIntHeader(String name, int value) { 579 addHeader(name, "" + value); 580 } 581 582 public void addHeader(String name, String value) { 583 if (isIncluding()) { 584 Logger.log(Logger.DEBUG, Launcher.RESOURCES, "WinstoneResponse.HeaderInInclude", 585 new String [] {name, value}); 586 } else if (isCommitted()) { 587 Logger.log(Logger.DEBUG, Launcher.RESOURCES, "WinstoneResponse.HeaderAfterCommitted", 588 new String [] {name, value}); 589 } else if (value != null) { 590 if (name.equals(CONTENT_TYPE_HEADER)) { 591 StringBuffer remainderHeader = new StringBuffer (); 592 String headerEncoding = getCharsetFromContentTypeHeader(value, remainderHeader); 593 if (this.outputWriter != null) { 594 value = remainderHeader + ";charset=" + getCharacterEncoding(); 595 } else if (headerEncoding != null) { 596 this.explicitEncoding = headerEncoding; 597 } 598 } 599 this.headers.add(name + ": " + value); 600 } 601 } 602 603 public void setDateHeader(String name, long date) { 604 setHeader(name, formatHeaderDate(new Date (date))); 605 } 606 607 public void setIntHeader(String name, int value) { 608 setHeader(name, "" + value); 609 } 610 611 public void setHeader(String name, String value) { 612 if (isIncluding()) { 613 Logger.log(Logger.DEBUG, Launcher.RESOURCES, "WinstoneResponse.HeaderInInclude", 614 new String [] {name, value}); 615 } else if (isCommitted()) { 616 Logger.log(Logger.DEBUG, Launcher.RESOURCES, "WinstoneResponse.HeaderAfterCommitted", 617 new String [] {name, value}); 618 } else { 619 boolean found = false; 620 for (int n = 0; (n < this.headers.size()); n++) { 621 String header = (String ) this.headers.get(n); 622 if (header.startsWith(name + ": ")) { 623 if (found) { 624 this.headers.remove(n); 625 continue; 626 } 627 if (name.equals(CONTENT_TYPE_HEADER)) { 628 if (value != null) { 629 StringBuffer remainderHeader = new StringBuffer (); 630 String headerEncoding = getCharsetFromContentTypeHeader( 631 value, remainderHeader); 632 if (this.outputWriter != null) { 633 value = remainderHeader + ";charset=" + getCharacterEncoding(); 634 } else if (headerEncoding != null) { 635 this.explicitEncoding = headerEncoding; 636 } 637 } 638 } 639 640 if (value != null) { 641 this.headers.set(n, name + ": " + value); 642 } else { 643 this.headers.remove(n); 644 } 645 found = true; 646 } 647 } 648 if (!found) { 649 addHeader(name, value); 650 } 651 } 652 } 653 654 private void forceHeader(String name, String value) { 655 boolean found = false; 656 for (int n = 0; (n < this.headers.size()); n++) { 657 String header = (String ) this.headers.get(n); 658 if (header.startsWith(name + ": ")) { 659 found = true; 660 this.headers.set(n, name + ": " + value); 661 } 662 } 663 if (!found) { 664 this.headers.add(name + ": " + value); 665 } 666 } 667 668 private String getCurrentEncoding() { 669 if (this.explicitEncoding != null) { 670 return this.explicitEncoding; 671 } else if (this.implicitEncoding != null) { 672 return this.implicitEncoding; 673 } else if ((this.req != null) && (this.req.getCharacterEncoding() != null)) { 674 try { 675 "0".getBytes(this.req.getCharacterEncoding()); 676 return this.req.getCharacterEncoding(); 677 } catch (UnsupportedEncodingException err) { 678 return null; 679 } 680 } else { 681 return null; 682 } 683 } 684 685 public String getHeader(String name) { 686 for (int n = 0; n < this.headers.size(); n++) { 687 String header = (String ) this.headers.get(n); 688 if (header.startsWith(name + ": ")) 689 return header.substring(name.length() + 2); 690 } 691 return null; 692 } 693 694 public String encodeRedirectURL(String url) { 695 return url; 696 } 697 698 public String encodeURL(String url) { 699 return url; 700 } 701 702 public int getStatus() { 703 return this.statusCode; 704 } 705 706 public Integer getErrorStatusCode() { 707 return this.errorStatusCode; 708 } 709 710 public void setStatus(int sc) { 711 if (!isIncluding() && (this.errorStatusCode == null)) { 712 this.statusCode = sc; 714 } 718 } 719 720 public void sendRedirect(String location) throws IOException { 721 if (isIncluding()) { 722 Logger.log(Logger.ERROR, Launcher.RESOURCES, "IncludeResponse.Redirect", 723 location); 724 return; 725 } else if (isCommitted()) { 726 throw new IllegalStateException (Launcher.RESOURCES.getString("WinstoneOutputStream.AlreadyCommitted")); 727 } 728 resetBuffer(); 729 730 StringBuffer fullLocation = new StringBuffer (); 732 if (location.startsWith("http://") || location.startsWith("https://")) 733 fullLocation.append(location); 734 else { 735 fullLocation.append(this.req.getScheme()).append("://"); 736 fullLocation.append(this.req.getServerName()); 737 if (!((this.req.getServerPort() == 80) && this.req.getScheme() 738 .equals("http")) 739 && !((this.req.getServerPort() == 443) && this.req 740 .getScheme().equals("https"))) 741 fullLocation.append(':').append(this.req.getServerPort()); 742 if (location.startsWith("/")) { 743 fullLocation.append(location); 744 } else { 745 fullLocation.append(this.req.getRequestURI()); 746 if (fullLocation.toString().indexOf("?") != -1) 747 fullLocation.delete(fullLocation.toString().indexOf("?"), 748 fullLocation.length()); 749 fullLocation.delete( 750 fullLocation.toString().lastIndexOf("/") + 1, 751 fullLocation.length()); 752 fullLocation.append(location); 753 } 754 } 755 if (this.req != null) { 756 this.req.discardRequestBody(); 757 } 758 this.statusCode = HttpServletResponse.SC_MOVED_TEMPORARILY; 759 setHeader(LOCATION_HEADER, fullLocation.toString()); 760 setContentLength(0); 761 getWriter().flush(); 762 } 763 764 public void sendError(int sc) throws IOException { 765 sendError(sc, null); 766 } 767 768 public void sendError(int sc, String msg) throws IOException { 769 if (isIncluding()) { 770 Logger.log(Logger.ERROR, Launcher.RESOURCES, "IncludeResponse.Error", 771 new String [] { "" + sc, msg }); 772 return; 773 } 774 775 Logger.log(Logger.DEBUG, Launcher.RESOURCES, 776 "WinstoneResponse.SendingError", new String [] { "" + sc, msg }); 777 778 if ((this.webAppConfig != null) && (this.req != null)) { 779 780 RequestDispatcher rd = this.webAppConfig 781 .getErrorDispatcherByCode(sc, msg, null); 782 if (rd != null) { 783 try { 784 rd.forward(this.req, this); 785 return; 786 } catch (IllegalStateException err) { 787 throw err; 788 } catch (IOException err) { 789 throw err; 790 } catch (Throwable err) { 791 Logger.log(Logger.WARNING, Launcher.RESOURCES, 792 "WinstoneResponse.ErrorInErrorPage", new String [] { 793 rd.getName(), sc + "" }, err); 794 return; 795 } 796 } 797 } 798 if (this.errorStatusCode == null) { 801 this.statusCode = sc; 802 } 803 String output = Launcher.RESOURCES.getString("WinstoneResponse.ErrorPage", 804 new String [] { sc + "", (msg == null ? "" : msg), "", 805 Launcher.RESOURCES.getString("ServerVersion"), 806 "" + new Date () }); 807 setContentLength(output.getBytes(getCharacterEncoding()).length); 808 Writer out = getWriter(); 809 out.write(output); 810 out.flush(); 811 } 812 813 816 public String encodeRedirectUrl(String url) { 817 return encodeRedirectURL(url); 818 } 819 820 823 public String encodeUrl(String url) { 824 return encodeURL(url); 825 } 826 827 830 public void setStatus(int sc, String sm) { 831 setStatus(sc); 832 } 833 } 834 | Popular Tags |