1 17 18 package org.apache.catalina.connector; 19 20 import java.io.IOException ; 21 import java.io.Reader ; 22 import java.security.AccessController ; 23 import java.security.PrivilegedActionException ; 24 import java.security.PrivilegedExceptionAction ; 25 import java.util.HashMap ; 26 27 import org.apache.catalina.security.SecurityUtil; 28 import org.apache.coyote.Request; 29 import org.apache.tomcat.util.buf.B2CConverter; 30 import org.apache.tomcat.util.buf.ByteChunk; 31 import org.apache.tomcat.util.buf.CharChunk; 32 33 34 42 public class InputBuffer extends Reader 43 implements ByteChunk.ByteInputChannel, CharChunk.CharInputChannel, 44 CharChunk.CharOutputChannel { 45 46 47 49 50 public static final String DEFAULT_ENCODING = 51 org.apache.coyote.Constants.DEFAULT_CHARACTER_ENCODING; 52 public static final int DEFAULT_BUFFER_SIZE = 8*1024; 53 54 public final int INITIAL_STATE = 0; 57 public final int CHAR_STATE = 1; 58 public final int BYTE_STATE = 2; 59 60 61 63 64 67 private ByteChunk bb; 68 69 70 73 private CharChunk cb; 74 75 76 79 private int state = 0; 80 81 82 85 private int bytesRead = 0; 86 87 88 91 private int charsRead = 0; 92 93 94 97 private boolean closed = false; 98 99 100 103 private ByteChunk inputChunk = new ByteChunk(); 104 105 106 109 private String enc; 110 111 112 115 private boolean gotEnc = false; 116 117 118 121 protected HashMap encoders = new HashMap (); 122 123 124 127 protected B2CConverter conv; 128 129 130 133 private Request coyoteRequest; 134 135 136 139 private int markPos = -1; 140 141 142 145 private int size = -1; 146 147 148 150 151 154 public InputBuffer() { 155 156 this(DEFAULT_BUFFER_SIZE); 157 158 } 159 160 161 166 public InputBuffer(int size) { 167 168 this.size = size; 169 bb = new ByteChunk(size); 170 bb.setLimit(size); 171 bb.setByteInputChannel(this); 172 cb = new CharChunk(size); 173 cb.setLimit(size); 174 cb.setOptimizedWrite(false); 175 cb.setCharInputChannel(this); 176 cb.setCharOutputChannel(this); 177 178 } 179 180 181 183 184 189 public void setRequest(Request coyoteRequest) { 190 this.coyoteRequest = coyoteRequest; 191 } 192 193 194 199 public Request getRequest() { 200 return this.coyoteRequest; 201 } 202 203 204 206 207 210 public void recycle() { 211 212 state = INITIAL_STATE; 213 bytesRead = 0; 214 charsRead = 0; 215 216 if (cb.getChars().length > size) { 218 cb = new CharChunk(size); 219 cb.setLimit(size); 220 cb.setOptimizedWrite(false); 221 cb.setCharInputChannel(this); 222 cb.setCharOutputChannel(this); 223 } else { 224 cb.recycle(); 225 } 226 markPos = -1; 227 bb.recycle(); 228 closed = false; 229 230 if (conv != null) { 231 conv.recycle(); 232 } 233 234 gotEnc = false; 235 enc = null; 236 237 } 238 239 240 243 public void clearEncoders() { 244 encoders.clear(); 245 } 246 247 248 253 public void close() 254 throws IOException { 255 closed = true; 256 } 257 258 259 public int available() 260 throws IOException { 261 if (state == BYTE_STATE) { 262 return bb.getLength(); 263 } else if (state == CHAR_STATE) { 264 return cb.getLength(); 265 } else { 266 return 0; 267 } 268 } 269 270 271 273 274 283 public int realReadBytes(byte cbuf[], int off, int len) 284 throws IOException { 285 286 if (closed) 287 return -1; 288 if (coyoteRequest == null) 289 return -1; 290 291 state = BYTE_STATE; 292 293 int result = coyoteRequest.doRead(bb); 294 295 return result; 296 297 } 298 299 300 public int readByte() 301 throws IOException { 302 return bb.substract(); 303 } 304 305 306 public int read(byte[] b, int off, int len) 307 throws IOException { 308 return bb.substract(b, off, len); 309 } 310 311 312 314 315 321 public void realWriteChars(char c[], int off, int len) 322 throws IOException { 323 markPos = -1; 324 } 325 326 327 public void setEncoding(String s) { 328 enc = s; 329 } 330 331 332 public int realReadChars(char cbuf[], int off, int len) 333 throws IOException { 334 335 if (!gotEnc) 336 setConverter(); 337 338 if (bb.getLength() <= 0) { 339 int nRead = realReadBytes(bb.getBytes(), 0, bb.getBytes().length); 340 if (nRead < 0) { 341 return -1; 342 } 343 } 344 345 if (markPos == -1) { 346 cb.setOffset(0); 347 cb.setEnd(0); 348 } 349 350 int limit = bb.getLength()+cb.getStart(); 351 if( cb.getLimit() < limit ) 352 cb.setLimit(limit); 353 conv.convert(bb, cb); 354 bb.setOffset(bb.getEnd()); 355 state = CHAR_STATE; 356 357 return cb.getLength(); 358 359 } 360 361 362 public int read() 363 throws IOException { 364 return cb.substract(); 365 } 366 367 368 public int read(char[] cbuf) 369 throws IOException { 370 return read(cbuf, 0, cbuf.length); 371 } 372 373 374 public int read(char[] cbuf, int off, int len) 375 throws IOException { 376 return cb.substract(cbuf, off, len); 377 } 378 379 380 public long skip(long n) 381 throws IOException { 382 383 if (n < 0) { 384 throw new IllegalArgumentException (); 385 } 386 387 long nRead = 0; 388 while (nRead < n) { 389 if (cb.getLength() >= n) { 390 cb.setOffset(cb.getStart() + (int) n); 391 nRead = n; 392 } else { 393 nRead += cb.getLength(); 394 cb.setOffset(cb.getEnd()); 395 int toRead = 0; 396 if (cb.getChars().length < (n - nRead)) { 397 toRead = cb.getChars().length; 398 } else { 399 toRead = (int) (n - nRead); 400 } 401 int nb = realReadChars(cb.getChars(), 0, toRead); 402 if (nb < 0) 403 break; 404 } 405 } 406 407 return nRead; 408 409 } 410 411 412 public boolean ready() 413 throws IOException { 414 return (cb.getLength() > 0); 415 } 416 417 418 public boolean markSupported() { 419 return true; 420 } 421 422 423 public void mark(int readAheadLimit) 424 throws IOException { 425 if (cb.getLength() <= 0) { 426 cb.setOffset(0); 427 cb.setEnd(0); 428 } else { 429 if ((cb.getBuffer().length > (2 * size)) 430 && (cb.getLength()) < (cb.getStart())) { 431 System.arraycopy(cb.getBuffer(), cb.getStart(), 432 cb.getBuffer(), 0, cb.getLength()); 433 cb.setEnd(cb.getLength()); 434 cb.setOffset(0); 435 } 436 } 437 int offset = readAheadLimit; 438 if (offset < size) { 439 offset = size; 440 } 441 cb.setLimit(cb.getStart() + offset); 442 markPos = cb.getStart(); 443 } 444 445 446 public void reset() 447 throws IOException { 448 if (state == CHAR_STATE) { 449 if (markPos < 0) { 450 cb.recycle(); 451 markPos = -1; 452 throw new IOException (); 453 } else { 454 cb.setOffset(markPos); 455 } 456 } else { 457 bb.recycle(); 458 } 459 } 460 461 462 public void checkConverter() 463 throws IOException { 464 465 if (!gotEnc) 466 setConverter(); 467 468 } 469 470 471 protected void setConverter() 472 throws IOException { 473 474 if (coyoteRequest != null) 475 enc = coyoteRequest.getCharacterEncoding(); 476 477 gotEnc = true; 478 if (enc == null) 479 enc = DEFAULT_ENCODING; 480 conv = (B2CConverter) encoders.get(enc); 481 if (conv == null) { 482 if (SecurityUtil.isPackageProtectionEnabled()){ 483 try{ 484 conv = (B2CConverter)AccessController.doPrivileged( 485 new PrivilegedExceptionAction (){ 486 487 public Object run() throws IOException { 488 return new B2CConverter(enc); 489 } 490 491 } 492 ); 493 }catch(PrivilegedActionException ex){ 494 Exception e = ex.getException(); 495 if (e instanceof IOException ) 496 throw (IOException )e; 497 } 498 } else { 499 conv = new B2CConverter(enc); 500 } 501 encoders.put(enc, conv); 502 } 503 504 } 505 506 } 507 | Popular Tags |