1 17 18 package org.apache.coyote.http11; 19 20 import java.io.IOException ; 21 import java.nio.ByteBuffer ; 22 23 import org.apache.tomcat.jni.Socket; 24 import org.apache.tomcat.util.buf.ByteChunk; 25 import org.apache.tomcat.util.buf.CharChunk; 26 import org.apache.tomcat.util.buf.MessageBytes; 27 import org.apache.tomcat.util.http.HttpMessages; 28 import org.apache.tomcat.util.http.MimeHeaders; 29 import org.apache.tomcat.util.res.StringManager; 30 31 import org.apache.coyote.ActionCode; 32 import org.apache.coyote.OutputBuffer; 33 import org.apache.coyote.Response; 34 35 40 public class InternalAprOutputBuffer 41 implements OutputBuffer { 42 43 44 46 47 49 50 53 public InternalAprOutputBuffer(Response response) { 54 this(response, Constants.DEFAULT_HTTP_HEADER_BUFFER_SIZE); 55 } 56 57 58 61 public InternalAprOutputBuffer(Response response, int headerBufferSize) { 62 63 this.response = response; 64 headers = response.getMimeHeaders(); 65 66 buf = new byte[headerBufferSize]; 67 if (headerBufferSize < (8 * 1024)) { 68 bbuf = ByteBuffer.allocateDirect(6 * 1500); 69 } else { 70 bbuf = ByteBuffer.allocateDirect((headerBufferSize / 1500 + 1) * 1500); 71 } 72 73 outputStreamOutputBuffer = new SocketOutputBuffer(); 74 75 filterLibrary = new OutputFilter[0]; 76 activeFilters = new OutputFilter[0]; 77 lastActiveFilter = -1; 78 79 committed = false; 80 finished = false; 81 82 HttpMessages.getMessage(200); 84 85 } 86 87 88 90 91 94 protected static StringManager sm = 95 StringManager.getManager(Constants.Package); 96 97 98 100 101 104 protected Response response; 105 106 107 110 protected MimeHeaders headers; 111 112 113 116 protected boolean committed; 117 118 119 122 protected boolean finished; 123 124 125 128 protected byte[] buf; 129 130 131 134 protected int pos; 135 136 137 140 protected long socket; 141 142 143 146 protected OutputBuffer outputStreamOutputBuffer; 147 148 149 153 protected OutputFilter[] filterLibrary; 154 155 156 159 protected OutputFilter[] activeFilters; 160 161 162 165 protected int lastActiveFilter; 166 167 168 171 protected ByteBuffer bbuf = null; 172 173 174 176 177 180 public void setSocket(long socket) { 181 this.socket = socket; 182 Socket.setsbb(this.socket, bbuf); 183 } 184 185 186 189 public long getSocket() { 190 return socket; 191 } 192 193 194 197 public void setSocketBuffer(int socketBufferSize) { 198 } 200 201 202 205 public void addFilter(OutputFilter filter) { 206 207 OutputFilter[] newFilterLibrary = 208 new OutputFilter[filterLibrary.length + 1]; 209 for (int i = 0; i < filterLibrary.length; i++) { 210 newFilterLibrary[i] = filterLibrary[i]; 211 } 212 newFilterLibrary[filterLibrary.length] = filter; 213 filterLibrary = newFilterLibrary; 214 215 activeFilters = new OutputFilter[filterLibrary.length]; 216 217 } 218 219 220 223 public OutputFilter[] getFilters() { 224 225 return filterLibrary; 226 227 } 228 229 230 233 public void clearFilters() { 234 235 filterLibrary = new OutputFilter[0]; 236 lastActiveFilter = -1; 237 238 } 239 240 241 244 public void addActiveFilter(OutputFilter filter) { 245 246 if (lastActiveFilter == -1) { 247 filter.setBuffer(outputStreamOutputBuffer); 248 } else { 249 for (int i = 0; i <= lastActiveFilter; i++) { 250 if (activeFilters[i] == filter) 251 return; 252 } 253 filter.setBuffer(activeFilters[lastActiveFilter]); 254 } 255 256 activeFilters[++lastActiveFilter] = filter; 257 258 filter.setResponse(response); 259 260 } 261 262 263 265 266 271 public void flush() 272 throws IOException { 273 274 if (!committed) { 275 276 response.action(ActionCode.ACTION_COMMIT, null); 280 281 } 282 283 flushBuffer(); 285 286 } 287 288 289 294 public void reset() { 295 296 if (committed) 297 throw new IllegalStateException (); 298 299 response.recycle(); 301 302 } 303 304 305 309 public void recycle() { 310 311 response.recycle(); 313 bbuf.clear(); 314 315 socket = 0; 316 pos = 0; 317 lastActiveFilter = -1; 318 committed = false; 319 finished = false; 320 321 } 322 323 324 330 public void nextRequest() { 331 332 response.recycle(); 334 335 for (int i = 0; i <= lastActiveFilter; i++) { 337 activeFilters[i].recycle(); 338 } 339 340 pos = 0; 342 lastActiveFilter = -1; 343 committed = false; 344 finished = false; 345 346 } 347 348 349 354 public void endRequest() 355 throws IOException { 356 357 if (!committed) { 358 359 response.action(ActionCode.ACTION_COMMIT, null); 363 364 } 365 366 if (finished) 367 return; 368 369 if (lastActiveFilter != -1) 370 activeFilters[lastActiveFilter].end(); 371 372 flushBuffer(); 373 374 finished = true; 375 376 } 377 378 379 381 382 385 public void sendAck() 386 throws IOException { 387 388 if (!committed) { 389 if (Socket.send(socket, Constants.ACK_BYTES, 0, Constants.ACK_BYTES.length) < 0) 390 throw new IOException (sm.getString("iib.failedwrite")); 391 } 392 393 } 394 395 396 399 public void sendStatus() { 400 401 write(Constants.HTTP_11_BYTES); 403 buf[pos++] = Constants.SP; 404 405 int status = response.getStatus(); 407 switch (status) { 408 case 200: 409 write(Constants._200_BYTES); 410 break; 411 case 400: 412 write(Constants._400_BYTES); 413 break; 414 case 404: 415 write(Constants._404_BYTES); 416 break; 417 default: 418 write(status); 419 } 420 421 buf[pos++] = Constants.SP; 422 423 String message = response.getMessage(); 425 if (message == null) { 426 write(HttpMessages.getMessage(status)); 427 } else { 428 write(message); 429 } 430 431 buf[pos++] = Constants.CR; 433 buf[pos++] = Constants.LF; 434 435 } 436 437 438 444 public void sendHeader(MessageBytes name, MessageBytes value) { 445 446 write(name); 447 buf[pos++] = Constants.COLON; 448 buf[pos++] = Constants.SP; 449 write(value); 450 buf[pos++] = Constants.CR; 451 buf[pos++] = Constants.LF; 452 453 } 454 455 456 462 public void sendHeader(ByteChunk name, ByteChunk value) { 463 464 write(name); 465 buf[pos++] = Constants.COLON; 466 buf[pos++] = Constants.SP; 467 write(value); 468 buf[pos++] = Constants.CR; 469 buf[pos++] = Constants.LF; 470 471 } 472 473 474 480 public void sendHeader(String name, String value) { 481 482 write(name); 483 buf[pos++] = Constants.COLON; 484 buf[pos++] = Constants.SP; 485 write(value); 486 buf[pos++] = Constants.CR; 487 buf[pos++] = Constants.LF; 488 489 } 490 491 492 495 public void endHeaders() { 496 497 buf[pos++] = Constants.CR; 498 buf[pos++] = Constants.LF; 499 500 } 501 502 503 505 506 513 public int doWrite(ByteChunk chunk, Response res) 514 throws IOException { 515 516 if (!committed) { 517 518 response.action(ActionCode.ACTION_COMMIT, null); 522 523 } 524 525 if (lastActiveFilter == -1) 526 return outputStreamOutputBuffer.doWrite(chunk, res); 527 else 528 return activeFilters[lastActiveFilter].doWrite(chunk, res); 529 530 } 531 532 533 535 536 541 protected void commit() 542 throws IOException { 543 544 committed = true; 546 response.setCommitted(true); 547 548 if (pos > 0) { 549 bbuf.put(buf, 0, pos); 551 } 552 553 } 554 555 556 563 protected void write(MessageBytes mb) { 564 565 if (mb.getType() == MessageBytes.T_BYTES) { 566 ByteChunk bc = mb.getByteChunk(); 567 write(bc); 568 } else if (mb.getType() == MessageBytes.T_CHARS) { 569 CharChunk cc = mb.getCharChunk(); 570 write(cc); 571 } else { 572 write(mb.toString()); 573 } 574 575 } 576 577 578 585 protected void write(ByteChunk bc) { 586 587 System.arraycopy(bc.getBytes(), bc.getStart(), buf, pos, 589 bc.getLength()); 590 pos = pos + bc.getLength(); 591 592 } 593 594 595 602 protected void write(CharChunk cc) { 603 604 int start = cc.getStart(); 605 int end = cc.getEnd(); 606 char[] cbuf = cc.getBuffer(); 607 for (int i = start; i < end; i++) { 608 char c = cbuf[i]; 609 if ((c <= 31) && (c != 9)) { 614 c = ' '; 615 } else if (c == 127) { 616 c = ' '; 617 } 618 buf[pos++] = (byte) c; 619 } 620 621 } 622 623 624 631 public void write(byte[] b) { 632 633 System.arraycopy(b, 0, buf, pos, b.length); 635 pos = pos + b.length; 636 637 } 638 639 640 647 protected void write(String s) { 648 649 if (s == null) 650 return; 651 652 int len = s.length(); 654 for (int i = 0; i < len; i++) { 655 char c = s.charAt (i); 656 if ((c <= 31) && (c != 9)) { 661 c = ' '; 662 } else if (c == 127) { 663 c = ' '; 664 } 665 buf[pos++] = (byte) c; 666 } 667 668 } 669 670 671 678 protected void write(int i) { 679 680 write(String.valueOf(i)); 681 682 } 683 684 685 688 protected void flushBuffer() 689 throws IOException { 690 if (bbuf.position() > 0) { 691 if (Socket.sendbb(socket, 0, bbuf.position()) < 0) { 692 throw new IOException (); 693 } 694 bbuf.clear(); 695 } 696 } 697 698 699 701 702 706 protected class SocketOutputBuffer 707 implements OutputBuffer { 708 709 710 713 public int doWrite(ByteChunk chunk, Response res) 714 throws IOException { 715 716 int len = chunk.getLength(); 717 int start = chunk.getStart(); 718 byte[] b = chunk.getBuffer(); 719 while (len > 0) { 720 int thisTime = len; 721 if (bbuf.position() == bbuf.capacity()) { 722 flushBuffer(); 723 } 724 if (thisTime > bbuf.capacity() - bbuf.position()) { 725 thisTime = bbuf.capacity() - bbuf.position(); 726 } 727 bbuf.put(b, start, thisTime); 728 len = len - thisTime; 729 start = start + thisTime; 730 } 731 return chunk.getLength(); 732 733 } 734 735 736 } 737 738 739 } 740 | Popular Tags |