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 }