1 48 49 package com.caucho.burlap.client; 50 51 import java.io.ByteArrayOutputStream ; 52 import java.io.IOException ; 53 import java.io.InputStream ; 54 import java.util.Calendar ; 55 import java.util.Date ; 56 import java.util.Hashtable ; 57 import java.util.TimeZone ; 58 import java.util.Vector ; 59 60 81 public class MicroBurlapInput { 82 private static int base64Decode[]; 83 84 private InputStream is; 85 protected int peek; 86 protected boolean peekTag; 87 protected Date date; 88 protected Calendar utcCalendar; 89 private Calendar localCalendar; 90 protected Vector refs; 91 protected String method; 92 protected StringBuffer sbuf = new StringBuffer (); 93 protected StringBuffer entity = new StringBuffer (); 94 95 101 public MicroBurlapInput(InputStream is) 102 { 103 init(is); 104 } 105 106 109 public MicroBurlapInput() 110 { 111 } 112 113 116 public String getMethod() 117 { 118 return method; 119 } 120 121 126 public void init(InputStream is) 127 { 128 this.is = is; 129 this.refs = null; 130 } 131 132 142 public void startCall() 143 throws IOException 144 { 145 expectStartTag("burlap:call"); 146 expectStartTag("method"); 147 method = parseString(); 148 expectEndTag("method"); 149 this.refs = null; 150 } 151 152 159 public void completeCall() 160 throws IOException 161 { 162 expectEndTag("burlap:call"); 163 } 164 165 169 public Object readReply(Class expectedClass) 170 throws Exception 171 { 172 if (startReply()) { 173 Object value = readObject(expectedClass); 174 completeReply(); 175 return value; 176 } 177 else { 178 Hashtable fault = readFault(); 179 180 Object detail = fault.get("detail"); 181 if (detail instanceof Exception ) 182 throw (Exception ) detail; 183 184 else { 185 String code = (String ) fault.get("code"); 186 String message = (String ) fault.get("message"); 187 188 throw new BurlapServiceException(message, code, detail); 189 } 190 } 191 } 192 193 205 public boolean startReply() 206 throws IOException 207 { 208 this.refs = null; 209 210 expectStartTag("burlap:reply"); 211 212 if (! parseTag()) 213 throw new BurlapProtocolException("expected <value>"); 214 215 String tag = sbuf.toString(); 216 if (tag.equals("fault")) { 217 peekTag = true; 218 return false; 219 } 220 else { 221 peekTag = true; 222 return true; 223 } 224 } 225 226 233 public void completeReply() 234 throws IOException 235 { 236 expectEndTag("burlap:reply"); 237 } 238 239 242 public boolean readBoolean() 243 throws IOException 244 { 245 expectStartTag("boolean"); 246 247 int value = parseInt(); 248 249 expectEndTag("boolean"); 250 251 return value != 0; 252 } 253 254 257 public int readInt() 258 throws IOException 259 { 260 expectStartTag("int"); 261 262 int value = parseInt(); 263 264 expectEndTag("int"); 265 266 return value; 267 } 268 269 272 public long readLong() 273 throws IOException 274 { 275 expectStartTag("long"); 276 277 long value = parseLong(); 278 279 expectEndTag("long"); 280 281 return value; 282 } 283 284 287 public long readUTCDate() 288 throws IOException 289 { 290 expectStartTag("date"); 291 292 if (utcCalendar == null) 293 utcCalendar = Calendar.getInstance(TimeZone.getTimeZone("UTC")); 294 295 long value = parseDate(utcCalendar); 296 297 expectEndTag("date"); 298 299 return value; 300 } 301 302 305 public long readLocalDate() 306 throws IOException 307 { 308 expectStartTag("date"); 309 310 if (localCalendar == null) 311 localCalendar = Calendar.getInstance(); 312 313 long value = parseDate(localCalendar); 314 315 expectEndTag("date"); 316 317 return value; 318 } 319 320 323 public BurlapRemote readRemote() 324 throws IOException 325 { 326 expectStartTag("remote"); 327 328 String type = readType(); 329 String url = readString(); 330 331 expectEndTag("remote"); 332 333 return new BurlapRemote(type, url); 334 } 335 336 349 public String readString() 350 throws IOException 351 { 352 if (! parseTag()) 353 throw new BurlapProtocolException("expected <string>"); 354 355 String tag = sbuf.toString(); 356 if (tag.equals("null")) { 357 expectEndTag("null"); 358 return null; 359 } 360 else if (tag.equals("string")) { 361 sbuf.setLength(0); 362 parseString(sbuf); 363 String value = sbuf.toString(); 364 expectEndTag("string"); 365 return value; 366 } 367 else 368 throw expectBeginTag("string", tag); 369 } 370 371 377 public byte []readBytes() 378 throws IOException 379 { 380 if (! parseTag()) 381 throw new BurlapProtocolException("expected <base64>"); 382 383 String tag = sbuf.toString(); 384 if (tag.equals("null")) { 385 expectEndTag("null"); 386 return null; 387 } 388 else if (tag.equals("base64")) { 389 sbuf.setLength(0); 390 byte []value = parseBytes(); 391 expectEndTag("base64"); 392 return value; 393 } 394 else 395 throw expectBeginTag("base64", tag); 396 } 397 398 401 public Object readObject(Class expectedClass) 402 throws IOException 403 { 404 if (! parseTag()) 405 throw new BurlapProtocolException("expected <tag>"); 406 407 String tag = sbuf.toString(); 408 if (tag.equals("null")) { 409 expectEndTag("null"); 410 return null; 411 } 412 else if (tag.equals("boolean")) { 413 int value = parseInt(); 414 expectEndTag("boolean"); 415 return new Boolean (value != 0); 416 } 417 else if (tag.equals("int")) { 418 int value = parseInt(); 419 expectEndTag("int"); 420 return new Integer (value); 421 } 422 else if (tag.equals("long")) { 423 long value = parseLong(); 424 expectEndTag("long"); 425 return new Long (value); 426 } 427 else if (tag.equals("string")) { 428 sbuf.setLength(0); 429 parseString(sbuf); 430 String value = sbuf.toString(); 431 expectEndTag("string"); 432 return value; 433 } 434 else if (tag.equals("xml")) { 435 sbuf.setLength(0); 436 parseString(sbuf); 437 String value = sbuf.toString(); 438 expectEndTag("xml"); 439 return value; 440 } 441 else if (tag.equals("date")) { 442 if (utcCalendar == null) 443 utcCalendar = Calendar.getInstance(TimeZone.getTimeZone("UTC")); 444 445 long value = parseDate(utcCalendar); 446 expectEndTag("date"); 447 return new Date (value); 448 } 449 else if (tag.equals("map")) { 450 String type = readType(); 451 452 return readMap(expectedClass, type); 453 } 454 else if (tag.equals("list")) { 455 String type = readType(); 456 457 int length = readLength(); 458 459 return readList(expectedClass, type, length); 460 } 461 else if (tag.equals("ref")) { 462 int value = parseInt(); 463 expectEndTag("ref"); 464 465 return refs.elementAt(value); 466 } 467 else if (tag.equals("remote")) { 468 String type = readType(); 469 String url = readString(); 470 471 expectEndTag("remote"); 472 473 return resolveRemote(type, url); 474 } 475 else 476 return readExtensionObject(expectedClass, tag); 477 } 478 479 486 public String readType() 487 throws IOException 488 { 489 if (! parseTag()) 490 throw new BurlapProtocolException("expected <type>"); 491 492 String tag = sbuf.toString(); 493 if (! tag.equals("type")) 494 throw new BurlapProtocolException("expected <type>"); 495 496 sbuf.setLength(0); 497 parseString(sbuf); 498 String value = sbuf.toString(); 499 expectEndTag("type"); 500 501 return value; 502 } 503 504 512 public int readLength() 513 throws IOException 514 { 515 expectStartTag("length"); 516 517 int ch = skipWhitespace(); 518 519 peek = ch; 520 521 if (ch == '<') { 522 expectEndTag("length"); 523 return -1; 524 } 525 526 int value = parseInt(); 527 528 expectEndTag("length"); 529 530 return value; 531 } 532 533 536 public Object resolveRemote(String type, String url) 537 throws IOException 538 { 539 return new BurlapRemote(type, url); 540 } 541 542 545 public Hashtable readFault() 546 throws IOException 547 { 548 expectStartTag("fault"); 549 550 Hashtable map = new Hashtable (); 551 552 while (parseTag()) { 553 peekTag = true; 554 Object key = readObject(null); 555 Object value = readObject(null); 556 557 if (key != null && value != null) 558 map.put(key, value); 559 } 560 561 if (! sbuf.toString().equals("fault")) 562 throw new BurlapProtocolException("expected </fault>"); 563 564 return map; 565 } 566 567 573 public Object readMap(Class expectedClass, String type) 574 throws IOException 575 { 576 Hashtable map = new Hashtable (); 577 if (refs == null) 578 refs = new Vector (); 579 refs.addElement(map); 580 581 while (parseTag()) { 582 peekTag = true; 583 Object key = readObject(null); 584 Object value = readObject(null); 585 586 map.put(key, value); 587 } 588 if (! sbuf.toString().equals("map")) 589 throw new BurlapProtocolException("expected </map>"); 590 591 return map; 592 } 593 594 597 protected Object readExtensionObject(Class expectedClass, String tag) 598 throws IOException 599 { 600 throw new BurlapProtocolException("unknown object tag <" + tag + ">"); 601 } 602 603 610 public Object readList(Class expectedClass, String type, int length) 611 throws IOException 612 { 613 Vector list = new Vector (); 614 if (refs == null) 615 refs = new Vector (); 616 refs.addElement(list); 617 618 while (parseTag()) { 619 peekTag = true; 620 Object value = readObject(null); 621 622 list.addElement(value); 623 } 624 625 if (! sbuf.toString().equals("list")) 626 throw new BurlapProtocolException("expected </list>"); 627 628 return list; 629 } 630 631 634 protected int parseInt() 635 throws IOException 636 { 637 int sign = 1; 638 int value = 0; 639 640 int ch = skipWhitespace(); 641 if (ch == '+') 642 ch = read(); 643 else if (ch == '-') { 644 sign = -1; 645 ch = read(); 646 } 647 648 for (; ch >= '0' && ch <= '9'; ch = read()) 649 value = 10 * value + ch - '0'; 650 651 peek = ch; 652 653 return sign * value; 654 } 655 656 659 protected long parseLong() 660 throws IOException 661 { 662 long sign = 1; 663 long value = 0; 664 665 int ch = skipWhitespace(); 666 if (ch == '+') 667 ch = read(); 668 else if (ch == '-') { 669 sign = -1; 670 ch = read(); 671 } 672 673 for (; ch >= '0' && ch <= '9'; ch = read()) { 674 value = 10 * value + ch - '0'; 675 } 676 677 peek = ch; 678 679 return sign * value; 680 } 681 682 685 protected long parseDate(Calendar calendar) 686 throws IOException 687 { 688 int ch = skipWhitespace(); 689 690 int year = 0; 691 for (int i = 0; i < 4; i++) { 692 if (ch >= '0' && ch <= '9') 693 year = 10 * year + ch - '0'; 694 else 695 throw expectedChar("year", ch); 696 697 ch = read(); 698 } 699 700 int month = 0; 701 for (int i = 0; i < 2; i++) { 702 if (ch >= '0' && ch <= '9') 703 month = 10 * month + ch - '0'; 704 else 705 throw expectedChar("month", ch); 706 707 ch = read(); 708 } 709 710 int day = 0; 711 for (int i = 0; i < 2; i++) { 712 if (ch >= '0' && ch <= '9') 713 day = 10 * day + ch - '0'; 714 else 715 throw expectedChar("day", ch); 716 717 ch = read(); 718 } 719 720 if (ch != 'T') 721 throw expectedChar("`T'", ch); 722 723 ch = read(); 724 725 int hour = 0; 726 for (int i = 0; i < 2; i++) { 727 if (ch >= '0' && ch <= '9') 728 hour = 10 * hour + ch - '0'; 729 else 730 throw expectedChar("hour", ch); 731 732 ch = read(); 733 } 734 735 int minute = 0; 736 for (int i = 0; i < 2; i++) { 737 if (ch >= '0' && ch <= '9') 738 minute = 10 * minute + ch - '0'; 739 else 740 throw expectedChar("minute", ch); 741 742 ch = read(); 743 } 744 745 int second = 0; 746 for (int i = 0; i < 2; i++) { 747 if (ch >= '0' && ch <= '9') 748 second = 10 * second + ch - '0'; 749 else 750 throw expectedChar("second", ch); 751 752 ch = read(); 753 } 754 755 for (; ch > 0 && ch != '<'; ch = read()) { 756 } 757 758 peek = ch; 759 760 calendar.set(Calendar.YEAR, year); 761 calendar.set(Calendar.MONTH, month - 1); 762 calendar.set(Calendar.DAY_OF_MONTH, day); 763 calendar.set(Calendar.HOUR_OF_DAY, hour); 764 calendar.set(Calendar.MINUTE, minute); 765 calendar.set(Calendar.SECOND, second); 766 calendar.set(Calendar.MILLISECOND, 0); 767 768 return calendar.getTime().getTime(); 769 } 770 771 775 protected String parseString() 776 throws IOException 777 { 778 StringBuffer sbuf = new StringBuffer (); 779 780 return parseString(sbuf).toString(); 781 } 782 783 787 protected StringBuffer parseString(StringBuffer sbuf) 788 throws IOException 789 { 790 int ch = read(); 791 792 for (; ch >= 0 && ch != '<'; ch = read()) { 793 if (ch == '&') { 794 ch = read(); 795 796 if (ch == '#') { 797 ch = read(); 798 799 if (ch >= '0' && ch <= '9') { 800 int v = 0; 801 for (; ch >= '0' && ch <= '9'; ch = read()) { 802 v = 10 * v + ch - '0'; 803 } 804 805 sbuf.append((char) v); 806 } 807 } 808 else { 809 StringBuffer entityBuffer = new StringBuffer (); 810 811 for (; ch >= 'a' && ch <= 'z'; ch = read()) 812 entityBuffer.append((char) ch); 813 814 String entity = entityBuffer.toString(); 815 if (entity.equals("amp")) 816 sbuf.append('&'); 817 else if (entity.equals("apos")) 818 sbuf.append('\''); 819 else if (entity.equals("quot")) 820 sbuf.append('"'); 821 else if (entity.equals("lt")) 822 sbuf.append('<'); 823 else if (entity.equals("gt")) 824 sbuf.append('>'); 825 else 826 throw new BurlapProtocolException("unknown XML entity &" + entity + "; at `" + (char) ch + "'"); 827 } 828 829 if (ch != ';') 830 throw expectedChar("';'", ch); 831 } 832 else if (ch < 0x80) 833 sbuf.append((char) ch); 834 else if ((ch & 0xe0) == 0xc0) { 835 int ch1 = read(); 836 int v = ((ch & 0x1f) << 6) + (ch1 & 0x3f); 837 838 sbuf.append((char) v); 839 } 840 else if ((ch & 0xf0) == 0xe0) { 841 int ch1 = read(); 842 int ch2 = read(); 843 int v = ((ch & 0x0f) << 12) + ((ch1 & 0x3f) << 6) + (ch2 & 0x3f); 844 845 sbuf.append((char) v); 846 } 847 else 848 throw new BurlapProtocolException("bad utf-8 encoding"); 849 } 850 851 peek = ch; 852 853 return sbuf; 854 } 855 856 859 protected byte []parseBytes() 860 throws IOException 861 { 862 ByteArrayOutputStream bos = new ByteArrayOutputStream (); 863 864 parseBytes(bos); 865 866 return bos.toByteArray(); 867 } 868 869 872 protected ByteArrayOutputStream parseBytes(ByteArrayOutputStream bos) 873 throws IOException 874 { 875 int ch; 876 for (ch = read(); ch >= 0 && ch != '<'; ch = read()) { 877 int b1 = ch; 878 int b2 = read(); 879 int b3 = read(); 880 int b4 = read(); 881 882 if (b4 != '=') { 883 int chunk = ((base64Decode[b1] << 18) + 884 (base64Decode[b2] << 12) + 885 (base64Decode[b3] << 6) + 886 (base64Decode[b4])); 887 888 bos.write(chunk >> 16); 889 bos.write(chunk >> 8); 890 bos.write(chunk); 891 } 892 else if (b3 != '=') { 893 int chunk = ((base64Decode[b1] << 12) + 894 (base64Decode[b2] << 6) + 895 (base64Decode[b3])); 896 897 bos.write(chunk >> 8); 898 bos.write(chunk); 899 } 900 else { 901 int chunk = ((base64Decode[b1] << 6) + 902 (base64Decode[b2])); 903 904 bos.write(chunk); 905 } 906 } 907 908 if (ch == '<') 909 peek = ch; 910 911 return bos; 912 } 913 914 protected void expectStartTag(String tag) 915 throws IOException 916 { 917 if (! parseTag()) 918 throw new BurlapProtocolException("expected <" + tag + ">"); 919 920 if (! sbuf.toString().equals(tag)) 921 throw new BurlapProtocolException("expected <" + tag + "> at <" + sbuf + ">"); 922 } 923 924 protected void expectEndTag(String tag) 925 throws IOException 926 { 927 if (parseTag()) 928 throw new BurlapProtocolException("expected </" + tag + ">"); 929 930 if (! sbuf.toString().equals(tag)) 931 throw new BurlapProtocolException("expected </" + tag + "> at </" + sbuf + ">"); 932 } 933 934 937 protected boolean parseTag() 938 throws IOException 939 { 940 if (peekTag) { 941 peekTag = false; 942 return true; 943 } 944 945 int ch = skipWhitespace(); 946 boolean isStartTag = true; 947 948 if (ch != '<') 949 throw expectedChar("'<'", ch); 950 951 ch = read(); 952 if (ch == '/') { 953 isStartTag = false; 954 ch = is.read(); 955 } 956 957 if (! isTagChar(ch)) 958 throw expectedChar("tag", ch); 959 960 sbuf.setLength(0); 961 for (; isTagChar(ch); ch = read()) 962 sbuf.append((char) ch); 963 964 if (ch != '>') 965 throw expectedChar("'>'", ch); 966 967 return isStartTag; 968 } 969 970 protected IOException expectedChar(String expect, int actualChar) 971 { 972 return new BurlapProtocolException("expected " + expect + " at " + 973 (char) actualChar + "'"); 974 } 975 976 protected IOException expectBeginTag(String expect, String tag) 977 { 978 return new BurlapProtocolException("expected <" + expect + "> at <" + tag + ">"); 979 } 980 981 private boolean isTagChar(int ch) 982 { 983 return (ch >= 'a' && ch <= 'z' || 984 ch >= 'A' && ch <= 'Z' || 985 ch >= '0' && ch <= '9' || 986 ch == ':' || ch == '-'); 987 } 988 989 protected int skipWhitespace() 990 throws IOException 991 { 992 int ch = read(); 993 994 for (; 995 ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'; 996 ch = read()) { 997 } 998 999 return ch; 1000 } 1001 1002 protected boolean isWhitespace(int ch) 1003 throws IOException 1004 { 1005 return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'; 1006 } 1007 1008 protected int read() 1009 throws IOException 1010 { 1011 if (peek > 0) { 1012 int value = peek; 1013 peek = 0; 1014 return value; 1015 } 1016 1017 return is.read(); 1018 } 1019 1020 static { 1021 base64Decode = new int[256]; 1022 for (int i = 'A'; i <= 'Z'; i++) 1023 base64Decode[i] = i - 'A'; 1024 for (int i = 'a'; i <= 'z'; i++) 1025 base64Decode[i] = i - 'a' + 26; 1026 for (int i = '0'; i <= '9'; i++) 1027 base64Decode[i] = i - '0' + 52; 1028 base64Decode['+'] = 62; 1029 base64Decode['/'] = 63; 1030 } 1031} 1032 | Popular Tags |