1 package com.quadcap.http.server22; 2 3 40 41 import java.util.Calendar ; 42 import java.util.Date ; 43 import java.util.Enumeration ; 44 import java.util.Hashtable ; 45 import java.util.Locale ; 46 import java.util.TimeZone ; 47 import java.util.Vector ; 48 49 import java.text.DateFormat ; 50 import java.text.SimpleDateFormat ; 51 52 import java.io.ByteArrayOutputStream ; 53 import java.io.IOException ; 54 import java.io.OutputStream ; 55 import java.io.OutputStreamWriter ; 56 import java.io.PrintWriter ; 57 58 import javax.servlet.ServletOutputStream ; 59 import javax.servlet.http.Cookie ; 60 import javax.servlet.http.HttpServletResponse ; 61 62 import com.quadcap.net.server.WorkerOutputStream; 63 64 import com.quadcap.util.Debug; 65 66 74 public class HttpResponse implements HttpServletResponse { 75 WebWorker w; 76 Hashtable headers = new Hashtable (); 77 String protocol; 78 int sc = SC_OK; 79 String sm = "Request Completed"; 80 boolean changedCode = false; 81 Locale defaultLocale = Locale.getDefault(); 82 Locale locale = defaultLocale; 83 84 int contentLength = -1; 85 String contentType = null; 86 StringBuffer headerBuf = new StringBuffer (); 87 boolean headerBufValid = true; 88 boolean anyHeaders = false; 89 boolean keepAlive = false; 90 public boolean getWriterCalled = false; 91 public boolean getOutputStreamCalled = false; 92 93 byte[] fixedHeaders = null; 94 ByteArrayOutputStream fixedH = new ByteArrayOutputStream (); 95 96 HttpOutputStream os; 97 PrintWriter writer = null; 98 JspWriter jWriter = new JspWriter(8192, true); 99 boolean jWriterInit = false; 100 101 Vector cookies = null; 102 long calbase = -1; 103 byte[] curTime = null; 104 105 static DateFormat cookieDateFormat; 106 static TimeZone GMT; 107 static SimpleDateFormat df; 108 static SimpleDateFormat df2; 109 110 static { 111 GMT = TimeZone.getTimeZone("GMT"); 112 cookieDateFormat = new SimpleDateFormat ("E, dd-MMM-yy HH:mm:ss 'GMT'"); 113 cookieDateFormat.setTimeZone(GMT); 114 df = new SimpleDateFormat ("'Date: 'EEE, dd MMM yyyy HH:mm:ss 'GMT\r\n'"); 115 df.setTimeZone(GMT); 116 df2 = new SimpleDateFormat ("EEE, dd MMM yyyy HH:mm:ss 'GMT'"); 117 df2.setTimeZone(GMT); 118 } 119 120 125 public HttpResponse(WebWorker w) { 126 this.w = w; 127 } 128 129 public void reset(HttpOutputStream os) { 130 this.os = os; 131 this.os.setResponse(this); 132 headers.clear(); 133 sc = SC_OK; 134 jWriterInit = false; 135 sm = "Request Completed"; 136 changedCode = false; 137 locale = defaultLocale; 138 contentLength = -1; 139 contentType = null; 140 headerBuf.setLength(0); 141 headerBufValid = true; 142 writer = null; 143 cookies = null; 144 anyHeaders = false; 145 getWriterCalled = false; 146 getOutputStreamCalled = false; 147 } 148 149 void setProtocol(String p) { 150 this.protocol = p; 151 } 152 153 void setKeepAlive(boolean v) { 154 this.keepAlive = v; 155 } 156 157 static final void write(OutputStream out, String s) throws IOException { 158 for (int i = 0; i < s.length(); i++) { 159 out.write((byte)s.charAt(i)); 160 } 161 } 162 163 static final byte[] headerSep = { (byte)':', (byte)' ' }; 164 static final byte[] CRLF = { (byte)'\r', (byte)'\n' }; 165 static final byte[] OKRESPONSE = 166 " 200 Request Completed\r\n".getBytes(); 167 static final byte[] CONTENT_TYPE = "Content-Type: ".getBytes(); 168 static final byte[] CONTENT_LENGTH = "Content-Length: ".getBytes(); 169 static final byte[] CONNECTION_KEEPALIVE = 170 "Connection: Keep-Alive\r\n".getBytes(); 171 static final byte[] CONNECTION_CLOSE = 172 "Connection: Close\r\n".getBytes(); 173 static final byte[] DEFAULT_CONTENT_TYPE = 174 "Content-Type: text/plain\r\n".getBytes(); 175 176 final void writeHeader(WorkerOutputStream out, String name, String val) 177 throws IOException 178 { 179 if (Trace.level() > 1) { 181 Debug.println("header: " + name + ": " + val); 182 } 183 out.write(name); 185 out.write(headerSep); 186 out.write(val); out.write(CRLF); 188 } 189 190 193 public void writeHeaders() throws IOException { 194 WorkerOutputStream out = os.getOutputStream(); 195 out.write(protocol); 196 if (changedCode) { 197 out.write(' '); 198 out.writeInt(sc); 199 out.write(' '); 200 out.write(sm); 201 out.write(CRLF); 202 } else { 203 out.write(OKRESPONSE); 204 } 205 206 if (keepAlive) { 207 out.write(CONNECTION_KEEPALIVE); 208 } else { 209 out.write(CONNECTION_CLOSE); 210 } 211 212 if (contentType != null) { 213 out.write(CONTENT_TYPE); 214 out.write(contentType); 215 out.write(CRLF); 216 } else { 217 out.write(DEFAULT_CONTENT_TYPE); 218 } 219 220 if (contentLength >= 0) { 221 out.write(CONTENT_LENGTH); 222 out.writeInt(contentLength); 223 out.write(CRLF); 224 } 225 if (fixedHeaders == null) { 226 if (fixedH != null) { 227 fixedHeaders = fixedH.toByteArray(); 228 fixedH = null; 229 } 230 out.write(fixedHeaders); 231 } 232 233 if (headerBufValid) { 234 out.write(headerBuf.toString()); 235 } else if (anyHeaders) { 236 Enumeration hdrs = headers.keys(); 237 while (hdrs.hasMoreElements()) { 238 String headerName = (String )hdrs.nextElement(); 239 Object headerVal = headers.get(headerName); 240 if (headerVal instanceof String ) { 241 writeHeader(out, headerName, headerVal.toString()); 242 } else { 243 Vector v = (Vector )headerVal; 244 for (int i = 0; i < v.size(); i++) { 245 writeHeader(out, headerName, v.elementAt(i).toString()); 246 } 247 } 248 } 249 } 250 251 if (cookies != null) { 252 writeCookies(out); 253 } 254 writeDateHeader(out); 255 out.write(CRLF); 256 } 257 258 static byte[] digits = "0123456789".getBytes(); 259 static byte[] GMTString = " GMT\r\n".getBytes(); 260 261 final void writeDateHeader(WorkerOutputStream out) throws IOException { 262 long now = System.currentTimeMillis(); 263 long msec = now - calbase; 264 if (msec >= 60000) { 265 Calendar c = Calendar.getInstance(GMT); 266 c.setTime(new Date (now)); 267 c.set(Calendar.SECOND, 0); 268 c.set(Calendar.MILLISECOND, 0); 269 Date d = c.getTime(); 270 calbase = d.getTime(); 271 curTime = df.format(d).getBytes(); 272 msec = now - calbase; 273 if (msec < 0) msec = 0; 274 } 275 int sec = (int)(msec / 1000); 276 curTime[29] = digits[sec / 10]; 277 curTime[30] = digits[sec % 10]; 278 out.write(curTime); 279 } 280 281 void writeAttr(WorkerOutputStream out, String name, String val) 282 throws IOException 283 { 284 if (val != null) { 285 out.write(';'); 286 out.write(name); 287 out.write('='); 288 out.write(val); 289 } 290 } 291 292 private static final String tspecials = "()<>@,;:\\\"/[]?={} \t"; 294 295 298 private static boolean isToken (String value) { 299 final int len = value.length(); 300 301 for (int i = 0; i < len; i++) { 302 char c = value.charAt(i); 303 if (c < 0x20 || c >= 0x7f || tspecials.indexOf(c) != -1) 304 return false; 305 } 306 return true; 307 } 308 309 private final void writeTok(WorkerOutputStream out, String val, int v) 310 throws IOException 311 { 312 if (v == 0 || isToken(val)) { 313 out.write(val); 314 } else { 315 out.write('"'); 316 out.write(val); 317 out.write('"'); 318 } 319 } 320 321 void writeCookies(WorkerOutputStream out) throws IOException { 322 out.write("Set-Cookie: "); 323 for (int i = 0; i < cookies.size(); i++) { 324 Cookie cookie = (Cookie )cookies.elementAt(i); 325 final int version = cookie.getVersion(); 326 if (i > 0) out.write('\t'); 327 out.write(cookie.getName()); 328 String val = cookie.getValue(); 329 if (val != null) { 330 out.write('='); 331 writeTok(out, val, version); 332 } 333 334 writeAttr(out, "Path", cookie.getPath()); 335 if (version == 0) { 336 writeAttr(out, "Domain", cookie.getDomain()); 337 if (cookie.getMaxAge() >= 0) { 338 Date d = new Date (); 339 long ms = d.getTime() + cookie.getMaxAge() * 1000; 340 d.setTime(ms); 341 writeAttr(out, "Expires", 342 cookieDateFormat.format(d)); 343 } 344 } else { 345 out.write(";Version=1"); 346 out.write(";Domain="); 347 writeTok(out, cookie.getDomain(), version); 348 if (cookie.getMaxAge() >= 0) { 349 writeAttr(out, "Max-Age", "" + cookie.getMaxAge()); 350 } else { 351 out.write(";Discard"); 352 } 353 writeAttr(out, "Comment", cookie.getComment()); 354 } 355 if (cookie.getSecure()) out.write(";Ssecure"); 356 out.write(CRLF); 357 } 358 } 359 360 final void setFixedHeader(String name, String val) { 361 try { 362 write(fixedH, name); 363 write(fixedH, ": "); 364 write(fixedH, val); 365 fixedH.write(CRLF); 366 } catch (Exception e) {} 367 } 368 369 372 373 378 public void setContentLength(int len) { 379 contentLength = len; 380 } 381 382 final void maybeSetContentLength(int len) { 383 if (contentLength == -1) { 384 contentLength = len; 385 } 386 } 387 388 int getContentLength() { return contentLength; } 389 390 405 public void setContentType(String type) { 406 contentType = type; 407 } 408 409 416 public ServletOutputStream getOutputStream() throws IOException { 417 if (getWriterCalled) { 418 throw new IllegalStateException ("getWriter() already called"); 419 } 420 getOutputStreamCalled = true; 421 return os; 422 } 423 424 438 public PrintWriter getWriter() throws IOException { 439 if (getOutputStreamCalled) { 440 throw new 441 IllegalStateException ("getOutputStream() already called"); 442 } 443 if (writer == null) { 444 String encoding = getCharacterEncoding(); 445 OutputStreamWriter ww = null; 446 OutputStream os = getOutputStream(); 447 if (encoding != null) { 448 ww = new OutputStreamWriter (os, encoding); 449 } else { 450 ww = new OutputStreamWriter (os); 451 } 452 writer = new PrintWriter (ww); 453 getWriterCalled = true; 454 } 455 return writer; 456 } 457 458 public JspWriter getJspWriter(int bufferSize, boolean autoFlush) 459 throws IOException 460 { 461 if (!jWriterInit) { 462 jWriterInit = true; 463 jWriter.setHttpOutputStream(os); 464 jWriter.setBufferSize(bufferSize); 465 jWriter.setAutoFlush(autoFlush); 466 } 467 return jWriter; 468 } 469 470 477 public String getCharacterEncoding () { 478 String s = contentType; 479 if (s == null) return null; 480 481 int idx = s.indexOf(';'); 482 while (idx > 0) { 483 s = s.substring(idx+1).trim(); 484 idx = s.indexOf(';'); 485 String c = s; 486 if (idx > 0) { 487 c = s.substring(0, idx).trim(); 488 } 489 if (c.startsWith("charset=")) { 490 return c.substring(8); 491 } 492 } 493 return null; 494 } 495 496 499 500 501 507 public void addCookie(Cookie cookie) { 508 if (Trace.level() > 7) { 510 Debug.println("addCookie(" + cookie + ")"); 511 } 512 if (cookies == null) { 514 cookies = new Vector (); 515 } 516 cookies.addElement(cookie); 517 } 518 519 527 public boolean containsHeader(String name) { 528 return headers.get(name) != null; 529 } 530 531 542 public void setStatus(int sc, String sm) { 543 this.changedCode = true; 544 this.sc = sc; 545 this.sm = sm; 546 } 547 548 558 public void setStatus(int sc) { 559 this.changedCode = true; 560 this.sc = sc; 561 this.sm = ""; 562 } 563 564 576 public void setHeader(String name, String value) { 577 if (name.charAt(0) == 'C') { 578 if (name.equals("Content-Type")) { 579 contentType = value; 580 return; 581 } else if (name.equals("Content-Length")) { 582 contentLength = Integer.parseInt(value); 583 return; 584 } 585 } 586 if (headerBufValid) { 587 if (headers.get(name) == null) { 588 appendHeader(name, value); 589 } else { 590 headerBufValid = false; 591 } 592 } 593 anyHeaders = true; 594 headers.put(name, value); 595 } 596 597 final void appendHeader(String name, String value) { 598 headerBuf.append(name); 599 headerBuf.append(": "); 600 headerBuf.append(value); 601 headerBuf.append("\r\n"); 602 } 603 604 608 public void addHeader(String name, String value) { 609 Object obj = headers.get(name); 610 Vector v = null; 611 boolean mustInsert = true; 612 if (obj instanceof String ) { 613 v = new Vector (); 614 v.addElement(obj.toString()); 615 } else if (obj == null) { 616 v = new Vector (); 617 } else { 618 v = (Vector )obj; 619 mustInsert = false; 620 } 621 v.addElement(value); 622 if (mustInsert) { 623 anyHeaders = true; 624 headers.put(name, v); 625 } 626 appendHeader(name, value); 627 } 628 629 630 641 public void setIntHeader(String name, int value) { 642 setHeader(name, "" + value); 643 } 644 645 public void addIntHeader(String name, int value) { 646 addHeader(name, "" + value); 647 } 648 649 662 public void setDateHeader(String name, long date) { 663 Date d = new Date (date); 664 setHeader(name, df2.format(d)); 665 } 666 667 public void addDateHeader(String name, long date) { 668 Date d = new Date (date); 669 addHeader(name, df2.format(d)); 670 } 671 672 684 public void sendError(int scode, String msg) throws IOException { 685 setStatus(scode, msg); 686 if (os.discard()) { 687 writer = null; 688 } 689 getWriterCalled = getOutputStreamCalled = false; 690 setContentType("text/html"); 691 PrintWriter p = getWriter(); 692 p.println("<HEAD><TITLE>" + scode + " " + msg + "</TITLE></HEAD>"); 693 p.print("<BODY><H1>"); 694 p.print(msg); 695 p.println("</H1>"); 696 if (scode == HttpServletResponse.SC_NOT_FOUND) { 697 p.print("The requested URL was not found on this server"); 698 p.println("<P>"); 699 } 700 p.println("</BODY>"); 701 flush(); 702 } 703 704 710 public void sendError(int scode) throws IOException { 711 sm = "Error " + scode; 712 setStatus(scode); 713 if (os.discard()) { 714 writer = null; 715 } 716 getWriterCalled = getOutputStreamCalled = false; 717 PrintWriter p = getWriter(); 718 p.println("<html><head><title>" + sm + "</title></head>"); 719 p.println("<body>"); 720 p.println(sm); 721 p.println("</body></html>"); 722 flush(); 723 } 724 725 728 void flush() throws IOException { 729 if (writer != null) writer.flush(); 730 os.flush(); 731 } 732 733 742 public void sendRedirect(String location) throws IOException { 743 setHeader("Location", location); 744 sendError(SC_MOVED_TEMPORARILY, 745 "<a HREF=\"" + location + "\">" + location + "</A>"); 746 } 747 748 764 public String encodeUrl (String url) { 765 return url; 766 } 767 public String encodeURL(String url) { 768 return url; 769 } 770 771 791 public String encodeRedirectUrl (String url) { 792 return url; 793 } 794 public String encodeRedirectURL(String url) { 795 return url; 796 } 797 798 public void flushBuffer() throws IOException { 799 if (writer != null) writer.flush(); 800 os.flushBuffered(); 801 } 802 803 public void setBufferSize(int size) throws IllegalStateException { 804 os.setBufferSize(size); 805 } 806 807 public int getBufferSize() { 808 return os.getBufferSize(); 809 } 810 811 public boolean isCommitted() { 812 return os.isCommitted(); 813 } 814 815 public void reset() throws IllegalStateException { 816 os.reset(); sc = SC_OK; 818 headers.clear(); 819 sm = "Request Completed"; 820 changedCode = false; 821 locale = defaultLocale; 822 contentLength = -1; 823 contentType = null; 824 headerBuf.setLength(0); 825 headerBufValid = true; 826 writer = null; 827 cookies = null; 828 anyHeaders = false; 829 getWriterCalled = false; 830 jWriterInit = false; 831 getOutputStreamCalled = false; 832 } 833 834 public void setLocale(Locale locale) { 835 this.locale = locale; 836 if (locale != null) { 837 String lang = locale.getLanguage(); 838 if (lang != null) { 839 setHeader("Content-Language", lang); 840 } 841 } 842 843 } 844 845 public Locale getLocale() { 846 return locale; 847 } 848 } 849 | Popular Tags |