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.
1121   */

1122  public int addRef(Object JavaDoc ref)
1123  {
1124    if (_refs == null)
1125      _refs = new ArrayList JavaDoc();
1126    
1127    _refs.add(ref);
1128
1129    return _refs.size() - 1;
1130  }
1131
1132  /**
1133   * Adds a list/map reference.
1134   */

1135  public void setRef(int i, Object JavaDoc ref)
1136  {
1137    _refs.set(i, ref);
1138  }
1139
1140  /**
1141   * Resolves a remote object.
1142   */

1143  public Object JavaDoc resolveRemote(String JavaDoc type, String JavaDoc url)
1144    throws IOException JavaDoc
1145  {
1146    HessianRemoteResolver resolver = getRemoteResolver();
1147
1148    if (resolver != null)
1149      return resolver.lookup(type, url);
1150    else
1151      return new BurlapRemote(type, url);
1152  }
1153
1154  /**
1155   * Parses a type from the stream.
1156   *
1157   * <pre>
1158   * &lt;type>type&lt;/type>
1159   * </pre>
1160   */

1161  public String JavaDoc readType()
1162    throws IOException JavaDoc
1163  {
1164    int code = parseTag();
1165
1166    if (code != TAG_TYPE) {
1167      _peekTag = code;
1168      return "";
1169    }
1170
1171    _sbuf.setLength(0);
1172    int ch;
1173    while ((ch = readChar()) >= 0)
1174      _sbuf.append((char) ch);
1175    String JavaDoc type = _sbuf.toString();
1176    
1177    expectTag(TAG_TYPE_END);
1178
1179    return type;
1180  }
1181
1182  /**
1183   * Parses a 32-bit integer value from the stream.
1184   */

1185  private int parseInt()
1186    throws IOException JavaDoc
1187  {
1188    int sign = 1;
1189
1190    int ch = read();
1191    if (ch == '-') {
1192      sign = -1;
1193      ch = read();
1194    }
1195
1196    int value = 0;
1197    for (; ch >= '0' && ch <= '9'; ch = read())
1198      value = 10 * value + ch - '0';
1199
1200    _peek = ch;
1201
1202    return sign * value;
1203  }
1204
1205  /**
1206   * Parses a 64-bit long value from the stream.
1207   */

1208  private long parseLong()
1209    throws IOException JavaDoc
1210  {
1211    int sign = 1;
1212
1213    int ch = read();
1214    if (ch == '-') {
1215      sign = -1;
1216      ch = read();
1217    }
1218
1219    long value = 0;
1220    for (; ch >= '0' && ch <= '9'; ch = read())
1221      value = 10 * value + ch - '0';
1222
1223    _peek = ch;
1224
1225    return sign * value;
1226  }
1227  
1228  /**
1229   * Parses a 64-bit double value from the stream.
1230   *
1231   * <pre>
1232   * b64 b56 b48 b40 b32 b24 b16 b8
1233   * </pre>
1234   */

1235  private double parseDouble()
1236    throws IOException JavaDoc
1237  {
1238    int ch = skipWhitespace();
1239
1240    _sbuf.setLength(0);
1241    
1242    for (; ! isWhitespace(ch) && ch != '<'; ch = read())
1243      _sbuf.append((char) ch);
1244
1245    _peek = ch;
1246    
1247    return new Double JavaDoc(_sbuf.toString()).doubleValue();
1248  }
1249
1250  /**
1251   * Parses a date value from the stream.
1252   */

1253  protected long parseDate()
1254    throws IOException JavaDoc
1255  {
1256    if (_utcCalendar == null)
1257      _utcCalendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
1258
1259    return parseDate(_utcCalendar);
1260  }
1261
1262  /**
1263   * Parses a date value from the stream.
1264   */

1265  protected long parseDate(Calendar JavaDoc calendar)
1266    throws IOException JavaDoc
1267  {
1268    int ch = skipWhitespace();
1269    
1270    int year = 0;
1271    for (int i = 0; i < 4; i++) {
1272      if (ch >= '0' && ch <= '9')
1273        year = 10 * year + ch - '0';
1274      else
1275        throw expectedChar("year", ch);
1276
1277      ch = read();
1278    }
1279
1280    int month = 0;
1281    for (int i = 0; i < 2; i++) {
1282      if (ch >= '0' && ch <= '9')
1283        month = 10 * month + ch - '0';
1284      else
1285        throw expectedChar("month", ch);
1286
1287      ch = read();
1288    }
1289
1290    int day = 0;
1291    for (int i = 0; i < 2; i++) {
1292      if (ch >= '0' && ch <= '9')
1293        day = 10 * day + ch - '0';
1294      else
1295        throw expectedChar("day", ch);
1296
1297      ch = read();
1298    }
1299
1300    if (ch != 'T')
1301      throw expectedChar("`T'", ch);
1302
1303    ch = read();
1304
1305    int hour = 0;
1306    for (int i = 0; i < 2; i++) {
1307      if (ch >= '0' && ch <= '9')
1308        hour = 10 * hour + ch - '0';
1309      else
1310        throw expectedChar("hour", ch);
1311
1312      ch = read();
1313    }
1314
1315    int minute = 0;
1316    for (int i = 0; i < 2; i++) {
1317      if (ch >= '0' && ch <= '9')
1318        minute = 10 * minute + ch - '0';
1319      else
1320        throw expectedChar("minute", ch);
1321
1322      ch = read();
1323    }
1324
1325    int second = 0;
1326    for (int i = 0; i < 2; i++) {
1327      if (ch >= '0' && ch <= '9')
1328        second = 10 * second + ch - '0';
1329      else
1330        throw expectedChar("second", ch);
1331
1332      ch = read();
1333    }
1334
1335    int ms = 0;
1336    if (ch == '.') {
1337      ch = read();
1338
1339      while (ch >= '0' && ch <= '9') {
1340        ms = 10 * ms + ch - '0';
1341
1342    ch = read();
1343      }
1344    }
1345
1346    for (; ch > 0 && ch != '<'; ch = read()) {
1347    }
1348
1349    _peek = ch;
1350
1351    calendar.set(Calendar.YEAR, year);
1352    calendar.set(Calendar.MONTH, month - 1);
1353    calendar.set(Calendar.DAY_OF_MONTH, day);
1354    calendar.set(Calendar.HOUR_OF_DAY, hour);
1355    calendar.set(Calendar.MINUTE, minute);
1356    calendar.set(Calendar.SECOND, second);
1357    calendar.set(Calendar.MILLISECOND, ms);
1358
1359    return calendar.getTime().getTime();
1360  }
1361  
1362  protected String JavaDoc parseString()
1363    throws IOException JavaDoc
1364  {
1365    _sbuf.setLength(0);
1366
1367    return parseString(_sbuf).toString();
1368  }
1369  
1370  /**
1371   * Parses a string value from the stream. The burlap object's
1372   * string buffer is used for the result.
1373   */

1374  protected StringBuffer JavaDoc parseString(StringBuffer JavaDoc sbuf)
1375    throws IOException JavaDoc
1376  {
1377    int ch;
1378
1379    while ((ch = readChar()) >= 0)
1380      sbuf.append((char) ch);
1381
1382    return sbuf;
1383  }
1384
1385  org.w3c.dom.Node JavaDoc parseXML()
1386    throws IOException JavaDoc
1387  {
1388    throw error("help!");
1389  }
1390  
1391  /**
1392   * Reads a character from the underlying stream.
1393   */

1394  int readChar()
1395    throws IOException JavaDoc
1396  {
1397    int ch = read();
1398
1399    if (ch == '<' || ch < 0) {
1400      _peek = ch;
1401      return -1;
1402    }
1403    
1404    if (ch == '&') {
1405      ch = read();
1406
1407      if (ch == '#') {
1408        ch = read();
1409
1410        if (ch >= '0' && ch <= '9') {
1411          int v = 0;
1412          for (; ch >= '0' && ch <= '9'; ch = read()) {
1413            v = 10 * v + ch - '0';
1414          }
1415
1416          if (ch != ';')
1417            throw error("expected ';' at " + (char) ch);
1418
1419          return (char) v;
1420        }
1421        else
1422          throw error("expected digit at " + (char) ch);
1423      }
1424      else {
1425        _entityBuffer.setLength(0);
1426
1427        for (; ch >= 'a' && ch <= 'z'; ch = read())
1428          _entityBuffer.append((char) ch);
1429
1430        String JavaDoc entity = _entityBuffer.toString();
1431
1432        if (ch != ';')
1433          throw expectedChar("';'", ch);
1434        
1435        if (entity.equals("amp"))
1436          return '&';
1437        else if (entity.equals("apos"))
1438          return '\'';
1439        else if (entity.equals("quot"))
1440          return '"';
1441        else if (entity.equals("lt"))
1442          return '<';
1443        else if (entity.equals("gt"))
1444          return '>';
1445        else
1446          throw new BurlapProtocolException("unknown XML entity &" + entity + "; at `" + (char) ch + "'");
1447      }
1448    }
1449    else if (ch < 0x80)
1450      return (char) ch;
1451    else if ((ch & 0xe0) == 0xc0) {
1452      int ch1 = read();
1453      int v = ((ch & 0x1f) << 6) + (ch1 & 0x3f);
1454
1455      return (char) v;
1456    }
1457    else if ((ch & 0xf0) == 0xe0) {
1458      int ch1 = read();
1459      int ch2 = read();
1460      int v = ((ch & 0x0f) << 12) + ((ch1 & 0x3f) << 6) + (ch2 & 0x3f);
1461
1462      return (char) v;
1463    }
1464    else
1465      throw new BurlapProtocolException("bad utf-8 encoding");
1466  }
1467  
1468  /**
1469   * Parses a byte array.
1470   */

1471  protected byte []parseBytes()
1472    throws IOException JavaDoc
1473  {
1474    ByteArrayOutputStream JavaDoc bos = new ByteArrayOutputStream JavaDoc();
1475
1476    parseBytes(bos);
1477
1478    return bos.toByteArray();
1479  }
1480  
1481  /**
1482   * Parses a byte array.
1483   */

1484  protected ByteArrayOutputStream JavaDoc parseBytes(ByteArrayOutputStream JavaDoc bos)
1485    throws IOException JavaDoc
1486  {
1487    int ch;
1488    for (ch = skipWhitespace(); ch >= 0 && ch != '<'; ch = skipWhitespace()) {
1489      int b1 = ch;
1490      int b2 = read();
1491      int b3 = read();
1492      int b4 = read();
1493
1494      if (b4 != '=') {
1495        int chunk = ((base64Decode[b1] << 18) +
1496                     (base64Decode[b2] << 12) +
1497                     (base64Decode[b3] << 6) +
1498                     (base64Decode[b4]));
1499
1500        bos.write(chunk >> 16);
1501        bos.write(chunk >> 8);
1502        bos.write(chunk);
1503      }
1504      else if (b3 != '=') {
1505        int chunk = ((base64Decode[b1] << 10) +
1506                     (base64Decode[b2] << 4) +
1507                     (base64Decode[b3] >> 2));
1508
1509        bos.write(chunk >> 8);
1510        bos.write(chunk);
1511      }
1512      else {
1513        int chunk = ((base64Decode[b1] << 2) +
1514                     (base64Decode[b2] >> 4));
1515
1516        bos.write(chunk);
1517      }
1518    }
1519
1520    if (ch == '<')
1521      _peek = ch;
1522    
1523    return bos;
1524  }
1525  
1526  public void expectTag(int expectTag)
1527    throws IOException JavaDoc
1528  {
1529    int tag = parseTag();
1530
1531    if (tag != expectTag)
1532      throw error("expected " + tagName(expectTag) + " at " + tagName(tag));
1533  }
1534
1535  /**
1536   * Parses a tag. Returns true if it's a start tag.
1537   */

1538  protected int parseTag()
1539    throws IOException JavaDoc
1540  {
1541    if (_peekTag >= 0) {
1542      int tag = _peekTag;
1543      _peekTag = -1;
1544      return tag;
1545    }
1546    
1547    int ch = skipWhitespace();
1548    int endTagDelta = 0;
1549
1550    if (ch != '<')
1551      throw expectedChar("'<'", ch);
1552
1553    ch = read();
1554    if (ch == '/') {
1555      endTagDelta = 100;
1556      ch = _is.read();
1557    }
1558    
1559    if (! isTagChar(ch))
1560      throw expectedChar("tag", ch);
1561      
1562    _sbuf.setLength(0);
1563    for (; isTagChar(ch); ch = read())
1564      _sbuf.append((char) ch);
1565
1566    if (ch != '>')
1567      throw expectedChar("'>'", ch);
1568
1569    Integer JavaDoc value = (Integer JavaDoc) _tagMap.get(_sbuf.toString());
1570    if (value == null)
1571      throw error("Unknown tag <" + _sbuf + ">");
1572
1573    return value.intValue() + endTagDelta;
1574  }
1575
1576  /**
1577   * Returns true if the character is a valid tag character.
1578   */

1579  private boolean isTagChar(int ch)
1580  {
1581    return (ch >= 'a' && ch <= 'z' ||
1582            ch >= 'A' && ch <= 'Z' ||
1583            ch >= '0' && ch <= '9' ||
1584            ch == ':' || ch == '-');
1585  }
1586
1587  protected int skipWhitespace()
1588    throws IOException JavaDoc
1589  {
1590    int ch = read();
1591
1592    for (;
1593         ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r';
1594         ch = read()) {
1595    }
1596
1597    return ch;
1598  }
1599
1600  protected boolean isWhitespace(int ch)
1601    throws IOException JavaDoc
1602  {
1603    return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r';
1604  }
1605  
1606  /**
1607   * Reads bytes from the underlying stream.
1608   */

1609  int read(byte []buffer, int offset, int length)
1610    throws IOException JavaDoc
1611  {
1612    throw new UnsupportedOperationException JavaDoc();
1613  }
1614
1615  int read()
1616    throws IOException JavaDoc
1617  {
1618    if (_peek >= 0) {
1619      int value = _peek;
1620      _peek = -1;
1621      return value;
1622    }
1623
1624    int ch = _is.read();
1625    return ch;
1626  }
1627
1628  public Reader JavaDoc getReader()
1629  {
1630    return null;
1631  }
1632
1633  public InputStream JavaDoc readInputStream()
1634  {
1635    return null;
1636  }
1637
1638  public InputStream JavaDoc getInputStream()
1639  {
1640    return null;
1641  }
1642
1643  protected IOException JavaDoc expectBeginTag(String JavaDoc expect, String JavaDoc tag)
1644  {
1645    return new BurlapProtocolException("expected <" + expect + "> at <" + tag + ">");
1646  }
1647  
1648  protected IOException JavaDoc expectedChar(String JavaDoc expect, int ch)
1649  {
1650    if (ch < 0)
1651      return error("expected " + expect + " at end of file");
1652    else
1653      return error("expected " + expect + " at " + (char) ch);
1654  }
1655  
1656  protected IOException JavaDoc expectedTag(String JavaDoc expect, int tag)
1657  {
1658    return error("expected " + expect + " at " + tagName(tag));
1659  }
1660  
1661  protected IOException JavaDoc error(String JavaDoc message)
1662  {
1663    return new BurlapProtocolException(message);
1664  }
1665
1666  protected static String JavaDoc tagName(int tag)
1667  {
1668    switch (tag) {
1669    case TAG_NULL:
1670      return "<null>";
1671    case TAG_NULL_END:
1672      return "</null>";
1673      
1674    case TAG_BOOLEAN:
1675      return "<boolean>";
1676    case TAG_BOOLEAN_END:
1677      return "</boolean>";
1678      
1679    case TAG_INT:
1680      return "<int>";
1681    case TAG_INT_END:
1682      return "</int>";
1683      
1684    case TAG_LONG:
1685      return "<long>";
1686    case TAG_LONG_END:
1687      return "</long>";
1688      
1689    case TAG_DOUBLE:
1690      return "<double>";
1691    case TAG_DOUBLE_END:
1692      return "</double>";
1693      
1694    case TAG_STRING:
1695      return "<string>";
1696    case TAG_STRING_END:
1697      return "</string>";
1698      
1699    case TAG_XML:
1700      return "<xml>";
1701    case TAG_XML_END:
1702      return "</xml>";
1703      
1704    case TAG_BASE64:
1705      return "<base64>";
1706    case TAG_BASE64_END:
1707      return "</base64>";
1708      
1709    case TAG_MAP:
1710      return "<map>";
1711    case TAG_MAP_END:
1712      return "</map>";
1713      
1714    case TAG_LIST:
1715      return "<list>";
1716    case TAG_LIST_END:
1717      return "</list>";
1718      
1719    case TAG_TYPE:
1720      return "<type>";
1721    case TAG_TYPE_END:
1722      return "</type>";
1723      
1724    case TAG_LENGTH:
1725      return "<length>";
1726    case TAG_LENGTH_END:
1727      return "</length>";
1728      
1729    case TAG_REF:
1730      return "<ref>";
1731    case TAG_REF_END:
1732      return "</ref>";
1733      
1734    case TAG_REMOTE:
1735      return "<remote>";
1736    case TAG_REMOTE_END:
1737      return "</remote>";
1738      
1739    case TAG_CALL:
1740      return "<burlap:call>";
1741    case TAG_CALL_END:
1742      return "</burlap:call>";
1743      
1744    case TAG_REPLY:
1745      return "<burlap:reply>";
1746    case TAG_REPLY_END:
1747      return "</burlap:reply>";
1748      
1749    case TAG_HEADER:
1750      return "<header>";
1751    case TAG_HEADER_END:
1752      return "</header>";
1753      
1754    case TAG_FAULT:
1755      return "<fault>";
1756    case TAG_FAULT_END:
1757      return "</fault>";
1758
1759    case -1:
1760      return "end of file";
1761
1762    default:
1763      return "unknown " + tag;
1764    }
1765  }
1766      
1767
1768  static {
1769    _tagMap = new HashMap JavaDoc();
1770    _tagMap.put("null", new Integer JavaDoc(TAG_NULL));
1771    
1772    _tagMap.put("boolean", new Integer JavaDoc(TAG_BOOLEAN));
1773    _tagMap.put("int", new Integer JavaDoc(TAG_INT));
1774    _tagMap.put("long", new Integer JavaDoc(TAG_LONG));
1775    _tagMap.put("double", new Integer JavaDoc(TAG_DOUBLE));
1776    
1777    _tagMap.put("date", new Integer JavaDoc(TAG_DATE));
1778    
1779    _tagMap.put("string", new Integer JavaDoc(TAG_STRING));
1780    _tagMap.put("xml", new Integer JavaDoc(TAG_XML));
1781    _tagMap.put("base64", new Integer JavaDoc(TAG_BASE64));
1782    
1783    _tagMap.put("map", new Integer JavaDoc(TAG_MAP));
1784    _tagMap.put("list", new Integer JavaDoc(TAG_LIST));
1785    
1786    _tagMap.put("type", new Integer JavaDoc(TAG_TYPE));
1787    _tagMap.put("length", new Integer JavaDoc(TAG_LENGTH));
1788    
1789    _tagMap.put("ref", new Integer JavaDoc(TAG_REF));
1790    _tagMap.put("remote", new Integer JavaDoc(TAG_REMOTE));
1791    
1792    _tagMap.put("burlap:call", new Integer JavaDoc(TAG_CALL));
1793    _tagMap.put("burlap:reply", new Integer JavaDoc(TAG_REPLY));
1794    _tagMap.put("fault", new Integer JavaDoc(TAG_FAULT));
1795    _tagMap.put("method", new Integer JavaDoc(TAG_METHOD));
1796    _tagMap.put("header", new Integer JavaDoc(TAG_HEADER));
1797  }
1798  
1799  static {
1800    base64Decode = new int[256];
1801    for (int i = 'A'; i <= 'Z'; i++)
1802      base64Decode[i] = i - 'A';
1803    for (int i = 'a'; i <= 'z'; i++)
1804      base64Decode[i] = i - 'a' + 26;
1805    for (int i = '0'; i <= '9'; i++)
1806      base64Decode[i] = i - '0' + 52;
1807    base64Decode['+'] = 62;
1808    base64Decode['/'] = 63;
1809  }
1810
1811  static {
1812    try {
1813      _detailMessageField = Throwable JavaDoc.class.getDeclaredField("detailMessage");
1814      _detailMessageField.setAccessible(true);
1815    } catch (Throwable JavaDoc e) {
1816    }
1817  }
1818}
1819
Popular Tags