1 17 18 package org.apache.coyote.http11; 19 20 import java.io.EOFException ; 21 import java.io.IOException ; 22 import java.nio.ByteBuffer ; 23 import java.nio.channels.SelectionKey ; 24 import java.nio.channels.Selector ; 25 26 import org.apache.coyote.ActionCode; 27 import org.apache.coyote.OutputBuffer; 28 import org.apache.coyote.Response; 29 import org.apache.tomcat.util.buf.ByteChunk; 30 import org.apache.tomcat.util.buf.CharChunk; 31 import org.apache.tomcat.util.buf.MessageBytes; 32 import org.apache.tomcat.util.http.HttpMessages; 33 import org.apache.tomcat.util.http.MimeHeaders; 34 import org.apache.tomcat.util.net.NioChannel; 35 import org.apache.tomcat.util.net.NioEndpoint; 36 import org.apache.tomcat.util.net.NioSelectorPool; 37 import org.apache.tomcat.util.res.StringManager; 38 39 45 public class InternalNioOutputBuffer 46 implements OutputBuffer { 47 48 49 51 52 int bbufLimit = 0; 54 55 56 59 public InternalNioOutputBuffer(Response response) { 60 this(response, Constants.DEFAULT_HTTP_HEADER_BUFFER_SIZE, 10000); 61 } 62 63 64 67 public InternalNioOutputBuffer(Response response, int headerBufferSize, long writeTimeout) { 68 69 this.response = response; 70 headers = response.getMimeHeaders(); 71 72 buf = new byte[headerBufferSize]; 73 74 if (headerBufferSize < (8 * 1024)) { 75 bbufLimit = 6 * 1500; 76 } else { 77 bbufLimit = (headerBufferSize / 1500 + 1) * 1500; 78 } 79 81 outputStreamOutputBuffer = new SocketOutputBuffer(); 82 83 filterLibrary = new OutputFilter[0]; 84 activeFilters = new OutputFilter[0]; 85 lastActiveFilter = -1; 86 87 committed = false; 88 finished = false; 89 90 this.writeTimeout = writeTimeout; 91 92 HttpMessages.getMessage(200); 94 95 } 96 97 98 100 101 104 protected static StringManager sm = 105 StringManager.getManager(Constants.Package); 106 107 108 110 111 114 protected Response response; 115 116 117 120 protected MimeHeaders headers; 121 122 123 126 protected boolean committed; 127 128 129 132 protected boolean finished; 133 134 135 138 protected byte[] buf; 139 140 141 144 protected int pos; 145 146 147 150 protected NioChannel socket; 151 152 155 protected NioSelectorPool pool; 156 157 158 159 162 protected OutputBuffer outputStreamOutputBuffer; 163 164 165 169 protected OutputFilter[] filterLibrary; 170 171 172 175 protected OutputFilter[] activeFilters; 176 177 178 181 protected int lastActiveFilter; 182 183 186 protected long writeTimeout = -1; 187 188 189 191 192 195 public void setSocket(NioChannel socket) { 196 this.socket = socket; 197 } 198 199 public void setWriteTimeout(long writeTimeout) { 200 this.writeTimeout = writeTimeout; 201 } 202 203 206 public NioChannel getSocket() { 207 return socket; 208 } 209 210 public long getWriteTimeout() { 211 return writeTimeout; 212 } 213 214 public void setSelectorPool(NioSelectorPool pool) { 215 this.pool = pool; 216 } 217 218 public NioSelectorPool getSelectorPool() { 219 return pool; 220 } 221 224 public void setSocketBuffer(int socketBufferSize) { 225 } 227 228 229 232 public void addFilter(OutputFilter filter) { 233 234 OutputFilter[] newFilterLibrary = 235 new OutputFilter[filterLibrary.length + 1]; 236 for (int i = 0; i < filterLibrary.length; i++) { 237 newFilterLibrary[i] = filterLibrary[i]; 238 } 239 newFilterLibrary[filterLibrary.length] = filter; 240 filterLibrary = newFilterLibrary; 241 242 activeFilters = new OutputFilter[filterLibrary.length]; 243 244 } 245 246 247 250 public OutputFilter[] getFilters() { 251 252 return filterLibrary; 253 254 } 255 256 257 260 public void clearFilters() { 261 262 filterLibrary = new OutputFilter[0]; 263 lastActiveFilter = -1; 264 265 } 266 267 268 271 public void addActiveFilter(OutputFilter filter) { 272 273 if (lastActiveFilter == -1) { 274 filter.setBuffer(outputStreamOutputBuffer); 275 } else { 276 for (int i = 0; i <= lastActiveFilter; i++) { 277 if (activeFilters[i] == filter) 278 return; 279 } 280 filter.setBuffer(activeFilters[lastActiveFilter]); 281 } 282 283 activeFilters[++lastActiveFilter] = filter; 284 285 filter.setResponse(response); 286 287 } 288 289 290 292 293 298 public void flush() 299 throws IOException { 300 301 if (!committed) { 302 303 response.action(ActionCode.ACTION_COMMIT, null); 307 308 } 309 310 flushBuffer(); 312 313 } 314 315 316 321 public void reset() { 322 323 if (committed) 324 throw new IllegalStateException (); 325 326 response.recycle(); 328 329 } 330 331 332 336 public void recycle() { 337 338 response.recycle(); 340 socket.getBufHandler().getWriteBuffer().clear(); 341 342 socket = null; 343 pos = 0; 344 lastActiveFilter = -1; 345 committed = false; 346 finished = false; 347 348 } 349 350 351 357 public void nextRequest() { 358 359 response.recycle(); 361 362 for (int i = 0; i <= lastActiveFilter; i++) { 364 activeFilters[i].recycle(); 365 } 366 367 pos = 0; 369 lastActiveFilter = -1; 370 committed = false; 371 finished = false; 372 373 } 374 375 376 381 public void endRequest() 382 throws IOException { 383 384 if (!committed) { 385 386 response.action(ActionCode.ACTION_COMMIT, null); 390 391 } 392 393 if (finished) 394 return; 395 396 if (lastActiveFilter != -1) 397 activeFilters[lastActiveFilter].end(); 398 399 flushBuffer(); 400 401 finished = true; 402 403 } 404 405 406 408 409 412 public void sendAck() 413 throws IOException { 414 415 if (!committed) { 416 ByteBuffer buf = ByteBuffer.wrap(Constants.ACK_BYTES,0,Constants.ACK_BYTES.length); 418 writeToSocket(buf,false); 419 } 420 421 } 422 423 private synchronized void writeToSocket(ByteBuffer bytebuffer, boolean flip) throws IOException { 424 if ( flip ) bytebuffer.flip(); 426 int written = 0; 427 Selector selector = null; 428 try { 429 selector = getSelectorPool().get(); 430 } catch ( IOException x ) { 431 } 433 try { 434 written = getSelectorPool().write(bytebuffer, socket, selector, writeTimeout); 435 do { 437 if (socket.flush(selector)) break; 438 }while ( true ); 439 }finally { 440 if ( selector != null ) getSelectorPool().put(selector); 441 } 442 socket.getBufHandler().getWriteBuffer().clear(); 443 this.total = 0; 444 } 445 446 447 450 public void sendStatus() { 451 452 write(Constants.HTTP_11_BYTES); 454 buf[pos++] = Constants.SP; 455 456 int status = response.getStatus(); 458 switch (status) { 459 case 200: 460 write(Constants._200_BYTES); 461 break; 462 case 400: 463 write(Constants._400_BYTES); 464 break; 465 case 404: 466 write(Constants._404_BYTES); 467 break; 468 default: 469 write(status); 470 } 471 472 buf[pos++] = Constants.SP; 473 474 String message = response.getMessage(); 476 if (message == null) { 477 write(HttpMessages.getMessage(status)); 478 } else { 479 write(message); 480 } 481 482 buf[pos++] = Constants.CR; 484 buf[pos++] = Constants.LF; 485 486 } 487 488 489 495 public void sendHeader(MessageBytes name, MessageBytes value) { 496 497 write(name); 498 buf[pos++] = Constants.COLON; 499 buf[pos++] = Constants.SP; 500 write(value); 501 buf[pos++] = Constants.CR; 502 buf[pos++] = Constants.LF; 503 504 } 505 506 507 513 public void sendHeader(ByteChunk name, ByteChunk value) { 514 515 write(name); 516 buf[pos++] = Constants.COLON; 517 buf[pos++] = Constants.SP; 518 write(value); 519 buf[pos++] = Constants.CR; 520 buf[pos++] = Constants.LF; 521 522 } 523 524 525 531 public void sendHeader(String name, String value) { 532 533 write(name); 534 buf[pos++] = Constants.COLON; 535 buf[pos++] = Constants.SP; 536 write(value); 537 buf[pos++] = Constants.CR; 538 buf[pos++] = Constants.LF; 539 540 } 541 542 543 546 public void endHeaders() { 547 548 buf[pos++] = Constants.CR; 549 buf[pos++] = Constants.LF; 550 551 } 552 553 554 556 557 564 public int doWrite(ByteChunk chunk, Response res) 565 throws IOException { 566 567 if (!committed) { 568 569 response.action(ActionCode.ACTION_COMMIT, null); 573 574 } 575 576 if (lastActiveFilter == -1) 577 return outputStreamOutputBuffer.doWrite(chunk, res); 578 else 579 return activeFilters[lastActiveFilter].doWrite(chunk, res); 580 581 } 582 583 584 586 587 592 protected void commit() 593 throws IOException { 594 595 committed = true; 597 response.setCommitted(true); 598 599 if (pos > 0) { 600 addToBB(buf, 0, pos); 602 } 603 604 } 605 606 int total = 0; 607 private void addToBB(byte[] buf, int offset, int length) throws IOException { 608 if (socket.getBufHandler().getWriteBuffer().remaining() < length) { 609 flushBuffer(); 610 } 611 socket.getBufHandler().getWriteBuffer().put(buf, offset, length); 612 total += length; 613 } 614 615 616 623 protected void write(MessageBytes mb) { 624 625 if (mb.getType() == MessageBytes.T_BYTES) { 626 ByteChunk bc = mb.getByteChunk(); 627 write(bc); 628 } else if (mb.getType() == MessageBytes.T_CHARS) { 629 CharChunk cc = mb.getCharChunk(); 630 write(cc); 631 } else { 632 write(mb.toString()); 633 } 634 635 } 636 637 638 645 protected void write(ByteChunk bc) { 646 647 System.arraycopy(bc.getBytes(), bc.getStart(), buf, pos, 649 bc.getLength()); 650 pos = pos + bc.getLength(); 651 652 } 653 654 655 662 protected void write(CharChunk cc) { 663 664 int start = cc.getStart(); 665 int end = cc.getEnd(); 666 char[] cbuf = cc.getBuffer(); 667 for (int i = start; i < end; i++) { 668 char c = cbuf[i]; 669 if ((c <= 31) && (c != 9)) { 674 c = ' '; 675 } else if (c == 127) { 676 c = ' '; 677 } 678 buf[pos++] = (byte) c; 679 } 680 681 } 682 683 684 691 public void write(byte[] b) { 692 693 System.arraycopy(b, 0, buf, pos, b.length); 695 pos = pos + b.length; 696 697 } 698 699 700 707 protected void write(String s) { 708 709 if (s == null) 710 return; 711 712 int len = s.length(); 714 for (int i = 0; i < len; i++) { 715 char c = s.charAt (i); 716 if ((c <= 31) && (c != 9)) { 721 c = ' '; 722 } else if (c == 127) { 723 c = ' '; 724 } 725 buf[pos++] = (byte) c; 726 } 727 728 } 729 730 731 738 protected void write(int i) { 739 740 write(String.valueOf(i)); 741 742 } 743 744 745 748 protected void flushBuffer() 749 throws IOException { 750 751 SelectionKey key = socket.getIOChannel().keyFor(socket.getPoller().getSelector()); 753 if (key != null) { 754 NioEndpoint.KeyAttachment attach = (NioEndpoint.KeyAttachment) key.attachment(); 755 attach.access(); 756 } 757 758 if (socket.getBufHandler().getWriteBuffer().position() > 0) { 760 writeToSocket(socket.getBufHandler().getWriteBuffer(),true); 761 } 762 } 763 764 765 767 768 772 protected class SocketOutputBuffer 773 implements OutputBuffer { 774 775 776 779 public int doWrite(ByteChunk chunk, Response res) 780 throws IOException { 781 782 int len = chunk.getLength(); 783 int start = chunk.getStart(); 784 byte[] b = chunk.getBuffer(); 785 while (len > 0) { 786 int thisTime = len; 787 if (socket.getBufHandler().getWriteBuffer().position() == socket.getBufHandler().getWriteBuffer().capacity()) { 788 flushBuffer(); 789 } 790 if (thisTime > socket.getBufHandler().getWriteBuffer().capacity() - socket.getBufHandler().getWriteBuffer().position()) { 791 thisTime = socket.getBufHandler().getWriteBuffer().capacity() - socket.getBufHandler().getWriteBuffer().position(); 792 } 793 addToBB(b,start,thisTime); 794 len = len - thisTime; 795 start = start + thisTime; 796 } 797 return chunk.getLength(); 798 799 } 800 801 802 } 803 804 805 } 806 | Popular Tags |