1 25 26 package org.apache.coyote.tomcat5; 27 28 import java.io.IOException ; 29 import java.io.Reader ; 30 import java.security.AccessController ; 31 import java.security.PrivilegedActionException ; 32 import java.security.PrivilegedExceptionAction ; 33 import java.util.HashMap ; 34 35 import org.apache.catalina.security.SecurityUtil; 36 import org.apache.coyote.Request; 37 import org.apache.tomcat.util.buf.B2CConverter; 38 import org.apache.tomcat.util.buf.ByteChunk; 39 import org.apache.tomcat.util.buf.CharChunk; 40 41 42 50 public class InputBuffer extends Reader 51 implements ByteChunk.ByteInputChannel, CharChunk.CharInputChannel, 52 CharChunk.CharOutputChannel { 53 54 private static com.sun.org.apache.commons.logging.Log log= 55 com.sun.org.apache.commons.logging.LogFactory.getLog( InputBuffer.class ); 56 57 59 60 public static final String DEFAULT_ENCODING = 61 org.apache.coyote.Constants.DEFAULT_CHARACTER_ENCODING; 62 public static final int DEFAULT_BUFFER_SIZE = 8*1024; 63 static final int debug = 0; 64 65 66 public final int INITIAL_STATE = 0; 69 public final int CHAR_STATE = 1; 70 public final int BYTE_STATE = 2; 71 72 73 75 76 79 private ByteChunk bb; 80 81 82 85 private CharChunk cb; 86 87 88 91 private int state = 0; 92 93 94 97 private int bytesRead = 0; 98 99 100 103 private int charsRead = 0; 104 105 106 109 private boolean closed = false; 110 111 112 115 private ByteChunk inputChunk = new ByteChunk(); 116 117 118 121 private String enc; 122 123 124 127 private boolean gotEnc = false; 128 129 130 133 protected HashMap encoders = new HashMap (); 134 135 136 139 protected B2CConverter conv; 140 141 142 145 private Request coyoteRequest; 146 147 148 151 private int markPos = -1; 152 153 154 157 private int size = -1; 158 159 160 162 163 166 public InputBuffer() { 167 168 this(DEFAULT_BUFFER_SIZE); 169 170 } 171 172 173 178 public InputBuffer(int size) { 179 180 this.size = size; 181 bb = new ByteChunk(size); 182 bb.setLimit(size); 183 bb.setByteInputChannel(this); 184 } 185 186 187 private void initChar() { 189 if (cb != null) 190 return; 191 cb = new CharChunk(size); 192 cb.setLimit(size); 193 cb.setOptimizedWrite(false); 194 cb.setCharInputChannel(this); 195 cb.setCharOutputChannel(this); 196 } 197 200 201 206 public void setRequest(Request coyoteRequest) { 207 this.coyoteRequest = coyoteRequest; 208 } 209 210 211 216 public Request getRequest() { 217 return this.coyoteRequest; 218 } 219 220 221 223 224 227 public void recycle() { 228 229 if (log.isTraceEnabled()) 230 log.trace("recycle()"); 231 232 state = INITIAL_STATE; 233 bytesRead = 0; 234 charsRead = 0; 235 236 248 cb = null; 249 251 bb.recycle(); 252 markPos = -1; 253 closed = false; 254 255 if (conv != null) { 256 conv.recycle(); 257 } 258 259 gotEnc = false; 260 enc = null; 261 262 } 263 264 265 270 public void close() 271 throws IOException { 272 closed = true; 273 } 274 275 276 public int available() 277 throws IOException { 278 if (state == BYTE_STATE) { 279 return bb.getLength(); 280 } else if (state == CHAR_STATE) { 281 return cb.getLength(); 282 } else { 283 return 0; 284 } 285 } 286 287 288 290 291 300 public int realReadBytes(byte cbuf[], int off, int len) 301 throws IOException { 302 303 if (log.isDebugEnabled()) 304 log.debug("realRead() " + coyoteRequest); 305 306 if (closed) 307 return -1; 308 if (coyoteRequest == null) 309 return -1; 310 311 state = BYTE_STATE; 312 313 int result = coyoteRequest.doRead(bb); 314 315 return result; 316 317 } 318 319 320 public int readByte() 321 throws IOException { 322 return bb.substract(); 323 } 324 325 326 public int read(byte[] b, int off, int len) 327 throws IOException { 328 return bb.substract(b, off, len); 329 } 330 331 332 334 335 341 public void realWriteChars(char c[], int off, int len) 342 throws IOException { 343 initChar(); 345 markPos = -1; 347 } 348 349 350 public void setEncoding(String s) { 351 enc = s; 352 } 353 354 355 public int realReadChars(char cbuf[], int off, int len) 356 throws IOException { 357 358 initChar(); 360 if (log.isDebugEnabled()) 362 log.debug("realRead() " + cb.getOffset() + " " + len); 363 364 if (!gotEnc) 365 setConverter(); 366 367 if (log.isDebugEnabled()) 368 log.debug("encoder: " + conv + " " + gotEnc); 369 370 if (bb.getLength() <= 0) { 371 int nRead = realReadBytes(bb.getBytes(), 0, bb.getBytes().length); 372 if (nRead < 0) { 373 return -1; 374 } 375 } 376 377 int limit = bb.getLength()+cb.getStart(); 378 if ( cb.getLimit() < limit ) 379 cb.setLimit(limit); 380 381 if (markPos == -1) { 382 cb.setOffset(0); 383 cb.setEnd(0); 384 } 385 386 conv.convert(bb, cb); 387 bb.setOffset(bb.getEnd()); 388 state = CHAR_STATE; 389 390 return cb.getLength(); 391 392 } 393 394 395 public int read() 396 throws IOException { 397 initChar(); 399 return cb.substract(); 401 } 402 403 404 public int read(char[] cbuf) 405 throws IOException { 406 initChar(); 408 return read(cbuf, 0, cbuf.length); 410 } 411 412 413 public int read(char[] cbuf, int off, int len) 414 throws IOException { 415 initChar(); 417 return cb.substract(cbuf, off, len); 419 } 420 421 422 public long skip(long n) 423 throws IOException { 424 425 if (n < 0) { 426 throw new IllegalArgumentException (); 427 } 428 429 initChar(); 431 long nRead = 0; 433 while (nRead < n) { 434 if (cb.getLength() >= n) { 435 cb.setOffset(cb.getStart() + (int) n); 436 nRead = n; 437 } else { 438 nRead += cb.getLength(); 439 cb.setOffset(cb.getEnd()); 440 int toRead = 0; 441 if (cb.getChars().length < (n - nRead)) { 442 toRead = cb.getChars().length; 443 } else { 444 toRead = (int) (n - nRead); 445 } 446 int nb = realReadChars(cb.getChars(), 0, toRead); 447 if (nb < 0) 448 break; 449 } 450 } 451 452 return nRead; 453 454 } 455 456 457 public boolean ready() 458 throws IOException { 459 initChar(); 461 return (cb.getLength() > 0); 463 } 464 465 466 public boolean markSupported() { 467 return true; 468 } 469 470 471 public void mark(int readAheadLimit) 472 throws IOException { 473 initChar(); 475 if (cb.getLength() <= 0) { 477 cb.setOffset(0); 478 cb.setEnd(0); 479 } else { 480 if ((cb.getBuffer().length > (2 * size)) 481 && (cb.getLength()) < (cb.getStart())) { 482 System.arraycopy(cb.getBuffer(), cb.getStart(), 483 cb.getBuffer(), 0, cb.getLength()); 484 cb.setEnd(cb.getLength()); 485 cb.setOffset(0); 486 } 487 } 488 int offset = readAheadLimit; 489 if (offset < size) { 490 offset = size; 491 } 492 cb.setLimit(cb.getStart() + offset); 493 markPos = cb.getStart(); 494 } 495 496 497 public void reset() 498 throws IOException { 499 if (state == CHAR_STATE) { 500 if (markPos < 0) { 501 cb.recycle(); 502 markPos = -1; 503 throw new IOException (); 504 } else { 505 cb.setOffset(markPos); 506 } 507 } else { 508 bb.recycle(); 509 } 510 } 511 512 513 public void checkConverter() 514 throws IOException { 515 516 if (!gotEnc) 517 setConverter(); 518 519 } 520 521 522 protected void setConverter() 523 throws IOException { 524 525 if (coyoteRequest != null) 526 enc = coyoteRequest.getCharacterEncoding(); 527 528 if (log.isDebugEnabled()) 529 log.debug("Got encoding: " + enc); 530 531 gotEnc = true; 532 if (enc == null) 533 enc = DEFAULT_ENCODING; 534 conv = (B2CConverter) encoders.get(enc); 535 if (conv == null) { 536 if (SecurityUtil.isPackageProtectionEnabled()){ 537 try{ 538 conv = (B2CConverter)AccessController.doPrivileged( 539 new PrivilegedExceptionAction (){ 540 541 public Object run() throws IOException { 542 return new B2CConverter(enc); 543 } 544 545 } 546 ); 547 }catch(PrivilegedActionException ex){ 548 Exception e = ex.getException(); 549 if (e instanceof IOException ) 550 throw (IOException )e; 551 552 if (log.isDebugEnabled()) 553 log.debug("setConverter: " + ex.getMessage()); 554 } 555 } else { 556 conv = new B2CConverter(enc); 557 } 558 encoders.put(enc, conv); 559 } 560 561 } 562 } 563 | Popular Tags |