1 17 18 package org.apache.catalina.connector; 19 20 21 import java.io.IOException ; 22 import java.io.Writer ; 23 import java.security.AccessController ; 24 import java.security.PrivilegedActionException ; 25 import java.security.PrivilegedExceptionAction ; 26 import java.util.HashMap ; 27 28 import org.apache.coyote.ActionCode; 29 import org.apache.coyote.Response; 30 import org.apache.tomcat.util.buf.ByteChunk; 31 import org.apache.tomcat.util.buf.C2BConverter; 32 33 34 42 public class OutputBuffer extends Writer 43 implements ByteChunk.ByteOutputChannel { 44 45 46 48 49 public static final String DEFAULT_ENCODING = 50 org.apache.coyote.Constants.DEFAULT_CHARACTER_ENCODING; 51 public static final int DEFAULT_BUFFER_SIZE = 8*1024; 52 53 54 56 57 60 private ByteChunk bb; 61 62 63 66 private boolean initial = true; 67 68 69 72 private int bytesWritten = 0; 73 74 75 78 private int charsWritten = 0; 79 80 81 84 private boolean closed = false; 85 86 87 90 private boolean doFlush = false; 91 92 93 96 private ByteChunk outputChunk = new ByteChunk(); 97 98 99 102 private String enc; 103 104 105 108 private boolean gotEnc = false; 109 110 111 114 protected HashMap encoders = new HashMap (); 115 116 117 120 protected C2BConverter conv; 121 122 123 126 private Response coyoteResponse; 127 128 129 132 private boolean suspended = false; 133 134 135 137 138 141 public OutputBuffer() { 142 143 this(DEFAULT_BUFFER_SIZE); 144 145 } 146 147 148 153 public OutputBuffer(int size) { 154 155 bb = new ByteChunk(size); 156 bb.setLimit(size); 157 bb.setByteOutputChannel(this); 158 159 } 160 161 162 164 165 170 public void setResponse(Response coyoteResponse) { 171 this.coyoteResponse = coyoteResponse; 172 } 173 174 175 180 public Response getResponse() { 181 return this.coyoteResponse; 182 } 183 184 185 190 public boolean isSuspended() { 191 return this.suspended; 192 } 193 194 195 200 public void setSuspended(boolean suspended) { 201 this.suspended = suspended; 202 } 203 204 205 210 public boolean isClosed() { 211 return this.closed; 212 } 213 214 215 217 218 221 public void recycle() { 222 223 initial = true; 224 bytesWritten = 0; 225 charsWritten = 0; 226 227 bb.recycle(); 228 closed = false; 229 suspended = false; 230 231 if (conv!= null) { 232 conv.recycle(); 233 } 234 235 gotEnc = false; 236 enc = null; 237 238 } 239 240 241 244 public void clearEncoders() { 245 encoders.clear(); 246 } 247 248 249 255 public void close() 256 throws IOException { 257 258 if (closed) 259 return; 260 if (suspended) 261 return; 262 263 if ((!coyoteResponse.isCommitted()) 264 && (coyoteResponse.getContentLengthLong() == -1)) { 265 if (!coyoteResponse.isCommitted()) { 268 coyoteResponse.setContentLength(bb.getLength()); 269 } 270 } 271 272 doFlush(false); 273 closed = true; 274 275 coyoteResponse.finish(); 276 277 } 278 279 280 285 public void flush() 286 throws IOException { 287 doFlush(true); 288 } 289 290 291 296 protected void doFlush(boolean realFlush) 297 throws IOException { 298 299 if (suspended) 300 return; 301 302 doFlush = true; 303 if (initial) { 304 coyoteResponse.sendHeaders(); 305 initial = false; 306 } 307 if (bb.getLength() > 0) { 308 bb.flushBuffer(); 309 } 310 doFlush = false; 311 312 if (realFlush) { 313 coyoteResponse.action(ActionCode.ACTION_CLIENT_FLUSH, 314 coyoteResponse); 315 if (coyoteResponse.isExceptionPresent()) { 318 throw new ClientAbortException 319 (coyoteResponse.getErrorException()); 320 } 321 } 322 323 } 324 325 326 328 329 339 public void realWriteBytes(byte buf[], int off, int cnt) 340 throws IOException { 341 342 if (closed) 343 return; 344 if (coyoteResponse == null) 345 return; 346 347 if (cnt > 0) { 349 outputChunk.setBytes(buf, off, cnt); 351 try { 352 coyoteResponse.doWrite(outputChunk); 353 } catch (IOException e) { 354 throw new ClientAbortException(e); 358 } 359 } 360 361 } 362 363 364 public void write(byte b[], int off, int len) throws IOException { 365 366 if (suspended) 367 return; 368 369 writeBytes(b, off, len); 370 371 } 372 373 374 private void writeBytes(byte b[], int off, int len) 375 throws IOException { 376 377 if (closed) 378 return; 379 380 bb.append(b, off, len); 381 bytesWritten += len; 382 383 if (doFlush) { 386 bb.flushBuffer(); 387 } 388 389 } 390 391 392 public void writeByte(int b) 393 throws IOException { 394 395 if (suspended) 396 return; 397 398 bb.append((byte) b); 399 bytesWritten++; 400 401 } 402 403 404 406 407 public void write(int c) 408 throws IOException { 409 410 if (suspended) 411 return; 412 413 conv.convert((char) c); 414 conv.flushBuffer(); 415 charsWritten++; 416 417 } 418 419 420 public void write(char c[]) 421 throws IOException { 422 423 if (suspended) 424 return; 425 426 write(c, 0, c.length); 427 428 } 429 430 431 public void write(char c[], int off, int len) 432 throws IOException { 433 434 if (suspended) 435 return; 436 437 conv.convert(c, off, len); 438 conv.flushBuffer(); 439 charsWritten += len; 440 441 } 442 443 444 447 public void write(String s, int off, int len) 448 throws IOException { 449 450 if (suspended) 451 return; 452 453 charsWritten += len; 454 if (s == null) 455 s = "null"; 456 conv.convert(s, off, len); 457 conv.flushBuffer(); 458 459 } 460 461 462 public void write(String s) 463 throws IOException { 464 465 if (suspended) 466 return; 467 468 if (s == null) 469 s = "null"; 470 conv.convert(s); 471 conv.flushBuffer(); 472 473 } 474 475 476 public void setEncoding(String s) { 477 enc = s; 478 } 479 480 481 public void checkConverter() 482 throws IOException { 483 484 if (!gotEnc) 485 setConverter(); 486 487 } 488 489 490 protected void setConverter() 491 throws IOException { 492 493 if (coyoteResponse != null) 494 enc = coyoteResponse.getCharacterEncoding(); 495 496 gotEnc = true; 497 if (enc == null) 498 enc = DEFAULT_ENCODING; 499 conv = (C2BConverter) encoders.get(enc); 500 if (conv == null) { 501 502 if (System.getSecurityManager() != null){ 503 try{ 504 conv = (C2BConverter)AccessController.doPrivileged( 505 new PrivilegedExceptionAction (){ 506 507 public Object run() throws IOException { 508 return new C2BConverter(bb, enc); 509 } 510 511 } 512 ); 513 }catch(PrivilegedActionException ex){ 514 Exception e = ex.getException(); 515 if (e instanceof IOException ) 516 throw (IOException )e; 517 } 518 } else { 519 conv = new C2BConverter(bb, enc); 520 } 521 522 encoders.put(enc, conv); 523 524 } 525 } 526 527 528 530 531 534 public void flushBytes() 535 throws IOException { 536 537 bb.flushBuffer(); 538 539 } 540 541 542 public int getBytesWritten() { 543 return bytesWritten; 544 } 545 546 547 public int getCharsWritten() { 548 return charsWritten; 549 } 550 551 552 public int getContentWritten() { 553 return bytesWritten + charsWritten; 554 } 555 556 557 561 public boolean isNew() { 562 return (bytesWritten == 0) && (charsWritten == 0); 563 } 564 565 566 public void setBufferSize(int size) { 567 if (size > bb.getLimit()) { bb.setLimit(size); 569 } 570 } 571 572 573 public void reset() { 574 575 bb.recycle(); 576 bytesWritten = 0; 577 charsWritten = 0; 578 gotEnc = false; 579 enc = null; 580 initial = true; 581 582 } 583 584 585 public int getBufferSize() { 586 return bb.getLimit(); 587 } 588 589 590 } 591 | Popular Tags |