1 48 49 package com.caucho.hessian.io; 50 51 import java.io.IOException ; 52 import java.io.InputStream ; 53 import java.io.PrintWriter ; 54 import java.util.ArrayList ; 55 56 59 public class HessianDebugInputStream extends InputStream { 60 private InputStream _is; 61 private PrintWriter _dbg; 62 63 private State _state; 64 private ArrayList <State> _stateStack = new ArrayList <State>(); 65 66 private int _refId; 67 68 71 public HessianDebugInputStream(InputStream is, PrintWriter dbg) 72 { 73 _is = is; 74 _dbg = dbg; 75 76 _state = new InitialState(); 77 } 78 79 82 public int read() 83 throws IOException 84 { 85 int ch; 86 87 InputStream is = _is; 88 89 if (is == null) 90 return -1; 91 else 92 ch = is.read(); 93 94 _state = _state.next(ch); 95 96 return ch; 97 } 98 99 102 public void close() 103 throws IOException 104 { 105 InputStream is = _is; 106 _is = null; 107 _dbg = null; 108 109 if (is != null) 110 is.close(); 111 } 112 113 void println(String string) 114 { 115 println(0, string); 116 } 117 118 void println(int depth, String string) 119 { 120 for (int i = 0; i < _stateStack.size() + depth - 1; i++) 121 _dbg.print(" "); 122 123 _dbg.println(string); 124 _dbg.flush(); 125 } 126 127 void pushStack(State state) 128 { 129 _stateStack.add(state); 130 } 131 132 State popStack() 133 { 134 return _stateStack.remove(_stateStack.size() - 1); 135 } 136 137 abstract class State { 138 abstract State next(int ch); 139 140 protected State nextObject(int ch) 141 { 142 switch (ch) { 143 case -1: 144 return this; 145 146 case 'N': 147 println(1, "N: null"); 148 return this; 149 150 case 'T': 151 println(1, "T: true"); 152 return this; 153 154 case 'F': 155 println(1, "F: false"); 156 return this; 157 158 case 'I': 159 pushStack(this); 160 return new IntegerState("I"); 161 162 case 'R': 163 pushStack(this); 164 return new IntegerState("Ref"); 165 166 case 'r': 167 pushStack(this); 168 return new RemoteState(); 169 170 case 'L': 171 pushStack(this); 172 return new LongState(); 173 174 case 'd': 175 pushStack(this); 176 return new DateState(); 177 178 case 'D': 179 pushStack(this); 180 return new DoubleState(); 181 182 case 'S': case 'X': 183 pushStack(this); 184 return new StringState('S', true); 185 186 case 's': case 'x': 187 pushStack(this); 188 return new StringState('S', false); 189 190 case 'B': 191 pushStack(this); 192 return new ByteState(true); 193 194 case 'b': 195 pushStack(this); 196 return new ByteState(false); 197 198 case 'M': 199 println(1, "M: map/object #" + _refId++); 200 pushStack(this); 201 return new MapState(); 202 203 case 'V': 204 println(1, "V: list #" + _refId++); 205 pushStack(this); 206 return new ListState(); 207 208 case ' ': case '\n': case '\r': case '\t': 209 return this; 210 211 default: 212 println(String.valueOf((char) ch) + ": unexpected character"); 213 return this; 214 } 215 } 216 } 217 218 class InitialState extends State { 219 State next(int ch) 220 { 221 if (ch == 'r') { 222 pushStack(this); 223 return new ReplyState(); 224 } 225 else if (ch == 'c') { 226 pushStack(this); 227 return new CallState(); 228 } 229 else 230 return nextObject(ch); 231 } 232 } 233 234 class ObjectState extends State { 235 State next(int ch) 236 { 237 return nextObject(ch); 238 } 239 } 240 241 class IntegerState extends State { 242 String _typeCode; 243 244 int _length; 245 int _value; 246 247 IntegerState(String typeCode) 248 { 249 _typeCode = typeCode; 250 } 251 252 State next(int ch) 253 { 254 _value = 256 * _value + (ch & 0xff); 255 256 if (++_length == 4) { 257 println(_typeCode + ": " + _value); 258 return popStack(); 259 } 260 else 261 return this; 262 } 263 } 264 265 class LongState extends State { 266 int _length; 267 long _value; 268 269 State next(int ch) 270 { 271 _value = 256 * _value + (ch & 0xff); 272 273 if (++_length == 8) { 274 println("L: " + _value); 275 return popStack(); 276 } 277 else 278 return this; 279 } 280 } 281 282 class DateState extends State { 283 int _length; 284 long _value; 285 286 State next(int ch) 287 { 288 _value = 256 * _value + (ch & 0xff); 289 290 if (++_length == 8) { 291 println("d: " + new java.util.Date (_value)); 292 return popStack(); 293 } 294 else 295 return this; 296 } 297 } 298 299 class DoubleState extends State { 300 int _length; 301 long _value; 302 303 State next(int ch) 304 { 305 _value = 256 * _value + (ch & 0xff); 306 307 if (++_length == 8) { 308 println("D: " + Double.longBitsToDouble(_value)); 309 return popStack(); 310 } 311 else 312 return this; 313 } 314 } 315 316 class StringState extends State { 317 private static final int TOP = 0; 318 private static final int UTF_2_1 = 1; 319 private static final int UTF_3_1 = 2; 320 private static final int UTF_3_2 = 3; 321 322 char _typeCode; 323 324 StringBuilder _value = new StringBuilder (); 325 int _lengthIndex; 326 int _length; 327 boolean _isLastChunk; 328 329 int _utfState; 330 char _ch; 331 332 StringState(char typeCode, boolean isLastChunk) 333 { 334 _typeCode = typeCode; 335 _isLastChunk = isLastChunk; 336 } 337 338 State next(int ch) 339 { 340 if (_lengthIndex < 2) { 341 _length = 256 * _length + (ch & 0xff); 342 343 if (++_lengthIndex == 2 && _length == 0 && _isLastChunk) { 344 println(_typeCode + ": " + _value); 345 return popStack(); 346 } 347 else 348 return this; 349 } 350 else if (_length == 0) { 351 if (ch == 's' || ch == 'x') { 352 _isLastChunk = false; 353 _lengthIndex = 0; 354 return this; 355 } 356 else if (ch == 'S' || ch == 'X') { 357 _isLastChunk = true; 358 _lengthIndex = 0; 359 return this; 360 } 361 else { 362 println(String.valueOf((char) ch) + ": unexpected character"); 363 return popStack(); 364 } 365 } 366 367 switch (_utfState) { 368 case TOP: 369 if (ch < 0x80) { 370 _length--; 371 372 _value.append((char) ch); 373 } 374 else if (ch < 0xe0) { 375 _ch = (char) ((ch & 0x1f) << 6); 376 _utfState = UTF_2_1; 377 } 378 else { 379 _ch = (char) ((ch & 0xf) << 12); 380 _utfState = UTF_3_1; 381 } 382 break; 383 384 case UTF_2_1: 385 case UTF_3_2: 386 _ch += ch & 0x3f; 387 _value.append(_ch); 388 _length--; 389 _utfState = TOP; 390 break; 391 392 case UTF_3_1: 393 _ch += (char) ((ch & 0x3f) << 6); 394 _utfState = UTF_3_2; 395 break; 396 } 397 398 if (_length == 0) { 399 println(_typeCode + ": " + _value); 400 return popStack(); 401 } 402 else 403 return this; 404 } 405 } 406 407 class ByteState extends State { 408 int _lengthIndex; 409 int _length; 410 boolean _isLastChunk; 411 412 ByteState(boolean isLastChunk) 413 { 414 _isLastChunk = isLastChunk; 415 } 416 417 State next(int ch) 418 { 419 if (_lengthIndex < 2) { 420 _length = 256 * _length + (ch & 0xff); 421 422 if (++_lengthIndex == 2) { 423 if (_isLastChunk) 424 println("B: " + _length); 425 else 426 println("b: " + _length); 427 } 428 429 if (_lengthIndex == 2 && _length == 0 && _isLastChunk) { 430 return popStack(); 431 } 432 else 433 return this; 434 } 435 else if (_length == 0) { 436 if (ch == 'b') { 437 _isLastChunk = false; 438 _lengthIndex = 0; 439 return this; 440 } 441 else if (ch == 'B') { 442 _isLastChunk = true; 443 _lengthIndex = 0; 444 return this; 445 } 446 else { 447 println(String.valueOf((char) ch) + ": unexpected character"); 448 return popStack(); 449 } 450 } 451 452 _length--; 453 454 if (_length == 0) { 455 return popStack(); 456 } 457 else 458 return this; 459 } 460 } 461 462 class MapState extends State { 463 private static final int TYPE = 0; 464 private static final int KEY = 1; 465 private static final int VALUE = 2; 466 467 private int _state; 468 469 State next(int ch) 470 { 471 switch (_state) { 472 case TYPE: 473 if (ch == 't') { 474 _state = KEY; 475 pushStack(this); 476 return new StringState('t', true); 477 } 478 else if (ch == 'z') { 479 return popStack(); 480 } 481 else { 482 _state = VALUE; 483 return nextObject(ch); 484 } 485 486 case KEY: 487 if (ch == 'z') { 488 return popStack(); 489 } 490 else { 491 _state = VALUE; 492 return nextObject(ch); 493 } 494 495 case VALUE: 496 _state = KEY; 497 return nextObject(ch); 498 499 default: 500 throw new IllegalStateException (); 501 } 502 } 503 } 504 505 class ListState extends State { 506 private static final int TYPE = 0; 507 private static final int LENGTH = 1; 508 private static final int VALUE = 2; 509 510 private int _state; 511 512 State next(int ch) 513 { 514 switch (_state) { 515 case TYPE: 516 if (ch == 'z') { 517 return popStack(); 518 } 519 else if (ch == 't') { 520 _state = LENGTH; 521 pushStack(this); 522 return new StringState('t', true); 523 } 524 else if (ch == 'l') { 525 _state = VALUE; 526 pushStack(this); 527 return new IntegerState("l"); 528 } 529 else { 530 _state = VALUE; 531 return nextObject(ch); 532 } 533 534 case LENGTH: 535 if (ch == 'z') { 536 return popStack(); 537 } 538 else if (ch == 'l') { 539 _state = VALUE; 540 pushStack(this); 541 return new IntegerState("len"); 542 } 543 else { 544 _state = VALUE; 545 return nextObject(ch); 546 } 547 548 case VALUE: 549 if (ch == 'z') { 550 return popStack(); 551 } 552 else { 553 return nextObject(ch); 554 } 555 556 default: 557 throw new IllegalStateException (); 558 } 559 } 560 } 561 562 class CallState extends State { 563 private static final int MAJOR = 0; 564 private static final int MINOR = 1; 565 private static final int HEADER = 2; 566 private static final int VALUE = 3; 567 private static final int ARG = 4; 568 569 private int _state; 570 private int _major; 571 private int _minor; 572 573 State next(int ch) 574 { 575 switch (_state) { 576 case MAJOR: 577 _major = ch; 578 _state = MINOR; 579 return this; 580 581 case MINOR: 582 _minor = ch; 583 _state = HEADER; 584 println(-1, "call " + _major + "." + _minor); 585 return this; 586 587 case HEADER: 588 if (ch == 'H') { 589 _state = VALUE; 590 pushStack(this); 591 return new StringState('H', true); 592 } 593 else if (ch == 'm') { 594 _state = ARG; 595 pushStack(this); 596 return new StringState('m', true); 597 } 598 else { 599 println((char) ch + ": unexpected char"); 600 return popStack(); 601 } 602 603 case VALUE: 604 _state = HEADER; 605 return nextObject(ch); 606 607 case ARG: 608 if (ch == 'z') 609 return popStack(); 610 else 611 return nextObject(ch); 612 613 default: 614 throw new IllegalStateException (); 615 } 616 } 617 } 618 619 class ReplyState extends State { 620 private static final int MAJOR = 0; 621 private static final int MINOR = 1; 622 private static final int HEADER = 2; 623 private static final int VALUE = 3; 624 private static final int END = 4; 625 626 private int _state; 627 private int _major; 628 private int _minor; 629 630 State next(int ch) 631 { 632 switch (_state) { 633 case MAJOR: 634 if (ch == 't' || ch == 'S') 635 return new RemoteState().next(ch); 636 637 _major = ch; 638 _state = MINOR; 639 return this; 640 641 case MINOR: 642 _minor = ch; 643 _state = HEADER; 644 println(-1, "reply " + _major + "." + _minor); 645 return this; 646 647 case HEADER: 648 if (ch == 'H') { 649 _state = VALUE; 650 pushStack(this); 651 return new StringState('H', true); 652 } 653 else if (ch == 'f') { 654 println("f: fault"); 655 _state = END; 656 return new MapState(); 657 } 658 else { 659 _state = END; 660 return nextObject(ch); 661 } 662 663 case VALUE: 664 _state = HEADER; 665 return nextObject(ch); 666 667 case END: 668 return popStack().next(ch); 669 670 default: 671 throw new IllegalStateException (); 672 } 673 } 674 } 675 676 class RemoteState extends State { 677 private static final int TYPE = 0; 678 private static final int VALUE = 1; 679 private static final int END = 2; 680 681 private int _state; 682 private int _major; 683 private int _minor; 684 685 State next(int ch) 686 { 687 switch (_state) { 688 case TYPE: 689 println(-1, "remote"); 690 if (ch == 't') { 691 _state = VALUE; 692 pushStack(this); 693 return new StringState('t', false); 694 } 695 else { 696 _state = END; 697 return nextObject(ch); 698 } 699 700 case VALUE: 701 _state = END; 702 return nextObject(ch); 703 704 case END: 705 return popStack().next(ch); 706 707 default: 708 throw new IllegalStateException (); 709 } 710 } 711 } 712 } 713 | Popular Tags |