1 17 18 package org.apache.coyote.http11; 19 20 import java.io.IOException ; 21 import java.io.OutputStream ; 22 import java.security.AccessController ; 23 import java.security.PrivilegedAction ; 24 25 import org.apache.tomcat.util.buf.ByteChunk; 26 import org.apache.tomcat.util.buf.CharChunk; 27 import org.apache.tomcat.util.buf.MessageBytes; 28 import org.apache.tomcat.util.http.HttpMessages; 29 import org.apache.tomcat.util.http.MimeHeaders; 30 import org.apache.tomcat.util.res.StringManager; 31 32 import org.apache.coyote.ActionCode; 33 import org.apache.coyote.OutputBuffer; 34 import org.apache.coyote.Response; 35 36 41 public class InternalOutputBuffer 42 implements OutputBuffer, ByteChunk.ByteOutputChannel { 43 44 46 47 49 50 53 public InternalOutputBuffer(Response response) { 54 this(response, Constants.DEFAULT_HTTP_HEADER_BUFFER_SIZE); 55 } 56 57 58 61 public InternalOutputBuffer(Response response, int headerBufferSize) { 62 63 this.response = response; 64 65 headers = response.getMimeHeaders(); 66 67 buf = new byte[headerBufferSize]; 68 69 outputStreamOutputBuffer = new OutputStreamOutputBuffer(); 70 71 filterLibrary = new OutputFilter[0]; 72 activeFilters = new OutputFilter[0]; 73 lastActiveFilter = -1; 74 75 socketBuffer = new ByteChunk(); 76 socketBuffer.setByteOutputChannel(this); 77 78 committed = false; 79 finished = false; 80 81 } 82 83 84 86 87 90 protected static StringManager sm = 91 StringManager.getManager(Constants.Package); 92 93 94 96 97 100 protected Response response; 101 102 103 106 protected MimeHeaders headers; 107 108 109 112 protected boolean committed; 113 114 115 118 protected boolean finished; 119 120 121 124 protected byte[] buf; 125 126 127 130 protected int pos; 131 132 133 136 protected OutputStream outputStream; 137 138 139 142 protected OutputBuffer outputStreamOutputBuffer; 143 144 145 149 protected OutputFilter[] filterLibrary; 150 151 152 155 protected OutputFilter[] activeFilters; 156 157 158 161 protected int lastActiveFilter; 162 163 164 167 protected ByteChunk socketBuffer; 168 169 170 173 protected boolean useSocketBuffer = false; 174 175 176 178 179 182 public void setOutputStream(OutputStream outputStream) { 183 184 186 this.outputStream = outputStream; 187 188 } 189 190 191 194 public OutputStream getOutputStream() { 195 196 return outputStream; 197 198 } 199 200 201 204 public void setSocketBuffer(int socketBufferSize) { 205 206 if (socketBufferSize > 500) { 207 useSocketBuffer = true; 208 socketBuffer.allocate(socketBufferSize, socketBufferSize); 209 } else { 210 useSocketBuffer = false; 211 } 212 213 } 214 215 216 219 public void addFilter(OutputFilter filter) { 220 221 OutputFilter[] newFilterLibrary = 222 new OutputFilter[filterLibrary.length + 1]; 223 for (int i = 0; i < filterLibrary.length; i++) { 224 newFilterLibrary[i] = filterLibrary[i]; 225 } 226 newFilterLibrary[filterLibrary.length] = filter; 227 filterLibrary = newFilterLibrary; 228 229 activeFilters = new OutputFilter[filterLibrary.length]; 230 231 } 232 233 234 237 public OutputFilter[] getFilters() { 238 239 return filterLibrary; 240 241 } 242 243 244 247 public void clearFilters() { 248 249 filterLibrary = new OutputFilter[0]; 250 lastActiveFilter = -1; 251 252 } 253 254 255 258 public void addActiveFilter(OutputFilter filter) { 259 260 if (lastActiveFilter == -1) { 261 filter.setBuffer(outputStreamOutputBuffer); 262 } else { 263 for (int i = 0; i <= lastActiveFilter; i++) { 264 if (activeFilters[i] == filter) 265 return; 266 } 267 filter.setBuffer(activeFilters[lastActiveFilter]); 268 } 269 270 activeFilters[++lastActiveFilter] = filter; 271 272 filter.setResponse(response); 273 274 } 275 276 277 279 280 285 public void flush() 286 throws IOException { 287 288 if (!committed) { 289 290 response.action(ActionCode.ACTION_COMMIT, null); 294 295 } 296 297 if (useSocketBuffer) { 299 socketBuffer.flushBuffer(); 300 } 301 302 } 303 304 305 310 public void reset() { 311 312 if (committed) 313 throw new IllegalStateException (); 314 315 response.recycle(); 317 318 } 319 320 321 325 public void recycle() { 326 327 response.recycle(); 329 socketBuffer.recycle(); 330 331 outputStream = null; 332 pos = 0; 333 lastActiveFilter = -1; 334 committed = false; 335 finished = false; 336 337 } 338 339 340 346 public void nextRequest() { 347 348 response.recycle(); 350 socketBuffer.recycle(); 351 352 for (int i = 0; i <= lastActiveFilter; i++) { 354 activeFilters[i].recycle(); 355 } 356 357 pos = 0; 359 lastActiveFilter = -1; 360 committed = false; 361 finished = false; 362 363 } 364 365 366 371 public void endRequest() 372 throws IOException { 373 374 if (!committed) { 375 376 response.action(ActionCode.ACTION_COMMIT, null); 380 381 } 382 383 if (finished) 384 return; 385 386 if (lastActiveFilter != -1) 387 activeFilters[lastActiveFilter].end(); 388 389 if (useSocketBuffer) { 390 socketBuffer.flushBuffer(); 391 } 392 393 finished = true; 394 395 } 396 397 398 400 401 404 public void sendAck() 405 throws IOException { 406 407 if (!committed) 408 outputStream.write(Constants.ACK_BYTES); 409 410 } 411 412 413 416 public void sendStatus() { 417 418 write(Constants.HTTP_11_BYTES); 420 buf[pos++] = Constants.SP; 421 422 int status = response.getStatus(); 424 switch (status) { 425 case 200: 426 write(Constants._200_BYTES); 427 break; 428 case 400: 429 write(Constants._400_BYTES); 430 break; 431 case 404: 432 write(Constants._404_BYTES); 433 break; 434 default: 435 write(status); 436 } 437 438 buf[pos++] = Constants.SP; 439 440 String message = response.getMessage(); 442 if (message == null) { 443 write(getMessage(status)); 444 } else { 445 write(message); 446 } 447 448 if (System.getSecurityManager() != null){ 450 AccessController.doPrivileged( 451 new PrivilegedAction (){ 452 public Object run(){ 453 buf[pos++] = Constants.CR; 454 buf[pos++] = Constants.LF; 455 return null; 456 } 457 } 458 ); 459 } else { 460 buf[pos++] = Constants.CR; 461 buf[pos++] = Constants.LF; 462 } 463 464 } 465 466 private String getMessage(final int message){ 467 if (System.getSecurityManager() != null){ 468 return (String )AccessController.doPrivileged( 469 new PrivilegedAction (){ 470 public Object run(){ 471 return HttpMessages.getMessage(message); 472 } 473 } 474 ); 475 } else { 476 return HttpMessages.getMessage(message); 477 } 478 } 479 480 486 public void sendHeader(MessageBytes name, MessageBytes value) { 487 488 write(name); 489 buf[pos++] = Constants.COLON; 490 buf[pos++] = Constants.SP; 491 write(value); 492 buf[pos++] = Constants.CR; 493 buf[pos++] = Constants.LF; 494 495 } 496 497 498 504 public void sendHeader(ByteChunk name, ByteChunk value) { 505 506 write(name); 507 buf[pos++] = Constants.COLON; 508 buf[pos++] = Constants.SP; 509 write(value); 510 buf[pos++] = Constants.CR; 511 buf[pos++] = Constants.LF; 512 513 } 514 515 516 522 public void sendHeader(String name, String value) { 523 524 write(name); 525 buf[pos++] = Constants.COLON; 526 buf[pos++] = Constants.SP; 527 write(value); 528 buf[pos++] = Constants.CR; 529 buf[pos++] = Constants.LF; 530 531 } 532 533 534 537 public void endHeaders() { 538 539 buf[pos++] = Constants.CR; 540 buf[pos++] = Constants.LF; 541 542 } 543 544 545 547 548 555 public int doWrite(ByteChunk chunk, Response res) 556 throws IOException { 557 558 if (!committed) { 559 560 response.action(ActionCode.ACTION_COMMIT, null); 564 565 } 566 567 if (lastActiveFilter == -1) 568 return outputStreamOutputBuffer.doWrite(chunk, res); 569 else 570 return activeFilters[lastActiveFilter].doWrite(chunk, res); 571 572 } 573 574 575 577 578 583 protected void commit() 584 throws IOException { 585 586 committed = true; 588 response.setCommitted(true); 589 590 if (pos > 0) { 591 if (useSocketBuffer) { 593 socketBuffer.append(buf, 0, pos); 594 } else { 595 outputStream.write(buf, 0, pos); 596 } 597 } 598 599 } 600 601 602 609 protected void write(MessageBytes mb) { 610 611 if (mb.getType() == MessageBytes.T_BYTES) { 612 ByteChunk bc = mb.getByteChunk(); 613 write(bc); 614 } else if (mb.getType() == MessageBytes.T_CHARS) { 615 CharChunk cc = mb.getCharChunk(); 616 write(cc); 617 } else { 618 write(mb.toString()); 619 } 620 621 } 622 623 624 631 protected void write(ByteChunk bc) { 632 633 System.arraycopy(bc.getBytes(), bc.getStart(), buf, pos, 635 bc.getLength()); 636 pos = pos + bc.getLength(); 637 638 } 639 640 641 648 protected void write(CharChunk cc) { 649 650 int start = cc.getStart(); 651 int end = cc.getEnd(); 652 char[] cbuf = cc.getBuffer(); 653 for (int i = start; i < end; i++) { 654 char c = cbuf[i]; 655 if ((c <= 31) && (c != 9)) { 660 c = ' '; 661 } else if (c == 127) { 662 c = ' '; 663 } 664 buf[pos++] = (byte) c; 665 } 666 667 } 668 669 670 677 public void write(byte[] b) { 678 679 System.arraycopy(b, 0, buf, pos, b.length); 681 pos = pos + b.length; 682 683 } 684 685 686 693 protected void write(String s) { 694 695 if (s == null) 696 return; 697 698 int len = s.length(); 700 for (int i = 0; i < len; i++) { 701 char c = s.charAt (i); 702 if ((c <= 31) && (c != 9)) { 707 c = ' '; 708 } else if (c == 127) { 709 c = ' '; 710 } 711 buf[pos++] = (byte) c; 712 } 713 714 } 715 716 717 724 protected void write(int i) { 725 726 write(String.valueOf(i)); 727 728 } 729 730 731 734 public void realWriteBytes(byte cbuf[], int off, int len) 735 throws IOException { 736 if (len > 0) { 737 outputStream.write(cbuf, off, len); 738 } 739 } 740 741 742 744 745 749 protected class OutputStreamOutputBuffer 750 implements OutputBuffer { 751 752 753 756 public int doWrite(ByteChunk chunk, Response res) 757 throws IOException { 758 759 if (useSocketBuffer) { 760 socketBuffer.append(chunk.getBuffer(), chunk.getStart(), 761 chunk.getLength()); 762 } else { 763 outputStream.write(chunk.getBuffer(), chunk.getStart(), 764 chunk.getLength()); 765 } 766 return chunk.getLength(); 767 768 } 769 770 771 } 772 773 774 } 775 | Popular Tags |