KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > burlap > io > BurlapInput


1 /*
2  * Copyright (c) 2001-2006 Caucho Technology, Inc. All rights reserved.
3  *
4  * The Apache Software License, Version 1.1
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in
15  * the documentation and/or other materials provided with the
16  * distribution.
17  *
18  * 3. The end-user documentation included with the redistribution, if
19  * any, must include the following acknowlegement:
20  * "This product includes software developed by the
21  * Caucho Technology (http://www.caucho.com/)."
22  * Alternately, this acknowlegement may appear in the software itself,
23  * if and wherever such third-party acknowlegements normally appear.
24  *
25  * 4. The names "Hessian", "Resin", and "Caucho" must not be used to
26  * endorse or promote products derived from this software without prior
27  * written permission. For written permission, please contact
28  * info@caucho.com.
29  *
30  * 5. Products derived from this software may not be called "Resin"
31  * nor may "Resin" appear in their names without prior written
32  * permission of Caucho Technology.
33  *
34  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
35  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
36  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
37  * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS
38  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
39  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
40  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
41  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
42  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
43  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
44  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45  *
46  * @author Scott Ferguson
47  */

48
49 package com.caucho.burlap.io;
50
51 import com.caucho.hessian.io.Deserializer;
52 import com.caucho.hessian.io.HessianRemoteResolver;
53 import com.caucho.hessian.io.SerializerFactory;
54
55 import java.io.ByteArrayOutputStream JavaDoc;
56 import java.io.IOException JavaDoc;
57 import java.io.InputStream JavaDoc;
58 import java.io.Reader JavaDoc;
59 import java.lang.reflect.Field JavaDoc;
60 import java.util.ArrayList JavaDoc;
61 import java.util.Calendar JavaDoc;
62 import java.util.Date JavaDoc;
63 import java.util.HashMap JavaDoc;
64 import java.util.TimeZone JavaDoc;
65
66 /**
67  * Input stream for Burlap requests.
68  *
69  * <p>BurlapInput is unbuffered, so any client needs to provide
70  * its own buffering.
71  *
72  * <pre>
73  * InputStream is = ...; // from http connection
74  * BurlapInput in = new BurlapInput(is);
75  * String value;
76  *
77  * in.startReply(); // read reply header
78  * value = in.readString(); // read string value
79  * in.completeReply(); // read reply footer
80  * </pre>
81  */

82 public class BurlapInput extends AbstractBurlapInput {
83   private static int []base64Decode;
84   
85   public final static int TAG_EOF = -1;
86   
87   public final static int TAG_NULL = 0;
88   public final static int TAG_BOOLEAN = 1;
89   public final static int TAG_INT = 2;
90   public final static int TAG_LONG = 3;
91   public final static int TAG_DOUBLE = 4;
92   public final static int TAG_DATE = 5;
93   public final static int TAG_STRING = 6;
94   public final static int TAG_XML = 7;
95   public final static int TAG_BASE64 = 8;
96   public final static int TAG_MAP = 9;
97   public final static int TAG_LIST = 10;
98   public final static int TAG_TYPE = 11;
99   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 JavaDoc _tagMap;
134
135   private static Field JavaDoc _detailMessageField;
136   
137   protected SerializerFactory _serializerFactory;
138   
139   protected ArrayList JavaDoc _refs;
140   
141   // the underlying input stream
142
private InputStream JavaDoc _is;
143   // a peek character
144
protected int _peek = -1;
145   
146   // the method for a call
147
private String JavaDoc _method;
148
149   private int _peekTag;
150
151   private Throwable JavaDoc _replyFault;
152
153   protected StringBuffer JavaDoc _sbuf = new StringBuffer JavaDoc();
154   protected StringBuffer JavaDoc _entityBuffer = new StringBuffer JavaDoc();
155   
156   protected Calendar JavaDoc _utcCalendar;
157   protected Calendar JavaDoc _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 JavaDoc 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 JavaDoc 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 JavaDoc getMethod()
213   {
214     return _method;
215   }
216
217   /**
218    * Returns any reply fault.
219    */

220   public Throwable JavaDoc getReplyFault()
221   {
222     return _replyFault;
223   }
224
225   /**
226    * Starts reading the call
227    *
228    * <pre>
229    * &lt;burlap:call>
230    * &lt;method>method&lt;/method>
231    * </pre>
232    */

233   public void startCall()
234     throws IOException JavaDoc
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    * &lt;burlap:call>
251    * </pre>
252    */

253   public int readCall()
254     throws IOException JavaDoc
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    * &lt;method>method&lt;/method>
269    * </pre>
270    */

271   public String JavaDoc readMethod()
272     throws IOException JavaDoc
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    * &lt;/burlap:call>
290    * </pre>
291    */

292   public void completeCall()
293     throws IOException JavaDoc
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 JavaDoc readReply(Class JavaDoc expectedClass)
303     throws Throwable JavaDoc
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 JavaDoc 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    * &lt;burlap:reply>
328    * &lt;value>
329    * </pre>
330    */

331   public void startReply()
332     throws Throwable JavaDoc
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 JavaDoc prepareFault()
347     throws IOException JavaDoc
348   {
349     HashMap JavaDoc fault = readFault();
350
351     Object JavaDoc detail = fault.get("detail");
352     String JavaDoc message = (String JavaDoc) fault.get("message");
353
354     if (detail instanceof Throwable JavaDoc) {
355       _replyFault = (Throwable JavaDoc) detail;
356       
357       if (message != null && _detailMessageField != null) {
358     try {
359       _detailMessageField.set(_replyFault, message);
360     } catch (Throwable JavaDoc e) {
361     }
362       }
363     
364       return _replyFault;
365     }
366
367     else {
368       String JavaDoc code = (String JavaDoc) 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    * &lt;/burlap:reply>
383    * </pre>
384    */

385   public void completeReply()
386     throws IOException JavaDoc
387   {
388     expectTag(TAG_REPLY_END);
389   }
390
391   /**
392    * Reads a header, returning null if there are no headers.
393    *
394    * <pre>
395    * &lt;header>value&lt;/header>
396    * </pre>
397    */

398   public String JavaDoc readHeader()
399     throws IOException JavaDoc
400   {
401     int tag = parseTag();
402
403     if (tag == TAG_HEADER) {
404       _sbuf.setLength(0);
405       String JavaDoc 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    * &lt;null>&lt;/null>
420    * </pre>
421    */

422   public void readNull()
423     throws IOException JavaDoc
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    * &lt;boolean>0&lt;/boolean>
442    * &lt;boolean>1&lt;/boolean>
443    * </pre>
444    */

445   public boolean readBoolean()
446     throws IOException JavaDoc
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    * &lt;int>value&lt;/int>
488    * </pre>
489    */

490   public byte readByte()
491     throws IOException JavaDoc
492   {
493     return (byte) readInt();
494   }
495
496   /**
497    * Reads a short
498    *
499    * <pre>
500    * &lt;int>value&lt;/int>
501    * </pre>
502    */

503   public short readShort()
504     throws IOException JavaDoc
505   {
506     return (short) readInt();
507   }
508
509   /**
510    * Reads an integer
511    *
512    * <pre>
513    * &lt;int>value&lt;/int>
514    * </pre>
515    */

516   public int readInt()
517     throws IOException JavaDoc
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    * &lt;long>value&lt;/long>
559    * </pre>
560    */

561   public long readLong()
562     throws IOException JavaDoc
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    * &lt;double>value&lt;/double>
604    * </pre>
605    */

606   public float readFloat()
607     throws IOException JavaDoc
608   {
609     return (float) readDouble();
610   }
611
612   /**
613    * Reads a double
614    *
615    * <pre>
616    * &lt;double>value&lt;/double>
617    * </pre>
618    */

619   public double readDouble()
620     throws IOException JavaDoc
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    * &lt;date>ISO-8609 date&lt;/date>
662    * </pre>
663    */

664   public long readUTCDate()
665     throws IOException JavaDoc
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    * &lt;date>ISO-8609 date&lt;/date>
687    * </pre>
688    */

689   public long readLocalDate()
690     throws IOException JavaDoc
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    * &lt;string>value&lt;/string>
712    * </pre>
713    */

714   public String JavaDoc readString()
715     throws IOException JavaDoc
716   {
717     int tag = parseTag();
718
719     String JavaDoc 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&lt;/xml>
748    * </pre>
749    */

750   public org.w3c.dom.Node JavaDoc readNode()
751     throws IOException JavaDoc
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    * &lt;base64>...&lt;/base64>
775    * </pre>
776    */

777   public byte []readBytes()
778     throws IOException JavaDoc
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    * &lt;length>value&lt;/length>
803    * </pre>
804    */

805   public int readLength()
806     throws IOException JavaDoc
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 JavaDoc readFault()
826     throws IOException JavaDoc
827   {
828     HashMap JavaDoc map = new HashMap JavaDoc();
829
830     int code = parseTag();
831     for (; code >= 0 && code != TAG_FAULT_END; code = parseTag()) {
832       _peekTag = code;
833       
834       Object JavaDoc key = readObject();
835       Object JavaDoc 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 JavaDoc readObject(Class JavaDoc cl)
851     throws IOException JavaDoc
852   {
853     if (cl == null || cl.equals(Object JavaDoc.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 JavaDoc type = readType();
866       Deserializer reader;
867       reader = _serializerFactory.getObjectDeserializer(type);
868
869       if (cl != reader.getType() && cl.isAssignableFrom(reader.getType()))
870         return reader.readMap(this);
871
872       reader = _serializerFactory.getDeserializer(cl);
873
874       return reader.readMap(this);
875     }
876
877     case TAG_LIST:
878     {
879       String JavaDoc type = readType();
880       int length = readLength();
881       
882       Deserializer reader;
883       reader = _serializerFactory.getObjectDeserializer(type);
884
885       if (cl != reader.getType() && cl.isAssignableFrom(reader.getType()))
886         return reader.readList(this, length);
887
888       reader = _serializerFactory.getDeserializer(cl);
889
890       return reader.readList(this, length);
891     }
892
893     case TAG_REF:
894     {
895       int ref = parseInt();
896
897       expectTag(TAG_REF_END);
898
899       return _refs.get(ref);
900     }
901
902     case TAG_REMOTE:
903     {
904       String JavaDoc type = readType();
905       String JavaDoc url = readString();
906
907       expectTag(TAG_REMOTE_END);
908
909       Object JavaDoc remote = resolveRemote(type, url);
910       
911       return remote;
912     }
913     }
914     
915     _peekTag = tag;
916
917     Object JavaDoc value = _serializerFactory.getDeserializer(cl).readObject(this);
918
919     return value;
920   }
921   
922   /**
923    * Reads an arbitrary object from the input stream when the type
924    * is unknown.
925    */

926   public Object JavaDoc readObject()
927     throws IOException JavaDoc
928   {
929     int tag = parseTag();
930
931     switch (tag) {
932     case TAG_NULL:
933       expectTag(TAG_NULL_END);
934       return null;
935       
936     case TAG_BOOLEAN:
937     {
938       int value = parseInt();
939       expectTag(TAG_BOOLEAN_END);
940       return new Boolean JavaDoc(value != 0);
941     }
942     
943     case TAG_INT:
944     {
945       int value = parseInt();
946       expectTag(TAG_INT_END);
947       return new Integer JavaDoc(value);
948     }
949     
950     case TAG_LONG:
951     {
952       long value = parseLong();
953       expectTag(TAG_LONG_END);
954       return new Long JavaDoc(value);
955     }
956     
957     case TAG_DOUBLE:
958     {
959       double value = parseDouble();
960       expectTag(TAG_DOUBLE_END);
961       return new Double JavaDoc(value);
962     }
963     
964     case TAG_DATE:
965     {
966       long value = parseDate();
967       expectTag(TAG_DATE_END);
968       return new Date JavaDoc(value);
969     }
970     
971     case TAG_XML:
972     {
973       return parseXML();
974     }
975
976     case TAG_STRING:
977     {
978       _sbuf.setLength(0);
979
980       String JavaDoc value = parseString(_sbuf).toString();
981
982       expectTag(TAG_STRING_END);
983
984       return value;
985     }
986
987     case TAG_BASE64:
988     {
989       byte []data = parseBytes();
990
991       expectTag(TAG_BASE64_END);
992
993       return data;
994     }
995
996     case TAG_LIST:
997     {
998       String JavaDoc type = readType();
999       int length = readLength();
1000
1001      return _serializerFactory.readList(this, length, type);
1002    }
1003
1004    case TAG_MAP:
1005    {
1006      String JavaDoc type = readType();
1007      Deserializer deserializer;
1008      deserializer = _serializerFactory.getObjectDeserializer(type);
1009
1010      return deserializer.readMap(this);
1011    }
1012
1013    case TAG_REF:
1014    {
1015      int ref = parseInt();
1016
1017      expectTag(TAG_REF_END);
1018
1019      return _refs.get(ref);
1020    }
1021
1022    case TAG_REMOTE:
1023    {
1024      String JavaDoc type = readType();
1025      String JavaDoc url = readString();
1026
1027      expectTag(TAG_REMOTE_END);
1028
1029      return resolveRemote(type, url);
1030    }
1031
1032    default:
1033      throw error("unknown code:" + tagName(tag));
1034    }
1035  }
1036
1037  /**
1038   * Reads a remote object.
1039   */

1040  public Object JavaDoc readRemote()
1041    throws IOException JavaDoc
1042  {
1043    String JavaDoc type = readType();
1044    String JavaDoc url = readString();
1045
1046    return resolveRemote(type, url);
1047  }
1048
1049  /**
1050   * Reads a reference.
1051   */

1052  public Object JavaDoc readRef()
1053    throws IOException JavaDoc
1054  {
1055    return _refs.get(parseInt());
1056  }
1057
1058  /**
1059   * Reads the start of a list.
1060   */

1061  public int readListStart()
1062    throws IOException JavaDoc
1063  {
1064    return parseTag();
1065  }
1066
1067  /**
1068   * Reads the start of a map.
1069   */

1070  public int readMapStart()
1071    throws IOException JavaDoc
1072  {
1073    return parseTag();
1074  }
1075
1076  /**
1077   * Returns true if this is the end of a list or a map.
1078   */

1079  public boolean isEnd()
1080    throws IOException JavaDoc
1081  {
1082    int code = parseTag();
1083
1084    _peekTag = code;
1085
1086    return (code < 0 || code >= 100);
1087  }
1088
1089  /**
1090   * Reads the end byte.
1091   */

1092  public void readEnd()
1093    throws IOException JavaDoc
1094  {
1095    int code = parseTag();
1096
1097    if (code < 100)
1098      throw error("unknown code:" + (char) code);
1099  }
1100
1101  /**
1102   * Reads the end of the map
1103   */

1104  public void readMapEnd()
1105    throws IOException JavaDoc
1106  {
1107    expectTag(TAG_MAP_END);
1108  }
1109
1110  /**
1111   * Reads the end of the map
1112   */

1113  public void readListEnd()
1114    throws IOException JavaDoc
1115  {
1116    expectTag(TAG_LIST_END);
1117  }
1118
1119  /**
1120   * Adds a list/map reference.