001 /* 002 * Copyright (c) 2001-2008 Caucho Technology, Inc. All rights reserved. 003 * 004 * The Apache Software License, Version 1.1 005 * 006 * Redistribution and use in source and binary forms, with or without 007 * modification, are permitted provided that the following conditions 008 * are met: 009 * 010 * 1. Redistributions of source code must retain the above copyright 011 * notice, this list of conditions and the following disclaimer. 012 * 013 * 2. Redistributions in binary form must reproduce the above copyright 014 * notice, this list of conditions and the following disclaimer in 015 * the documentation and/or other materials provided with the 016 * distribution. 017 * 018 * 3. The end-user documentation included with the redistribution, if 019 * any, must include the following acknowlegement: 020 * "This product includes software developed by the 021 * Caucho Technology (http://www.caucho.com/)." 022 * Alternately, this acknowlegement may appear in the software itself, 023 * if and wherever such third-party acknowlegements normally appear. 024 * 025 * 4. The names "Hessian", "Resin", and "Caucho" must not be used to 026 * endorse or promote products derived from this software without prior 027 * written permission. For written permission, please contact 028 * info@caucho.com. 029 * 030 * 5. Products derived from this software may not be called "Resin" 031 * nor may "Resin" appear in their names without prior written 032 * permission of Caucho Technology. 033 * 034 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 035 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 036 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 037 * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS 038 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 039 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 040 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 041 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 042 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 043 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 044 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 045 * 046 * @author Scott Ferguson 047 */ 048 049 package com.caucho.burlap.io; 050 051 import com.caucho.hessian.io.Deserializer; 052 import com.caucho.hessian.io.HessianRemoteResolver; 053 import com.caucho.hessian.io.SerializerFactory; 054 055 import java.io.ByteArrayOutputStream; 056 import java.io.IOException; 057 import java.io.InputStream; 058 import java.io.Reader; 059 import java.lang.reflect.Field; 060 import java.util.ArrayList; 061 import java.util.Calendar; 062 import java.util.Date; 063 import java.util.HashMap; 064 import java.util.TimeZone; 065 066 /** 067 * Input stream for Burlap requests. 068 * 069 * <p>BurlapInput is unbuffered, so any client needs to provide 070 * its own buffering. 071 * 072 * <pre> 073 * InputStream is = ...; // from http connection 074 * BurlapInput in = new BurlapInput(is); 075 * String value; 076 * 077 * in.startReply(); // read reply header 078 * value = in.readString(); // read string value 079 * in.completeReply(); // read reply footer 080 * </pre> 081 */ 082 public class BurlapInput extends AbstractBurlapInput { 083 private static int []base64Decode; 084 085 public final static int TAG_EOF = -1; 086 087 public final static int TAG_NULL = 0; 088 public final static int TAG_BOOLEAN = 1; 089 public final static int TAG_INT = 2; 090 public final static int TAG_LONG = 3; 091 public final static int TAG_DOUBLE = 4; 092 public final static int TAG_DATE = 5; 093 public final static int TAG_STRING = 6; 094 public final static int TAG_XML = 7; 095 public final static int TAG_BASE64 = 8; 096 public final static int TAG_MAP = 9; 097 public final static int TAG_LIST = 10; 098 public final static int TAG_TYPE = 11; 099 public final static int TAG_LENGTH = 12; 100 101 public final static int TAG_REF = 13; 102 public final static int TAG_REMOTE = 14; 103 104 public final static int TAG_CALL = 15; 105 public final static int TAG_REPLY = 16; 106 public final static int TAG_FAULT = 17; 107 public final static int TAG_METHOD = 18; 108 public final static int TAG_HEADER = 19; 109 110 public final static int TAG_NULL_END = TAG_NULL + 100; 111 public final static int TAG_BOOLEAN_END = TAG_BOOLEAN + 100; 112 public final static int TAG_INT_END = TAG_INT + 100; 113 public final static int TAG_LONG_END = TAG_LONG + 100; 114 public final static int TAG_DOUBLE_END = TAG_DOUBLE + 100; 115 public final static int TAG_DATE_END = TAG_DATE + 100; 116 public final static int TAG_STRING_END = TAG_STRING + 100; 117 public final static int TAG_XML_END = TAG_XML + 100; 118 public final static int TAG_BASE64_END = TAG_BASE64 + 100; 119 public final static int TAG_MAP_END = TAG_MAP + 100; 120 public final static int TAG_LIST_END = TAG_LIST + 100; 121 public final static int TAG_TYPE_END = TAG_TYPE + 100; 122 public final static int TAG_LENGTH_END = TAG_LENGTH + 100; 123 124 public final static int TAG_REF_END = TAG_REF + 100; 125 public final static int TAG_REMOTE_END = TAG_REMOTE + 100; 126 127 public final static int TAG_CALL_END = TAG_CALL + 100; 128 public final static int TAG_REPLY_END = TAG_REPLY + 100; 129 public final static int TAG_FAULT_END = TAG_FAULT + 100; 130 public final static int TAG_METHOD_END = TAG_METHOD + 100; 131 public final static int TAG_HEADER_END = TAG_HEADER + 100; 132 133 private static HashMap _tagMap; 134 135 private static Field _detailMessageField; 136 137 protected SerializerFactory _serializerFactory; 138 139 protected ArrayList _refs; 140 141 // the underlying input stream 142 private InputStream _is; 143 // a peek character 144 protected int _peek = -1; 145 146 // the method for a call 147 private String _method; 148 149 private int _peekTag; 150 151 private Throwable _replyFault; 152 153 protected StringBuffer _sbuf = new StringBuffer(); 154 protected StringBuffer _entityBuffer = new StringBuffer(); 155 156 protected Calendar _utcCalendar; 157 protected Calendar _localCalendar; 158 159 /** 160 * Creates an uninitialized Burlap input stream. 161 */ 162 public BurlapInput() 163 { 164 } 165 166 /** 167 * Creates a new Burlap input stream, initialized with an 168 * underlying input stream. 169 * 170 * @param is the underlying input stream. 171 */ 172 public BurlapInput(InputStream is) 173 { 174 init(is); 175 } 176 177 /** 178 * Sets the serializer factory. 179 */ 180 public void setSerializerFactory(SerializerFactory factory) 181 { 182 _serializerFactory = factory; 183 } 184 185 /** 186 * Gets the serializer factory. 187 */ 188 public SerializerFactory getSerializerFactory() 189 { 190 return _serializerFactory; 191 } 192 193 /** 194 * Initialize the burlap stream with the underlying input stream. 195 */ 196 public void init(InputStream is) 197 { 198 _is = is; 199 _method = null; 200 _peek = -1; 201 _peekTag = -1; 202 _refs = null; 203 _replyFault = null; 204 205 if (_serializerFactory == null) 206 _serializerFactory = new SerializerFactory(); 207 } 208 209 /** 210 * Returns the calls method 211 */ 212 public String getMethod() 213 { 214 return _method; 215 } 216 217 /** 218 * Returns any reply fault. 219 */ 220 public Throwable getReplyFault() 221 { 222 return _replyFault; 223 } 224 225 /** 226 * Starts reading the call 227 * 228 * <pre> 229 * <burlap:call> 230 * <method>method</method> 231 * </pre> 232 */ 233 public void startCall() 234 throws IOException 235 { 236 readCall(); 237 238 while ((readHeader() != null)) 239 readObject(); 240 241 readMethod(); 242 } 243 244 /** 245 * Starts reading the call 246 * 247 * <p>A successful completion will have a single value: 248 * 249 * <pre> 250 * <burlap:call> 251 * </pre> 252 */ 253 public int readCall() 254 throws IOException 255 { 256 expectTag(TAG_CALL); 257 258 int major = 1; 259 int minor = 0; 260 261 return (major << 16) + minor; 262 } 263 264 /** 265 * Reads the method 266 * 267 * <pre> 268 * <method>method</method> 269 * </pre> 270 */ 271 public String readMethod() 272 throws IOException 273 { 274 expectTag(TAG_METHOD); 275 276 _method = parseString(); 277 278 expectTag(TAG_METHOD_END); 279 280 return _method; 281 } 282 283 /** 284 * Completes reading the call 285 * 286 * <p>A successful completion will have a single value: 287 * 288 * <pre> 289 * </burlap:call> 290 * </pre> 291 */ 292 public void completeCall() 293 throws IOException 294 { 295 expectTag(TAG_CALL_END); 296 } 297 298 /** 299 * Reads a reply as an object. 300 * If the reply has a fault, throws the exception. 301 */ 302 public Object readReply(Class expectedClass) 303 throws Throwable 304 { 305 expectTag(TAG_REPLY); 306 307 int tag = parseTag(); 308 309 if (tag == TAG_FAULT) 310 throw prepareFault(); 311 else { 312 _peekTag = tag; 313 Object value = readObject(expectedClass); 314 315 expectTag(TAG_REPLY_END); 316 317 return value; 318 } 319 } 320 321 /** 322 * Starts reading the reply 323 * 324 * <p>A successful completion will have a single value: 325 * 326 * <pre> 327 * <burlap:reply> 328 * <value> 329 * </pre> 330 */ 331 public void startReply() 332 throws Throwable 333 { 334 expectTag(TAG_REPLY); 335 336 int tag = parseTag(); 337 if (tag == TAG_FAULT) 338 throw prepareFault(); 339 else 340 _peekTag = tag; 341 } 342 343 /** 344 * Prepares the fault. 345 */ 346 private Throwable prepareFault() 347 throws IOException 348 { 349 HashMap fault = readFault(); 350 351 Object detail = fault.get("detail"); 352 String message = (String) fault.get("message"); 353 354 if (detail instanceof Throwable) { 355 _replyFault = (Throwable) detail; 356 357 if (message != null && _detailMessageField != null) { 358 try { 359 _detailMessageField.set(_replyFault, message); 360 } catch (Throwable e) { 361 } 362 } 363 364 return _replyFault; 365 } 366 367 else { 368 String code = (String) fault.get("code"); 369 370 _replyFault = new BurlapServiceException(message, code, detail); 371 372 return _replyFault; 373 } 374 } 375 376 /** 377 * Completes reading the call 378 * 379 * <p>A successful completion will have a single value: 380 * 381 * <pre> 382 * </burlap:reply> 383 * </pre> 384 */ 385 public void completeReply() 386 throws IOException 387 { 388 expectTag(TAG_REPLY_END); 389 } 390 391 /** 392 * Reads a header, returning null if there are no headers. 393 * 394 * <pre> 395 * <header>value</header> 396 * </pre> 397 */ 398 public String readHeader() 399 throws IOException 400 { 401 int tag = parseTag(); 402 403 if (tag == TAG_HEADER) { 404 _sbuf.setLength(0); 405 String value = parseString(_sbuf).toString(); 406 expectTag(TAG_HEADER_END); 407 return value; 408 } 409 410 _peekTag = tag; 411 412 return null; 413 } 414 415 /** 416 * Reads a null 417 * 418 * <pre> 419 * <null></null> 420 * </pre> 421 */ 422 public void readNull() 423 throws IOException 424 { 425 int tag = parseTag(); 426 427 switch (tag) { 428 case TAG_NULL: 429 expectTag(TAG_NULL_END); 430 return; 431 432 default: 433 throw expectedTag("null", tag); 434 } 435 } 436 437 /** 438 * Reads a boolean 439 * 440 * <pre> 441 * <boolean>0</boolean> 442 * <boolean>1</boolean> 443 * </pre> 444 */ 445 public boolean readBoolean() 446 throws IOException 447 { 448 int tag = parseTag(); 449 450 boolean value; 451 452 switch (tag) { 453 case TAG_NULL: 454 value = false; 455 expectTag(TAG_NULL_END); 456 return value; 457 458 case TAG_BOOLEAN: 459 value = parseInt() != 0; 460 expectTag(TAG_BOOLEAN_END); 461 return value; 462 463 case TAG_INT: 464 value = parseInt() != 0; 465 expectTag(TAG_INT_END); 466 return value; 467 468 case TAG_LONG: 469 value = parseLong() != 0; 470 expectTag(TAG_LONG_END); 471 return value; 472 473 case TAG_DOUBLE: 474 value = parseDouble() != 0; 475 expectTag(TAG_DOUBLE_END); 476 return value; 477 478 default: 479 throw expectedTag("boolean", tag); 480 } 481 } 482 483 /** 484 * Reads a byte 485 * 486 * <pre> 487 * <int>value</int> 488 * </pre> 489 */ 490 public byte readByte() 491 throws IOException 492 { 493 return (byte) readInt(); 494 } 495 496 /** 497 * Reads a short 498 * 499 * <pre> 500 * <int>value</int> 501 * </pre> 502 */ 503 public short readShort() 504 throws IOException 505 { 506 return (short) readInt(); 507 } 508 509 /** 510 * Reads an integer 511 * 512 * <pre> 513 * <int>value</int> 514 * </pre> 515 */ 516 public int readInt() 517 throws IOException 518 { 519 int tag = parseTag(); 520 521 int value; 522 523 switch (tag) { 524 case TAG_NULL: 525 value = 0; 526 expectTag(TAG_NULL_END); 527 return value; 528 529 case TAG_BOOLEAN: 530 value = parseInt(); 531 expectTag(TAG_BOOLEAN_END); 532 return value; 533 534 case TAG_INT: 535 value = parseInt(); 536 expectTag(TAG_INT_END); 537 return value; 538 539 case TAG_LONG: 540 value = (int) parseLong(); 541 expectTag(TAG_LONG_END); 542 return value; 543 544 case TAG_DOUBLE: 545 value = (int) parseDouble(); 546 expectTag(TAG_DOUBLE_END); 547 return value; 548 549 default: 550 throw expectedTag("int", tag); 551 } 552 } 553 554 /** 555 * Reads a long 556 * 557 * <pre> 558 * <long>value</long> 559 * </pre> 560 */ 561 public long readLong() 562 throws IOException 563 { 564 int tag = parseTag(); 565 566 long value; 567 568 switch (tag) { 569 case TAG_NULL: 570 value = 0; 571 expectTag(TAG_NULL_END); 572 return value; 573 574 case TAG_BOOLEAN: 575 value = parseInt(); 576 expectTag(TAG_BOOLEAN_END); 577 return value; 578 579 case TAG_INT: 580 value = parseInt(); 581 expectTag(TAG_INT_END); 582 return value; 583 584 case TAG_LONG: 585 value = parseLong(); 586 expectTag(TAG_LONG_END); 587 return value; 588 589 case TAG_DOUBLE: 590 value = (long) parseDouble(); 591 expectTag(TAG_DOUBLE_END); 592 return value; 593 594 default: 595 throw expectedTag("long", tag); 596 } 597 } 598 599 /** 600 * Reads a float 601 * 602 * <pre> 603 * <double>value</double> 604 * </pre> 605 */ 606 public float readFloat() 607 throws IOException 608 { 609 return (float) readDouble(); 610 } 611 612 /** 613 * Reads a double 614 * 615 * <pre> 616 * <double>value</double> 617 * </pre> 618 */ 619 public double readDouble() 620 throws IOException 621 { 622 int tag = parseTag(); 623 624 double value; 625 626 switch (tag) { 627 case TAG_NULL: 628 value = 0; 629 expectTag(TAG_NULL_END); 630 return value; 631 632 case TAG_BOOLEAN: 633 value = parseInt(); 634 expectTag(TAG_BOOLEAN_END); 635 return value; 636 637 case TAG_INT: 638 value = parseInt(); 639 expectTag(TAG_INT_END); 640 return value; 641 642 case TAG_LONG: 643 value = parseLong(); 644 expectTag(TAG_LONG_END); 645 return value; 646 647 case TAG_DOUBLE: 648 value = parseDouble(); 649 expectTag(TAG_DOUBLE_END); 650 return value; 651 652 default: 653 throw expectedTag("double", tag); 654 } 655 } 656 657 /** 658 * Reads a date. 659 * 660 * <pre> 661 * <date>ISO-8609 date</date> 662 * </pre> 663 */ 664 public long readUTCDate() 665 throws IOException 666 { 667 int tag = parseTag(); 668 669 if (tag != TAG_DATE) 670 throw error("expected date"); 671 672 if (_utcCalendar == null) 673 _utcCalendar = Calendar.getInstance(TimeZone.getTimeZone("UTC")); 674 675 long value = parseDate(_utcCalendar); 676 677 expectTag(TAG_DATE_END); 678 679 return value; 680 } 681 682 /** 683 * Reads a date. 684 * 685 * <pre> 686 * <date>ISO-8609 date</date> 687 * </pre> 688 */ 689 public long readLocalDate() 690 throws IOException 691 { 692 int tag = parseTag(); 693 694 if (tag != TAG_DATE) 695 throw error("expected date"); 696 697 if (_localCalendar == null) 698 _localCalendar = Calendar.getInstance(); 699 700 long value = parseDate(_localCalendar); 701 702 expectTag(TAG_DATE_END); 703 704 return value; 705 } 706 707 /** 708 * Reads a string 709 * 710 * <pre> 711 * <string>value</string> 712 * </pre> 713 */ 714 public String readString() 715 throws IOException 716 { 717 int tag = parseTag(); 718 719 String value; 720 721 switch (tag) { 722 case TAG_NULL: 723 expectTag(TAG_NULL_END); 724 return null; 725 726 case TAG_STRING: 727 _sbuf.setLength(0); 728 value = parseString(_sbuf).toString(); 729 expectTag(TAG_STRING_END); 730 return value; 731 732 case TAG_XML: 733 _sbuf.setLength(0); 734 value = parseString(_sbuf).toString(); 735 expectTag(TAG_XML_END); 736 return value; 737 738 default: 739 throw expectedTag("string", tag); 740 } 741 } 742 743 /** 744 * Reads an XML node. 745 * 746 * <pre> 747 * &xml;xml string</xml> 748 * </pre> 749 */ 750 public org.w3c.dom.Node readNode() 751 throws IOException 752 { 753 int tag = read(); 754 755 switch (tag) { 756 case 'N': 757 return null; 758 759 case 'S': 760 case 's': 761 case 'X': 762 case 'x': 763 throw error("can't cope"); 764 765 default: 766 throw expectedTag("string", tag); 767 } 768 } 769 770 /** 771 * Reads a byte array 772 * 773 * <pre> 774 * <base64>...</base64> 775 * </pre> 776 */ 777 public byte []readBytes() 778 throws IOException 779 { 780 int tag = parseTag(); 781 782 switch (tag) { 783 case TAG_NULL: 784 expectTag(TAG_NULL_END); 785 return null; 786 787 case TAG_BASE64: 788 byte []data = parseBytes(); 789 expectTag(TAG_BASE64_END); 790 791 return data; 792 793 default: 794 throw expectedTag("bytes", tag); 795 } 796 } 797 798 /** 799 * Reads a length 800 * 801 * <pre> 802 * <length>value</length> 803 * </pre> 804 */ 805 public int readLength() 806 throws IOException 807 { 808 int tag = parseTag(); 809 810 if (tag != TAG_LENGTH) { 811 _peekTag = tag; 812 return -1; 813 } 814 815 int value = parseInt(); 816 817 expectTag(TAG_LENGTH_END); 818 819 return value; 820 } 821 822 /** 823 * Reads a fault. 824 */ 825 private HashMap readFault() 826 throws IOException 827 { 828 HashMap map = new HashMap(); 829 830 int code = parseTag(); 831 for (; code >= 0 && code != TAG_FAULT_END; code = parseTag()) { 832 _peekTag = code; 833 834 Object key = readObject(); 835 Object value = readObject(); 836 837 if (key != null && value != null) 838 map.put(key, value); 839 } 840 841 if (code != TAG_FAULT_END) 842 throw expectedTag("fault", code); 843 844 return map; 845 } 846 847 /** 848 * Reads an object from the input stream with an expected type. 849 */ 850 public Object readObject(Class cl) 851 throws IOException 852 { 853 if (cl == null || cl.equals(Object.class)) 854 return readObject(); 855 856 int tag = parseTag(); 857 858 switch (tag) { 859 case TAG_NULL: 860 expectTag(TAG_NULL_END); 861 return null; 862 863 case TAG_MAP: 864 { 865 String type = readType(); 866 Deserializer reader; 867 868 reader = _serializerFactory.getObjectDeserializer(type, cl); 869 870 return reader.readMap(this); 871 } 872 873 case TAG_LIST: 874 { 875 String type = readType(); 876 int length = readLength(); 877 878 Deserializer reader; 879 reader = _serializerFactory.getObjectDeserializer(type, cl); 880 881 return reader.readList(this, length); 882 } 883 884 case TAG_REF: 885 { 886 int ref = parseInt(); 887 888 expectTag(TAG_REF_END); 889 890 return _refs.get(ref); 891 } 892 893 case TAG_REMOTE: 894 { 895 String type = readType(); 896 String url = readString(); 897 898 expectTag(TAG_REMOTE_END); 899 900 Object remote = resolveRemote(type, url); 901 902 return remote; 903 } 904 } 905 906 _peekTag = tag; 907 908 Object value = _serializerFactory.getDeserializer(cl).readObject(this); 909 910 return value; 911 } 912 913 /** 914 * Reads an arbitrary object from the input stream when the type 915 * is unknown. 916 */ 917 public Object readObject() 918 throws IOException 919 { 920 int tag = parseTag(); 921 922 switch (tag) { 923 case TAG_NULL: 924 expectTag(TAG_NULL_END); 925 return null; 926 927 case TAG_BOOLEAN: 928 { 929 int value = parseInt(); 930 expectTag(TAG_BOOLEAN_END); 931 return new Boolean(value != 0); 932 } 933 934 case TAG_INT: 935 { 936 int value = parseInt(); 937 expectTag(TAG_INT_END); 938 return new Integer(value); 939 } 940 941 case TAG_LONG: 942 { 943 long value = parseLong(); 944 expectTag(TAG_LONG_END); 945 return new Long(value); 946 } 947 948 case TAG_DOUBLE: 949 { 950 double value = parseDouble(); 951 expectTag(TAG_DOUBLE_END); 952 return new Double(value); 953 } 954 955 case TAG_DATE: 956 { 957 long value = parseDate(); 958 expectTag(TAG_DATE_END); 959 return new Date(value); 960 } 961 962 case TAG_XML: 963 { 964 return parseXML(); 965 } 966 967 case TAG_STRING: 968 { 969 _sbuf.setLength(0); 970 971 String value = parseString(_sbuf).toString(); 972 973 expectTag(TAG_STRING_END); 974 975 return value; 976 } 977 978 case TAG_BASE64: 979 { 980 byte []data = parseBytes(); 981 982 expectTag(TAG_BASE64_END); 983 984 return data; 985 } 986 987 case TAG_LIST: 988 { 989 String type = readType(); 990 int length = readLength(); 991 992 return _serializerFactory.readList(this, length, type); 993 } 994 995 case TAG_MAP: 996 { 997 String type = readType(); 998 Deserializer deserializer; 999 deserializer = _serializerFactory.getObjectDeserializer(type); 1000 1001 return deserializer.readMap(this); 1002 } 1003 1004 case TAG_REF: 1005 { 1006 int ref = parseInt(); 1007 1008 expectTag(TAG_REF_END); 1009 1010 return _refs.get(ref); 1011 } 1012 1013 case TAG_REMOTE: 1014 { 1015 String type = readType(); 1016 String url = readString(); 1017 1018 expectTag(TAG_REMOTE_END); 1019 1020 return resolveRemote(type, url); 1021 } 1022 1023 default: 1024 throw error("unknown code:" + tagName(tag)); 1025 } 1026 } 1027 1028 /** 1029 * Reads a remote object. 1030 */ 1031 public Object readRemote() 1032 throws IOException 1033 { 1034 String type = readType(); 1035 String url = readString(); 1036 1037 return resolveRemote(type, url); 1038 } 1039 1040 /** 1041 * Reads a reference. 1042 */ 1043 public Object readRef() 1044 throws IOException 1045 { 1046 return _refs.get(parseInt()); 1047 } 1048 1049 /** 1050 * Reads the start of a list. 1051 */ 1052 public int readListStart() 1053 throws IOException 1054 { 1055 return parseTag(); 1056 } 1057 1058 /** 1059 * Reads the start of a map. 1060 */ 1061 public int readMapStart() 1062 throws IOException 1063 { 1064 return parseTag(); 1065 } 1066 1067 /** 1068 * Returns true if this is the end of a list or a map. 1069 */ 1070 public boolean isEnd() 1071 throws IOException 1072 { 1073 int code = parseTag(); 1074 1075 _peekTag = code; 1076 1077 return (code < 0 || code >= 100); 1078 } 1079 1080 /** 1081 * Reads the end byte. 1082 */ 1083 public void readEnd() 1084 throws IOException 1085 { 1086 int code = parseTag(); 1087 1088 if (code < 100) 1089 throw error("unknown code:" + (char) code); 1090 } 1091 1092 /** 1093 * Reads the end of the map 1094 */ 1095 public void readMapEnd() 1096 throws IOException 1097 { 1098 expectTag(TAG_MAP_END); 1099 } 1100 1101 /** 1102 * Reads the end of the map 1103 */ 1104 public void readListEnd() 1105 throws IOException 1106 { 1107 expectTag(TAG_LIST_END); 1108 } 1109 1110 /** 1111 * Adds a list/map reference. 1112 */ 1113 public int addRef(Object ref) 1114 { 1115 if (_refs == null) 1116 _refs = new ArrayList(); 1117 1118 _refs.add(ref); 1119 1120 return _refs.size() - 1; 1121 } 1122 1123 /** 1124 * Adds a list/map reference. 1125 */ 1126 public void setRef(int i, Object ref) 1127 { 1128 _refs.set(i, ref); 1129 } 1130 1131 /** 1132 * Resolves a remote object. 1133 */ 1134 public Object resolveRemote(String type, String url) 1135 throws IOException 1136 { 1137 HessianRemoteResolver resolver = getRemoteResolver(); 1138 1139 if (resolver != null) 1140 return resolver.lookup(type, url); 1141 else 1142 return new BurlapRemote(type, url); 1143 } 1144 1145 /** 1146 * Parses a type from the stream. 1147 * 1148 * <pre> 1149 * <type>type</type> 1150 * </pre> 1151 */ 1152 public String readType() 1153 throws IOException 1154 { 1155 int code = parseTag(); 1156 1157 if (code != TAG_TYPE) { 1158 _peekTag = code; 1159 return ""; 1160 } 1161 1162 _sbuf.setLength(0); 1163 int ch; 1164 while ((ch = readChar()) >= 0) 1165 _sbuf.append((char) ch); 1166 String type = _sbuf.toString(); 1167 1168 expectTag(TAG_TYPE_END); 1169 1170 return type; 1171 } 1172 1173 /** 1174 * Parses a 32-bit integer value from the stream. 1175 */ 1176 private int parseInt() 1177 throws IOException 1178 { 1179 int sign = 1; 1180 1181 int ch = read(); 1182 if (ch == '-') { 1183 sign = -1; 1184 ch = read(); 1185 } 1186 1187 int value = 0; 1188 for (; ch >= '0' && ch <= '9'; ch = read()) 1189 value = 10 * value + ch - '0'; 1190 1191 _peek = ch; 1192 1193 return sign * value; 1194 } 1195 1196 /** 1197 * Parses a 64-bit long value from the stream. 1198 */ 1199 private long parseLong() 1200 throws IOException 1201 { 1202 int sign = 1; 1203 1204 int ch = read(); 1205 if (ch == '-') { 1206 sign = -1; 1207 ch = read(); 1208 } 1209 1210 long value = 0; 1211 for (; ch >= '0' && ch <= '9'; ch = read()) 1212 value = 10 * value + ch - '0'; 1213 1214 _peek = ch; 1215 1216 return sign * value; 1217 } 1218 1219 /** 1220 * Parses a 64-bit double value from the stream. 1221 * 1222 * <pre> 1223 * b64 b56 b48 b40 b32 b24 b16 b8 1224 * </pre> 1225 */ 1226 private double parseDouble() 1227 throws IOException 1228 { 1229 int ch = skipWhitespace(); 1230 1231 _sbuf.setLength(0); 1232 1233 for (; ! isWhitespace(ch) && ch != '<'; ch = read()) 1234 _sbuf.append((char) ch); 1235 1236 _peek = ch; 1237 1238 return new Double(_sbuf.toString()).doubleValue(); 1239 } 1240 1241 /** 1242 * Parses a date value from the stream. 1243 */ 1244 protected long parseDate() 1245 throws IOException 1246 { 1247 if (_utcCalendar == null) 1248 _utcCalendar = Calendar.getInstance(TimeZone.getTimeZone("UTC")); 1249 1250 return parseDate(_utcCalendar); 1251 } 1252 1253 /** 1254 * Parses a date value from the stream. 1255 */ 1256 protected long parseDate(Calendar calendar) 1257 throws IOException 1258 { 1259 int ch = skipWhitespace(); 1260 1261 int year = 0; 1262 for (int i = 0; i < 4; i++) { 1263 if (ch >= '0' && ch <= '9') 1264 year = 10 * year + ch - '0'; 1265 else 1266 throw expectedChar("year", ch); 1267 1268 ch = read(); 1269 } 1270 1271 int month = 0; 1272 for (int i = 0; i < 2; i++) { 1273 if (ch >= '0' && ch <= '9') 1274 month = 10 * month + ch - '0'; 1275 else 1276 throw expectedChar("month", ch); 1277 1278 ch = read(); 1279 } 1280 1281 int day = 0; 1282 for (int i = 0; i < 2; i++) { 1283 if (ch >= '0' && ch <= '9') 1284 day = 10 * day + ch - '0'; 1285 else 1286 throw expectedChar("day", ch); 1287 1288 ch = read(); 1289 } 1290 1291 if (ch != 'T') 1292 throw expectedChar("`T'", ch); 1293 1294 ch = read(); 1295 1296 int hour = 0; 1297 for (int i = 0; i < 2; i++) { 1298 if (ch >= '0' && ch <= '9') 1299 hour = 10 * hour + ch - '0'; 1300 else 1301 throw expectedChar("hour", ch); 1302 1303 ch = read(); 1304 } 1305 1306 int minute = 0; 1307 for (int i = 0; i < 2; i++) { 1308 if (ch >= '0' && ch <= '9') 1309 minute = 10 * minute + ch - '0'; 1310 else 1311 throw expectedChar("minute", ch); 1312 1313 ch = read(); 1314 } 1315 1316 int second = 0; 1317 for (int i = 0; i < 2; i++) { 1318 if (ch >= '0' && ch <= '9') 1319 second = 10 * second + ch - '0'; 1320 else 1321 throw expectedChar("second", ch); 1322 1323 ch = read(); 1324 } 1325 1326 int ms = 0; 1327 if (ch == '.') { 1328 ch = read(); 1329 1330 while (ch >= '0' && ch <= '9') { 1331 ms = 10 * ms + ch - '0'; 1332 1333 ch = read(); 1334 } 1335 } 1336 1337 for (; ch > 0 && ch != '<'; ch = read()) { 1338 } 1339 1340 _peek = ch; 1341 1342 calendar.set(Calendar.YEAR, year); 1343 calendar.set(Calendar.MONTH, month - 1); 1344 calendar.set(Calendar.DAY_OF_MONTH, day); 1345 calendar.set(Calendar.HOUR_OF_DAY, hour); 1346 calendar.set(Calendar.MINUTE, minute); 1347 calendar.set(Calendar.SECOND, second); 1348 calendar.set(Calendar.MILLISECOND, ms); 1349 1350 return calendar.getTime().getTime(); 1351 } 1352 1353 protected String parseString() 1354 throws IOException 1355 { 1356 _sbuf.setLength(0); 1357 1358 return parseString(_sbuf).toString(); 1359 } 1360 1361 /** 1362 * Parses a string value from the stream. The burlap object's 1363 * string buffer is used for the result. 1364 */ 1365 protected StringBuffer parseString(StringBuffer sbuf) 1366 throws IOException 1367 { 1368 int ch; 1369 1370 while ((ch = readChar()) >= 0) 1371 sbuf.append((char) ch); 1372 1373 return sbuf; 1374 } 1375 1376 org.w3c.dom.Node parseXML() 1377 throws IOException 1378 { 1379 throw error("help!"); 1380 } 1381 1382 /** 1383 * Reads a character from the underlying stream. 1384 */ 1385 int readChar() 1386 throws IOException 1387 { 1388 int ch = read(); 1389 1390 if (ch == '<' || ch < 0) { 1391 _peek = ch; 1392 return -1; 1393 } 1394 1395 if (ch == '&') { 1396 ch = read(); 1397 1398 if (ch == '#') { 1399 ch = read(); 1400 1401 if (ch >= '0' && ch <= '9') { 1402 int v = 0; 1403 for (; ch >= '0' && ch <= '9'; ch = read()) { 1404 v = 10 * v + ch - '0'; 1405 } 1406 1407 if (ch != ';') 1408 throw error("expected ';' at " + (char) ch); 1409 1410 return (char) v; 1411 } 1412 else 1413 throw error("expected digit at " + (char) ch); 1414 } 1415 else { 1416 _entityBuffer.setLength(0); 1417 1418 for (; ch >= 'a' && ch <= 'z'; ch = read()) 1419 _entityBuffer.append((char) ch); 1420 1421 String entity = _entityBuffer.toString(); 1422 1423 if (ch != ';') 1424 throw expectedChar("';'", ch); 1425 1426 if (entity.equals("amp")) 1427 return '&'; 1428 else if (entity.equals("apos")) 1429 return '\''; 1430 else if (entity.equals("quot")) 1431 return '"'; 1432 else if (entity.equals("lt")) 1433 return '<'; 1434 else if (entity.equals("gt")) 1435 return '>'; 1436 else 1437 throw new BurlapProtocolException("unknown XML entity &" + entity + "; at `" + (char) ch + "'"); 1438 } 1439 } 1440 else if (ch < 0x80) 1441 return (char) ch; 1442 else if ((ch & 0xe0) == 0xc0) { 1443 int ch1 = read(); 1444 int v = ((ch & 0x1f) << 6) + (ch1 & 0x3f); 1445 1446 return (char) v; 1447 } 1448 else if ((ch & 0xf0) == 0xe0) { 1449 int ch1 = read(); 1450 int ch2 = read(); 1451 int v = ((ch & 0x0f) << 12) + ((ch1 & 0x3f) << 6) + (ch2 & 0x3f); 1452 1453 return (char) v; 1454 } 1455 else 1456 throw new BurlapProtocolException("bad utf-8 encoding"); 1457 } 1458 1459 /** 1460 * Parses a byte array. 1461 */ 1462 protected byte []parseBytes() 1463 throws IOException 1464 { 1465 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 1466 1467 parseBytes(bos); 1468 1469 return bos.toByteArray(); 1470 } 1471 1472 /** 1473 * Parses a byte array. 1474 */ 1475 protected ByteArrayOutputStream parseBytes(ByteArrayOutputStream bos) 1476 throws IOException 1477 { 1478 int ch; 1479 for (ch = skipWhitespace(); ch >= 0 && ch != '<'; ch = skipWhitespace()) { 1480 int b1 = ch; 1481 int b2 = read(); 1482 int b3 = read(); 1483 int b4 = read(); 1484 1485 if (b4 != '=') { 1486 int chunk = ((base64Decode[b1] << 18) + 1487 (base64Decode[b2] << 12) + 1488 (base64Decode[b3] << 6) + 1489 (base64Decode[b4])); 1490 1491 bos.write(chunk >> 16); 1492 bos.write(chunk >> 8); 1493 bos.write(chunk); 1494 } 1495 else if (b3 != '=') { 1496 int chunk = ((base64Decode[b1] << 10) + 1497 (base64Decode[b2] << 4) + 1498 (base64Decode[b3] >> 2)); 1499 1500 bos.write(chunk >> 8); 1501 bos.write(chunk); 1502 } 1503 else { 1504 int chunk = ((base64Decode[b1] << 2) + 1505 (base64Decode[b2] >> 4)); 1506 1507 bos.write(chunk); 1508 } 1509 } 1510 1511 if (ch == '<') 1512 _peek = ch; 1513 1514 return bos; 1515 } 1516 1517 public void expectTag(int expectTag) 1518 throws IOException 1519 { 1520 int tag = parseTag(); 1521 1522 if (tag != expectTag) 1523 throw error("expected " + tagName(expectTag) + " at " + tagName(tag)); 1524 } 1525 1526 /** 1527 * Parses a tag. Returns true if it's a start tag. 1528 */ 1529 protected int parseTag() 1530 throws IOException 1531 { 1532 if (_peekTag >= 0) { 1533 int tag = _peekTag; 1534 _peekTag = -1; 1535 return tag; 1536 } 1537 1538 int ch = skipWhitespace(); 1539 int endTagDelta = 0; 1540 1541 if (ch != '<') 1542 throw expectedChar("'<'", ch); 1543 1544 ch = read(); 1545 if (ch == '/') { 1546 endTagDelta = 100; 1547 ch = _is.read(); 1548 } 1549 1550 if (! isTagChar(ch)) 1551 throw expectedChar("tag", ch); 1552 1553 _sbuf.setLength(0); 1554 for (; isTagChar(ch); ch = read()) 1555 _sbuf.append((char) ch); 1556 1557 if (ch != '>') 1558 throw expectedChar("'>'", ch); 1559 1560 Integer value = (Integer) _tagMap.get(_sbuf.toString()); 1561 if (value == null) 1562 throw error("Unknown tag <" + _sbuf + ">"); 1563 1564 return value.intValue() + endTagDelta; 1565 } 1566 1567 /** 1568 * Returns true if the character is a valid tag character. 1569 */ 1570 private boolean isTagChar(int ch) 1571 { 1572 return (ch >= 'a' && ch <= 'z' || 1573 ch >= 'A' && ch <= 'Z' || 1574 ch >= '0' && ch <= '9' || 1575 ch == ':' || ch == '-'); 1576 } 1577 1578 protected int skipWhitespace() 1579 throws IOException 1580 { 1581 int ch = read(); 1582 1583 for (; 1584 ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'; 1585 ch = read()) { 1586 } 1587 1588 return ch; 1589 } 1590 1591 protected boolean isWhitespace(int ch) 1592 throws IOException 1593 { 1594 return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'; 1595 } 1596 1597 /** 1598 * Reads bytes from the underlying stream. 1599 */ 1600 int read(byte []buffer, int offset, int length) 1601 throws IOException 1602 { 1603 throw new UnsupportedOperationException(); 1604 } 1605 1606 int read() 1607 throws IOException 1608 { 1609 if (_peek >= 0) { 1610 int value = _peek; 1611 _peek = -1; 1612 return value; 1613 } 1614 1615 int ch = _is.read(); 1616 return ch; 1617 } 1618 1619 public Reader getReader() 1620 { 1621 return null; 1622 } 1623 1624 public InputStream readInputStream() 1625 { 1626 return null; 1627 } 1628 1629 public InputStream getInputStream() 1630 { 1631 return null; 1632 } 1633 1634 protected IOException expectBeginTag(String expect, String tag) 1635 { 1636 return new BurlapProtocolException("expected <" + expect + "> at <" + tag + ">"); 1637 } 1638 1639 protected IOException expectedChar(String expect, int ch) 1640 { 1641 if (ch < 0) 1642 return error("expected " + expect + " at end of file"); 1643 else 1644 return error("expected " + expect + " at " + (char) ch); 1645 } 1646 1647 protected IOException expectedTag(String expect, int tag) 1648 { 1649 return error("expected " + expect + " at " + tagName(tag)); 1650 } 1651 1652 protected IOException error(String message) 1653 { 1654 return new BurlapProtocolException(message); 1655 } 1656 1657 protected static String tagName(int tag) 1658 { 1659 switch (tag) { 1660 case TAG_NULL: 1661 return "<null>"; 1662 case TAG_NULL_END: 1663 return "</null>"; 1664 1665 case TAG_BOOLEAN: 1666 return "<boolean>"; 1667 case TAG_BOOLEAN_END: 1668 return "</boolean>"; 1669 1670 case TAG_INT: 1671 return "<int>"; 1672 case TAG_INT_END: 1673 return "</int>"; 1674 1675 case TAG_LONG: 1676 return "<long>"; 1677 case TAG_LONG_END: 1678 return "</long>"; 1679 1680 case TAG_DOUBLE: 1681 return "<double>"; 1682 case TAG_DOUBLE_END: 1683 return "</double>"; 1684 1685 case TAG_STRING: 1686 return "<string>"; 1687 case TAG_STRING_END: 1688 return "</string>"; 1689 1690 case TAG_XML: 1691 return "<xml>"; 1692 case TAG_XML_END: 1693 return "</xml>"; 1694 1695 case TAG_BASE64: 1696 return "<base64>"; 1697 case TAG_BASE64_END: 1698 return "</base64>"; 1699 1700 case TAG_MAP: 1701 return "<map>"; 1702 case TAG_MAP_END: 1703 return "</map>"; 1704 1705 case TAG_LIST: 1706 return "<list>"; 1707 case TAG_LIST_END: 1708 return "</list>"; 1709 1710 case TAG_TYPE: 1711 return "<type>"; 1712 case TAG_TYPE_END: 1713 return "</type>"; 1714 1715 case TAG_LENGTH: 1716 return "<length>"; 1717 case TAG_LENGTH_END: 1718 return "</length>"; 1719 1720 case TAG_REF: 1721 return "<ref>"; 1722 case TAG_REF_END: 1723 return "</ref>"; 1724 1725 case TAG_REMOTE: 1726 return "<remote>"; 1727 case TAG_REMOTE_END: 1728 return "</remote>"; 1729 1730 case TAG_CALL: 1731 return "<burlap:call>"; 1732 case TAG_CALL_END: 1733 return "</burlap:call>"; 1734 1735 case TAG_REPLY: 1736 return "<burlap:reply>"; 1737 case TAG_REPLY_END: 1738 return "</burlap:reply>"; 1739 1740 case TAG_HEADER: 1741 return "<header>"; 1742 case TAG_HEADER_END: 1743 return "</header>"; 1744 1745 case TAG_FAULT: 1746 return "<fault>"; 1747 case TAG_FAULT_END: 1748 return "</fault>"; 1749 1750 case -1: 1751 return "end of file"; 1752 1753 default: 1754 return "unknown " + tag; 1755 } 1756 } 1757 1758 1759 static { 1760 _tagMap = new HashMap(); 1761 _tagMap.put("null", new Integer(TAG_NULL)); 1762 1763 _tagMap.put("boolean", new Integer(TAG_BOOLEAN)); 1764 _tagMap.put("int", new Integer(TAG_INT)); 1765 _tagMap.put("long", new Integer(TAG_LONG)); 1766 _tagMap.put("double", new Integer(TAG_DOUBLE)); 1767 1768 _tagMap.put("date", new Integer(TAG_DATE)); 1769 1770 _tagMap.put("string", new Integer(TAG_STRING)); 1771 _tagMap.put("xml", new Integer(TAG_XML)); 1772 _tagMap.put("base64", new Integer(TAG_BASE64)); 1773 1774 _tagMap.put("map", new Integer(TAG_MAP)); 1775 _tagMap.put("list", new Integer(TAG_LIST)); 1776 1777 _tagMap.put("type", new Integer(TAG_TYPE)); 1778 _tagMap.put("length", new Integer(TAG_LENGTH)); 1779 1780 _tagMap.put("ref", new Integer(TAG_REF)); 1781 _tagMap.put("remote", new Integer(TAG_REMOTE)); 1782 1783 _tagMap.put("burlap:call", new Integer(TAG_CALL)); 1784 _tagMap.put("burlap:reply", new Integer(TAG_REPLY)); 1785 _tagMap.put("fault", new Integer(TAG_FAULT)); 1786 _tagMap.put("method", new Integer(TAG_METHOD)); 1787 _tagMap.put("header", new Integer(TAG_HEADER)); 1788 } 1789 1790 static { 1791 base64Decode = new int[256]; 1792 for (int i = 'A'; i <= 'Z'; i++) 1793 base64Decode[i] = i - 'A'; 1794 for (int i = 'a'; i <= 'z'; i++) 1795 base64Decode[i] = i - 'a' + 26; 1796 for (int i = '0'; i <= '9'; i++) 1797 base64Decode[i] = i - '0' + 52; 1798 base64Decode['+'] = 62; 1799 base64Decode['/'] = 63; 1800 } 1801 1802 static { 1803 try { 1804 _detailMessageField = Throwable.class.getDeclaredField("detailMessage"); 1805 _detailMessageField.setAccessible(true); 1806 } catch (Throwable e) { 1807 } 1808 } 1809 }