KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > hessian > io > Hessian2Input


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.hessian.io;
50
51 import java.io.ByteArrayOutputStream JavaDoc;
52 import java.io.IOException JavaDoc;
53 import java.io.InputStream JavaDoc;
54 import java.io.Reader JavaDoc;
55 import java.lang.reflect.Field JavaDoc;
56 import java.util.ArrayList JavaDoc;
57 import java.util.Date JavaDoc;
58 import java.util.HashMap JavaDoc;
59
60 /**
61  * Input stream for Hessian requests.
62  *
63  * <p>HessianInput is unbuffered, so any client needs to provide
64  * its own buffering.
65  *
66  * <pre>
67  * InputStream is = ...; // from http connection
68  * HessianInput in = new HessianInput(is);
69  * String value;
70  *
71  * in.startReply(); // read reply header
72  * value = in.readString(); // read string value
73  * in.completeReply(); // read reply footer
74  * </pre>
75  */

76 public class Hessian2Input
77   extends AbstractHessianInput
78   implements Hessian2Constants
79 {
80   private static final double D_256 = 1.0 / 256.0;
81   private static final int END_OF_DATA = -2;
82
83   private static Field JavaDoc _detailMessageField;
84   
85   // factory for deserializing objects in the input stream
86
protected SerializerFactory _serializerFactory;
87   
88   protected ArrayList JavaDoc _refs;
89   protected ArrayList JavaDoc _classDefs;
90   protected ArrayList JavaDoc _types;
91   
92   // the underlying input stream
93
private InputStream JavaDoc _is;
94
95   private static final int SIZE = 256;
96   private static final int GAP = 16;
97   private final byte []_buffer = new byte[SIZE];
98   // a peek character
99
private int _offset;
100   private int _length;
101   
102   // the method for a call
103
private String JavaDoc _method;
104
105   private Reader JavaDoc _chunkReader;
106   private InputStream JavaDoc _chunkInputStream;
107
108   private Throwable JavaDoc _replyFault;
109
110   private StringBuffer JavaDoc _sbuf = new StringBuffer JavaDoc();
111   
112   // true if this is the last chunk
113
private boolean _isLastChunk;
114   // the chunk length
115
private int _chunkLength;
116   
117   /**
118    * Creates a new Hessian input stream, initialized with an
119    * underlying input stream.
120    *
121    * @param is the underlying input stream.
122    */

123   public Hessian2Input(InputStream JavaDoc is)
124   {
125     _is = is;
126   }
127
128   /**
129    * Sets the serializer factory.
130    */

131   public void setSerializerFactory(SerializerFactory factory)
132   {
133     _serializerFactory = factory;
134   }
135
136   /**
137    * Gets the serializer factory.
138    */

139   public SerializerFactory getSerializerFactory()
140   {
141     return _serializerFactory;
142   }
143
144   /**
145    * Gets the serializer factory, creating a default if necessary.
146    */

147   protected final SerializerFactory findSerializerFactory()
148   {
149     SerializerFactory factory = _serializerFactory;
150
151     if (factory == null)
152       _serializerFactory = factory = new SerializerFactory();
153     
154     return factory;
155   }
156
157   /**
158    * Returns the calls method
159    */

160   public String JavaDoc getMethod()
161   {
162     return _method;
163   }
164
165   /**
166    * Returns any reply fault.
167    */

168   public Throwable JavaDoc getReplyFault()
169   {
170     return _replyFault;
171   }
172
173   /**
174    * Starts reading the call
175    *
176    * <pre>
177    * c major minor
178    * </pre>
179    */

180   public int readCall()
181     throws IOException JavaDoc
182   {
183     int tag = read();
184     
185     if (tag != 'c')
186       throw error("expected hessian call ('c') at code=" + tag + " ch=" + (char) tag);
187
188     int major = read();
189     int minor = read();
190
191     return (major << 16) + minor;
192   }
193
194   /**
195    * Starts reading the call
196    *
197    * <p>A successful completion will have a single value:
198    *
199    * <pre>
200    * m b16 b8 method
201    * </pre>
202    */

203   public String JavaDoc readMethod()
204     throws IOException JavaDoc
205   {
206     int tag = read();
207     
208     if (tag != 'm')
209       throw error("expected hessian method ('m') at code=" + tag + " ch=" + (char) tag);
210     int d1 = read();
211     int d2 = read();
212
213     _isLastChunk = true;
214     _chunkLength = d1 * 256 + d2;
215     _sbuf.setLength(0);
216     int ch;
217     while ((ch = parseChar()) >= 0)
218       _sbuf.append((char) ch);
219     
220     _method = _sbuf.toString();
221
222     return _method;
223   }
224
225   /**
226    * Starts reading the call, including the headers.
227    *
228    * <p>The call expects the following protocol data
229    *
230    * <pre>
231    * c major minor
232    * m b16 b8 method
233    * </pre>
234    */

235   public void startCall()
236     throws IOException JavaDoc
237   {
238     readCall();
239
240     while (readHeader() != null) {
241       readObject();
242     }
243
244     readMethod();
245   }
246
247   /**
248    * Completes reading the call
249    *
250    * <p>A successful completion will have a single value:
251    *
252    * <pre>
253    * z
254    * </pre>
255    */

256   public void completeCall()
257     throws IOException JavaDoc
258   {
259     int tag = read();
260
261     if (tag == 'z') {
262     }
263     else if (tag < 0)
264       throw error("expected end of call ('z') at end of stream.");
265     else
266       throw error("expected end of call ('z') at '" + (char) tag + "'. Check method arguments and ensure method overloading is enabled if necessary");
267   }
268
269   /**
270    * Reads a reply as an object.
271    * If the reply has a fault, throws the exception.
272    */

273   public Object JavaDoc readReply(Class JavaDoc expectedClass)
274     throws Throwable JavaDoc
275   {
276     int tag = read();
277     
278     if (tag != 'r')
279       error("expected hessian reply");
280
281     int major = read();
282     int minor = read();
283
284     tag = read();
285     if (tag == 'f')
286       throw prepareFault();
287     else {
288       if (tag >= 0)
289     _offset--;
290     
291       Object JavaDoc value = readObject(expectedClass);
292       
293       completeValueReply();
294       
295       return value;
296     }
297   }
298
299   /**
300    * Starts reading the reply
301    *
302    * <p>A successful completion will have a single value:
303    *
304    * <pre>
305    * r
306    * </pre>
307    */

308   public void startReply()
309     throws Throwable JavaDoc
310   {
311     int tag = read();
312     
313     if (tag != 'r')
314       error("expected hessian reply");
315
316     int major = read();
317     int minor = read();
318     
319     tag = read();
320     if (tag == 'f')
321       throw prepareFault();
322     else if (tag >= 0)
323       _offset--;
324   }
325
326   /**
327    * Prepares the fault.
328    */

329   private Throwable JavaDoc prepareFault()
330     throws IOException JavaDoc
331   {
332     HashMap JavaDoc fault = readFault();
333
334     Object JavaDoc detail = fault.get("detail");
335     String JavaDoc message = (String JavaDoc) fault.get("message");
336
337     if (detail instanceof Throwable JavaDoc) {
338       _replyFault = (Throwable JavaDoc) detail;
339       
340       if (message != null && _detailMessageField != null) {
341     try {
342       _detailMessageField.set(_replyFault, message);
343     } catch (Throwable JavaDoc e) {
344     }
345       }
346     
347       return _replyFault;
348     }
349
350     else {
351       String JavaDoc code = (String JavaDoc) fault.get("code");
352         
353       _replyFault = new HessianServiceException(message, code, detail);
354
355       return _replyFault;
356     }
357   }
358
359   /**
360    * Completes reading the call
361    *
362    * <p>A successful completion will have a single value:
363    *
364    * <pre>
365    * z
366    * </pre>
367    */

368   public void completeReply()
369     throws IOException JavaDoc
370   {
371     int tag = read();
372     
373     if (tag != 'z')
374       error("expected end of reply");
375   }
376
377   /**
378    * Completes reading the call
379    *
380    * <p>A successful completion will have a single value:
381    *
382    * <pre>
383    * z
384    * </pre>
385    */

386   public void completeValueReply()
387     throws IOException JavaDoc
388   {
389     int tag = read();
390     
391     if (tag != 'z')
392       error("expected end of reply");
393   }
394
395   /**
396    * Reads a header, returning null if there are no headers.
397    *
398    * <pre>
399    * H b16 b8 value
400    * </pre>
401    */

402   public String JavaDoc readHeader()
403     throws IOException JavaDoc
404   {
405     int tag = read();
406
407     if (tag == 'H') {
408       _isLastChunk = true;
409       _chunkLength = (read() << 8) + read();
410
411       _sbuf.setLength(0);
412       int ch;
413       while ((ch = parseChar()) >= 0)
414         _sbuf.append((char) ch);
415
416       return _sbuf.toString();
417     }
418
419     if (tag >= 0)
420       _offset--;
421
422     return null;
423   }
424
425   /**
426    * Reads a null
427    *
428    * <pre>
429    * N
430    * </pre>
431    */

432   public void readNull()
433     throws IOException JavaDoc
434   {
435     int tag = read();
436
437     switch (tag) {
438     case 'N': return;
439       
440     default:
441       throw expect("null", tag);
442     }
443   }
444
445   /**
446    * Reads a boolean
447    *
448    * <pre>
449    * T
450    * F
451    * </pre>
452    */

453   public boolean readBoolean()
454     throws IOException JavaDoc
455   {
456     int tag = _offset < _length ? (_buffer[_offset++] & 0xff) : read();
457
458     switch (tag) {
459     case 'T': return true;
460     case 'F': return false;
461
462       // direct integer
463
case 0x80: case 0x81: case 0x82: case 0x83:
464     case 0x84: case 0x85: case 0x86: case 0x87:
465     case 0x88: case 0x89: case 0x8a: case 0x8b:
466     case 0x8c: case 0x8d: case 0x8e: case 0x8f:
467       
468     case 0x90: case 0x91: case 0x92: case 0x93:
469     case 0x94: case 0x95: case 0x96: case 0x97:
470     case 0x98: case 0x99: case 0x9a: case 0x9b:
471     case 0x9c: case 0x9d: case 0x9e: case 0x9f:
472       
473     case 0xa0: case 0xa1: case 0xa2: case 0xa3:
474     case 0xa4: case 0xa5: case 0xa6: case 0xa7:
475     case 0xa8: case 0xa9: case 0xaa: case 0xab:
476     case 0xac: case 0xad: case 0xae: case 0xaf:
477
478     case 0xb0: case 0xb1: case 0xb2: case 0xb3:
479     case 0xb4: case 0xb5: case 0xb6: case 0xb7:
480     case 0xb8: case 0xb9: case 0xba: case 0xbb:
481     case 0xbc: case 0xbd: case 0xbe: case 0xbf:
482       return tag != INT_ZERO;
483
484       // INT_BYTE = 0
485
case 0xc8:
486       return read() != 0;
487       
488       // INT_BYTE != 0
489
case 0xc0: case 0xc1: case 0xc2: case 0xc3:
490     case 0xc4: case 0xc5: case 0xc6: case 0xc7:
491     case 0xc9: case 0xca: case 0xcb:
492     case 0xcc: case 0xcd: case 0xce: case 0xcf:
493       read();
494       return true;
495
496       // INT_SHORT = 0
497
case 0xd4:
498       return (256 * read() + read()) != 0;
499       
500       // INT_SHORT != 0
501
case 0xd0: case 0xd1: case 0xd2: case 0xd3:
502     case 0xd5: case 0xd6: case 0xd7:
503       read();
504       read();
505       return true;
506       
507     case 'I': return
508     parseInt() != 0;
509       
510     case 0xd8: case 0xd9: case 0xda: case 0xdb:
511     case 0xdc: case 0xdd: case 0xde: case 0xdf:
512       
513     case 0xe0: case 0xe1: case 0xe2: case 0xe3:
514     case 0xe4: case 0xe5: case 0xe6: case 0xe7:
515     case 0xe8: case 0xe9: case 0xea: case 0xeb:
516     case 0xec: case 0xed: case 0xee: case 0xef:
517       return tag != LONG_ZERO;
518
519       // LONG_BYTE = 0
520
case 0xf8:
521       return read() != 0;
522       
523       // LONG_BYTE != 0
524
case 0xf0: case 0xf1: case 0xf2: case 0xf3:
525     case 0xf4: case 0xf5: case 0xf6: case 0xf7:
526     case 0xf9: case 0xfa: case 0xfb:
527     case 0xfc: case 0xfd: case 0xfe: case 0xff:
528       read();
529       return true;
530
531       // INT_SHORT = 0
532
case 0x3c:
533       return (256 * read() + read()) != 0;
534       
535       // INT_SHORT != 0
536
case 0x38: case 0x39: case 0x3a: case 0x3b:
537     case 0x3d: case 0x3e: case 0x3f:
538       read();
539       read();
540       return true;
541
542     case LONG_INT:
543       return (0x1000000L * read()
544           + 0x10000L * read()
545           + 0x100 * read()
546           + read()) != 0;
547       
548     case 'L':
549       return parseLong() != 0;
550
551     case DOUBLE_ZERO:
552       return false;
553       
554     case DOUBLE_ONE:
555       return true;
556       
557     case DOUBLE_BYTE:
558       return read() != 0;
559       
560     case DOUBLE_SHORT:
561       return (0x100 * read() + read()) != 0;
562       
563     case DOUBLE_INT:
564       return (0x1000000L * read()
565           + 0x10000L * read()
566           + 0x100 * read()
567           + read()) != 0;
568       
569     case DOUBLE_256_SHORT:
570       return (0x100 * read() + read()) != 0;
571       
572     case 'D':
573       return parseDouble() != 0.0;
574       
575     case 'N':
576       return false;
577       
578     default:
579       throw expect("boolean", tag);
580     }
581   }
582
583   /**
584    * Reads a short
585    *
586    * <pre>
587    * I b32 b24 b16 b8
588    * </pre>
589    */

590   public short readShort()
591     throws IOException JavaDoc
592   {
593     return (short) readInt();
594   }
595
596   /**
597    * Reads an integer
598    *
599    * <pre>
600    * I b32 b24 b16 b8
601    * </pre>
602    */

603   public final int readInt()
604     throws IOException JavaDoc
605   {
606     //int tag = _offset < _length ? (_buffer[_offset++] & 0xff) : read();
607
int tag = read();
608
609     switch (tag) {
610     case 'N':
611       return 0;
612       
613     case 'F':
614       return 0;
615       
616     case 'T':
617       return 1;
618
619       // direct integer
620
case 0x80: case 0x81: case 0x82: case 0x83:
621     case 0x84: case 0x85: case 0x86: case 0x87:
622     case 0x88: case 0x89: case 0x8a: case 0x8b:
623     case 0x8c: case 0x8d: case 0x8e: case 0x8f:
624       
625     case 0x90: case 0x91: case 0x92: case 0x93:
626     case 0x94: case 0x95: case 0x96: case 0x97:
627     case 0x98: case 0x99: case 0x9a: case 0x9b:
628     case 0x9c: case 0x9d: case 0x9e: case 0x9f:
629       
630     case 0xa0: case 0xa1: case 0xa2: case 0xa3:
631     case 0xa4: case 0xa5: case 0xa6: case 0xa7:
632     case 0xa8: case 0xa9: case 0xaa: case 0xab:
633     case 0xac: case 0xad: case 0xae: case 0xaf:
634       
635     case 0xb0: case 0xb1: case 0xb2: case 0xb3:
636     case 0xb4: case 0xb5: case 0xb6: case 0xb7:
637     case 0xb8: case 0xb9: case 0xba: case 0xbb:
638     case 0xbc: case 0xbd: case 0xbe: case 0xbf:
639       return tag - INT_ZERO;
640
641       /* byte int */
642     case 0xc0: case 0xc1: case 0xc2: case 0xc3:
643     case 0xc4: case 0xc5: case 0xc6: case 0xc7:
644     case 0xc8: case 0xc9: case 0xca: case 0xcb:
645     case 0xcc: case 0xcd: case 0xce: case 0xcf:
646       return ((tag - INT_BYTE_ZERO) << 8) + read();
647       
648       /* short int */
649     case 0xd0: case 0xd1: case 0xd2: case 0xd3:
650     case 0xd4: case 0xd5: case 0xd6: case 0xd7:
651       return ((tag - INT_SHORT_ZERO) << 16) + 256 * read() + read();
652
653     case 'I':
654     case LONG_INT:
655     case DOUBLE_INT:
656       return ((read() << 24)
657           + (read() << 16)
658           + (read() << 8)
659           + read());
660
661       // direct long
662
case 0xd8: case 0xd9: case 0xda: case 0xdb:
663     case 0xdc: case 0xdd: case 0xde: case 0xdf:
664       
665     case 0xe0: case 0xe1: case 0xe2: case 0xe3:
666     case 0xe4: case 0xe5: case 0xe6: case 0xe7:
667     case 0xe8: case 0xe9: case 0xea: case 0xeb:
668     case 0xec: case 0xed: case 0xee: case 0xef:
669       return tag - LONG_ZERO;
670
671       /* byte long */
672     case 0xf0: case 0xf1: case 0xf2: case 0xf3:
673     case 0xf4: case 0xf5: case 0xf6: case 0xf7:
674     case 0xf8: case 0xf9: case 0xfa: case 0xfb:
675     case 0xfc: case 0xfd: case 0xfe: case 0xff:
676       return ((tag - LONG_BYTE_ZERO) << 8) + read();
677       
678       /* short long */
679     case 0x38: case 0x39: case 0x3a: case 0x3b:
680     case 0x3c: case 0x3d: case 0x3e: case 0x3f:
681       return ((tag - LONG_SHORT_ZERO) << 16) + 256 * read() + read();
682
683     case 'L':
684       return (int) parseLong();
685
686       //case LONG_BYTE:
687
case DOUBLE_BYTE:
688       return (byte) (_offset < _length ? _buffer[_offset++] : read());
689
690       //case INT_SHORT:
691
//case LONG_SHORT:
692
case DOUBLE_SHORT:
693       return (short) (256 * read() + read());
694
695     case DOUBLE_ZERO:
696       return 0;
697
698     case DOUBLE_ONE:
699       return 1;
700
701     case DOUBLE_256_SHORT:
702       return ((short) (256 * read() + read())) >> 8;
703       
704     case 'D':
705       return (int) parseDouble();
706       
707     default:
708       throw expect("int", tag);
709     }
710   }
711
712   /**
713    * Reads a long
714    *
715    * <pre>
716    * L b64 b56 b48 b40 b32 b24 b16 b8
717    * </pre>
718    */

719   public long readLong()
720     throws IOException JavaDoc
721   {
722     int tag = read();
723
724     switch (tag) {
725     case 'N':
726       return 0;
727       
728     case 'F':
729       return 0;
730       
731     case 'T':
732       return 1;
733
734       // direct integer
735
case 0x80: case 0x81: case 0x82: case 0x83:
736     case 0x84: case 0x85: case 0x86: case 0x87:
737     case 0x88: case 0x89: case 0x8a: case 0x8b:
738     case 0x8c: case 0x8d: case 0x8e: case 0x8f:
739       
740     case 0x90: case 0x91: case 0x92: case 0x93:
741     case 0x94: case 0x95: case 0x96: case 0x97:
742     case 0x98: case 0x99: case 0x9a: case 0x9b:
743     case 0x9c: case 0x9d: case 0x9e: case 0x9f:
744       
745     case 0xa0: case 0xa1: case 0xa2: case 0xa3:
746     case 0xa4: case 0xa5: case 0xa6: case 0xa7:
747     case 0xa8: case 0xa9: case 0xaa: case 0xab:
748     case 0xac: case 0xad: case 0xae: case 0xaf:
749       
750     case 0xb0: case 0xb1: case 0xb2: case 0xb3:
751     case 0xb4: case 0xb5: case 0xb6: case 0xb7:
752     case 0xb8: case 0xb9: case 0xba: case 0xbb:
753     case 0xbc: case 0xbd: case 0xbe: case 0xbf:
754       return tag - INT_ZERO;
755
756       /* byte int */
757     case 0xc0: case 0xc1: case 0xc2: case 0xc3:
758     case 0xc4: case 0xc5: case 0xc6: case 0xc7:
759     case 0xc8: case 0xc9: case 0xca: case 0xcb:
760     case 0xcc: case 0xcd: case 0xce: case 0xcf:
761       return ((tag - INT_BYTE_ZERO) << 8) + read();
762       
763       /* short int */
764     case 0xd0: case 0xd1: case 0xd2: case 0xd3:
765     case 0xd4: case 0xd5: case 0xd6: case 0xd7:
766       return ((tag - INT_SHORT_ZERO) << 16) + 256 * read() + read();
767
768       //case LONG_BYTE:
769
case DOUBLE_BYTE:
770       return (byte) (_offset < _length ? _buffer[_offset++] : read());
771
772       //case INT_SHORT:
773
//case LONG_SHORT:
774
case DOUBLE_SHORT:
775       return (short) (256 * read() + read());
776
777     case 'I':
778     case LONG_INT:
779     case DOUBLE_INT:
780       return parseInt();
781
782       // direct long
783
case 0xd8: case 0xd9: case 0xda: case 0xdb:
784     case 0xdc: case 0xdd: case 0xde: case 0xdf:
785       
786     case 0xe0: case 0xe1: case 0xe2: case 0xe3:
787     case 0xe4: case 0xe5: case 0xe6: case 0xe7:
788     case 0xe8: case 0xe9: case 0xea: case 0xeb:
789     case 0xec: case 0xed: case 0xee: case 0xef:
790       return tag - LONG_ZERO;
791
792       /* byte long */
793     case 0xf0: case 0xf1: case 0xf2: case 0xf3:
794     case 0xf4: case 0xf5: case 0xf6: case 0xf7:
795     case 0xf8: case 0xf9: case 0xfa: case 0xfb:
796     case 0xfc: case 0xfd: case 0xfe: case 0xff:
797       return ((tag - LONG_BYTE_ZERO) << 8) + read();
798       
799       /* short long */
800     case 0x38: case 0x39: case 0x3a: case 0x3b:
801     case 0x3c: case 0x3d: case 0x3e: case 0x3f:
802       return ((tag - LONG_SHORT_ZERO) << 16) + 256 * read() + read();
803
804     case 'L':
805       return parseLong();
806
807     case DOUBLE_ZERO:
808       return 0;
809
810     case DOUBLE_ONE:
811       return 1;
812
813     case DOUBLE_256_SHORT:
814       return ((short) (256 * read() + read())) >> 8;
815       
816     case 'D':
817       return (long) parseDouble();
818       
819     default:
820       throw expect("long", tag);
821     }
822   }
823
824   /**
825    * Reads a float
826    *
827    * <pre>
828    * D b64 b56 b48 b40 b32 b24 b16 b8
829    * </pre>
830    */

831   public float readFloat()
832     throws IOException JavaDoc
833   {
834     return (float) readDouble();
835   }
836
837   /**
838    * Reads a double
839    *
840    * <pre>
841    * D b64 b56 b48 b40 b32 b24 b16 b8
842    * </pre>
843    */

844   public double readDouble()
845     throws IOException JavaDoc
846   {
847     int tag = read();
848
849     switch (tag) {
850     case 'N':
851       return 0;
852       
853     case 'F':
854       return 0;
855       
856     case 'T':
857       return 1;
858
859       // direct integer
860
case 0x80: case 0x81: case 0x82: case 0x83:
861     case 0x84: case 0x85: case 0x86: case 0x87:
862     case 0x88: case 0x89: case 0x8a: case 0x8b:
863     case 0x8c: case 0x8d: case 0x8e: case 0x8f:
864       
865     case 0x90: case 0x91: case 0x92: case 0x93:
866     case 0x94: case 0x95: case 0x96: case 0x97:
867     case 0x98: case 0x99: case 0x9a: case 0x9b:
868     case 0x9c: case 0x9d: case 0x9e: case 0x9f:
869       
870     case 0xa0: case 0xa1: case 0xa2: case 0xa3:
871     case 0xa4: case 0xa5: case 0xa6: case 0xa7:
872     case 0xa8: case 0xa9: case 0xaa: case 0xab:
873     case 0xac: case 0xad: case 0xae: case 0xaf:
874       
875     case 0xb0: case 0xb1: case 0xb2: case 0xb3:
876     case 0xb4: case 0xb5: case 0xb6: case 0xb7:
877     case 0xb8: case 0xb9: case 0xba: case 0xbb:
878     case 0xbc: case 0xbd: case 0xbe: case 0xbf:
879       return tag - 0x90;
880
881       /* byte int */
882     case 0xc0: case 0xc1: case 0xc2: case 0xc3:
883     case 0xc4: case 0xc5: case 0xc6: case 0xc7:
884     case 0xc8: case 0xc9: case 0xca: case 0xcb:
885     case 0xcc: case 0xcd: case 0xce: case 0xcf:
886       return ((tag - INT_BYTE_ZERO) << 8) + read();
887       
888       /* short int */
889     case 0xd0: case 0xd1: case 0xd2: case 0xd3:
890     case 0xd4: case 0xd5: case 0xd6: case 0xd7:
891       return ((tag - INT_SHORT_ZERO) << 16) + 256 * read() + read();
892
893     case 'I':
894     case LONG_INT:
895     case DOUBLE_INT:
896       return parseInt();
897
898       // direct long
899
case 0xd8: case 0xd9: case 0xda: case 0xdb:
900     case 0xdc: case 0xdd: case 0xde: case 0xdf:
901       
902     case 0xe0: case 0xe1: case 0xe2: case 0xe3:
903     case 0xe4: case 0xe5: case 0xe6: case 0xe7:
904     case 0xe8: case 0xe9: case 0xea: case 0xeb:
905     case 0xec: case 0xed: case 0xee: case 0xef:
906       return tag - LONG_ZERO;
907
908       /* byte long */
909     case 0xf0: case 0xf1: case 0xf2: case 0xf3:
910     case 0xf4: case 0xf5: case 0xf6: case 0xf7:
911     case 0xf8: case 0xf9: case 0xfa: case 0xfb:
912     case 0xfc: case 0xfd: case 0xfe: case 0xff:
913       return ((tag - LONG_BYTE_ZERO) << 8) + read();
914       
915       /* short long */
916     case 0x38: case 0x39: case 0x3a: case 0x3b:
917     case 0x3c: case 0x3d: case 0x3e: case 0x3f:
918       return ((tag - LONG_SHORT_ZERO) << 16) + 256 * read() + read();
919
920     case 'L':
921       return (double) parseLong();
922
923     case DOUBLE_ZERO:
924       return 0;
925
926     case DOUBLE_ONE:
927       return 1;
928
929     case DOUBLE_BYTE:
930       return (byte) (_offset < _length ? _buffer[_offset++] : read());
931
932     case DOUBLE_SHORT:
933       return (short) (256 * read() + read());
934
935     case DOUBLE_256_SHORT:
936       return D_256 * ((short) (256 * read() + read()));
937
938     case DOUBLE_FLOAT:
939       {
940     int f = parseInt();
941
942     return Float.intBitsToFloat(f);
943       }
944       
945     case 'D':
946       return parseDouble();
947       
948     default:
949       throw expect("double", tag);
950     }
951   }
952
953   /**
954    * Reads a date.
955    *
956    * <pre>
957    * T b64 b56 b48 b40 b32 b24 b16 b8
958    * </pre>
959    */

960   public long readUTCDate()
961     throws IOException JavaDoc
962   {
963     int tag = read();
964
965     if (tag != 'd')
966       throw error("expected date");
967
968     long b64 = read();
969     long b56 = read();
970     long b48 = read();
971     long b40 = read();
972     long b32 = read();
973     long b24 = read();
974     long b16 = read();
975     long b8 = read();
976
977     return ((b64 << 56) +
978             (b56 << 48) +
979             (b48 << 40) +
980             (b40 << 32) +
981             (b32 << 24) +
982             (b24 << 16) +
983             (b16 << 8) +
984             b8);
985   }
986
987   /**
988    * Reads a byte from the stream.
989    */

990   public int readChar()
991     throws IOException JavaDoc
992   {
993     if (_chunkLength > 0) {
994       _chunkLength--;
995       if (_chunkLength == 0 && _isLastChunk)
996         _chunkLength = END_OF_DATA;
997
998       int ch = parseUTF8Char();
999       return ch;
1000    }
1001    else if (_chunkLength == END_OF_DATA) {
1002      _chunkLength = 0;
1003      return -1;
1004    }
1005    
1006    int tag = read();
1007
1008    switch (tag) {
1009    case 'N':
1010      return -1;
1011
1012    case 'S':
1013    case 's':
1014    case 'X':
1015    case 'x':
1016      _isLastChunk = tag == 'S' || tag == 'X';
1017      _chunkLength = (read() << 8) + read();
1018
1019      _chunkLength--;
1020      int value = parseUTF8Char();
1021
1022      // special code so successive read byte won't
1023
// be read as a single object.
1024
if (_chunkLength == 0 && _isLastChunk)
1025        _chunkLength = END_OF_DATA;
1026
1027      return value;
1028      
1029    default:
1030      throw new IOException JavaDoc("expected 'S' at " + (char) tag);
1031    }
1032  }
1033
1034  /**
1035   * Reads a byte array from the stream.
1036   */

1037  public int readString(char []buffer, int offset, int length)
1038    throws IOException JavaDoc
1039  {
1040    int readLength = 0;
1041
1042    if (_chunkLength == END_OF_DATA) {
1043      _chunkLength = 0;
1044      return -1;
1045    }
1046    else if (_chunkLength == 0) {
1047      int tag = read();
1048
1049      switch (tag) {
1050      case 'N':
1051        return -1;
1052      
1053      case 'S':
1054      case 's':
1055      case 'X':
1056      case 'x':
1057        _isLastChunk = tag == 'S' || tag == 'X';
1058        _chunkLength = (read() << 8) + read();
1059        break;
1060
1061      case 0x00: case 0x01: case 0x02: case 0x03:
1062      case 0x04: case 0x05: case 0x06: case 0x07:
1063      case 0x08: case 0x09: case 0x0a: case 0x0b:
1064      case 0x0c: case 0x0d: case 0x0e: case 0x0f:
1065
1066      case 0x10: case 0x11: case 0x12: case 0x13:
1067      case 0x14: case 0x15: case 0x16: case 0x17:
1068      case 0x18: case 0x19: case 0x1a: case 0x1b:
1069      case 0x1c: case 0x1d: case 0x1e: case 0x1f:
1070    _isLastChunk = true;
1071    _chunkLength = tag - 0x00;
1072    break;
1073
1074      default:
1075        throw new IOException JavaDoc("expected 'S' at " + (char) tag);
1076      }
1077    }
1078
1079    while (length > 0) {
1080      if (_chunkLength > 0) {
1081        buffer[offset++] = (char) parseUTF8Char();
1082        _chunkLength--;
1083        length--;
1084        readLength++;
1085      }
1086      else if (_isLastChunk) {
1087        if (readLength == 0)
1088          return -1;
1089        else {
1090          _chunkLength = END_OF_DATA;
1091          return readLength;
1092        }
1093      }
1094      else {
1095        int tag = read();
1096
1097        switch (tag) {
1098        case 'S':
1099        case 's':
1100        case 'X':
1101        case 'x':
1102          _isLastChunk = tag == 'S' || tag == 'X';
1103          _chunkLength = (read() << 8) + read();
1104          break;
1105      
1106        default:
1107          throw new IOException JavaDoc("expected 'S' at " + (char) tag);
1108        }
1109      }
1110    }
1111    
1112    if (readLength == 0)
1113      return -1;
1114    else if (_chunkLength > 0 || ! _isLastChunk)
1115      return readLength;
1116    else {
1117      _chunkLength = END_OF_DATA;
1118      return readLength;
1119    }
1120  }
1121
1122  /**
1123   * Reads a string
1124   *
1125   * <pre>
1126   * S b16 b8 string value
1127   * </pre>
1128   */

1129  public String JavaDoc readString()
1130    throws IOException JavaDoc
1131  {
1132    int tag = read();
1133
1134    switch (tag) {
1135    case 'N':
1136      return null;
1137
1138    case 'I':
1139      return String.valueOf(parseInt());
1140    case 'L':
1141      return String.valueOf(parseLong());
1142    case 'D':
1143      return String.valueOf(parseDouble());
1144
1145    case 'S':
1146    case 's':
1147    case 'X':
1148    case 'x':
1149      _isLastChunk = tag == 'S' || tag == 'X';
1150      _chunkLength = (read() << 8) + read();
1151
1152      _sbuf.setLength(0);
1153      int ch;
1154
1155      while ((ch = parseChar()) >= 0)
1156        _sbuf.append((char) ch);
1157
1158      return _sbuf.toString();
1159
1160      // 0-byte string
1161
case 0x00: case 0x01: case 0x02: case 0x03:
1162    case 0x04: case 0x05: case 0x06: case 0x07:
1163    case 0x08: case 0x09: case 0x0a: case 0x0b:
1164    case 0x0c: case 0x0d: case 0x0e: case 0x0f:
1165
1166    case 0x10: case 0x11: case 0x12: case 0x13:
1167    case 0x14: case 0x15: case 0x16: case 0x17:
1168    case 0x18: case 0x19: case 0x1a: case 0x1b:
1169    case 0x1c: case 0x1d: case 0x1e: case 0x1f:
1170      _isLastChunk = true;
1171      _chunkLength = tag - 0x00;
1172
1173      _sbuf.setLength(0);
1174
1175      while ((ch = parseChar()) >= 0)
1176        _sbuf.append((char) ch);
1177
1178      return _sbuf.toString();
1179
1180    default:
1181      throw expect("string", tag);
1182    }
1183  }
1184
1185  /**
1186   * Reads an XML node.
1187   *
1188   * <pre>
1189   * S b16 b8 string value
1190   * </pre>
1191   */

1192  public org.w3c.dom.Node JavaDoc readNode()
1193    throws IOException JavaDoc
1194  {
1195    int tag = read();
1196
1197    switch (tag) {
1198    case 'N':
1199      return null;
1200
1201    case 'S':
1202    case 's':
1203    case 'X':
1204    case 'x':
1205      _isLastChunk = tag == 'S' || tag == 'X';
1206      _chunkLength = (read() << 8) + read();
1207
1208      throw error("can't cope");
1209
1210    case 0x00: case 0x01: case 0x02: case 0x03:
1211    case 0x04: case 0x05: case 0x06: case 0x07:
1212    case 0x08: case 0x09: case 0x0a: case 0x0b:
1213    case 0x0c: case 0x0d: case 0x0e: case 0x0f:
1214
1215    case 0x10: case 0x11: case 0x12: case 0x13:
1216    case 0x14: case 0x15: case 0x16: case 0x17:
1217    case 0x18: case 0x19: case 0x1a: case 0x1b:
1218    case 0x1c: case 0x1d: case 0x1e: case 0x1f:
1219      _isLastChunk = true;
1220      _chunkLength = tag - 0x00;
1221
1222      throw error("can't cope");
1223
1224    default:
1225      throw expect("string", tag);
1226    }
1227  }
1228
1229  /**
1230   * Reads a byte array
1231   *
1232   * <pre>
1233   * B b16 b8 data value
1234   * </pre>
1235   */

1236  public byte []readBytes()
1237    throws IOException JavaDoc
1238  {
1239    int tag = read();
1240
1241    switch (tag) {
1242    case 'N':
1243      return null;
1244
1245    case 'B':
1246    case 'b':
1247      _isLastChunk = tag == 'B';
1248      _chunkLength = (read() << 8) + read();
1249
1250      ByteArrayOutputStream JavaDoc bos = new ByteArrayOutputStream JavaDoc();
1251
1252      int data;
1253      while ((data = parseByte()) >= 0)
1254        bos.write(data);
1255
1256      return bos.toByteArray();
1257
1258    case 0x20: case 0x21: case 0x22: case 0x23:
1259    case 0x24: case 0x25: case 0x26: case 0x27:
1260    case 0x28: case 0x29: case 0x2a: case 0x2b:
1261    case 0x2c: case 0x2d: case 0x2e: case 0x2f:
1262      _isLastChunk = true;
1263      _chunkLength = tag - 0x20;
1264
1265      bos = new ByteArrayOutputStream JavaDoc();
1266
1267      while ((data = parseByte()) >= 0)
1268        bos.write(data);
1269
1270      return bos.toByteArray();
1271      
1272    default:
1273      throw expect("bytes", tag);
1274    }
1275  }
1276
1277  /**
1278   * Reads a byte from the stream.
1279   */

1280  public int readByte()
1281    throws IOException JavaDoc
1282  {
1283    if (_chunkLength > 0) {
1284      _chunkLength--;
1285      if (_chunkLength == 0 && _isLastChunk)
1286        _chunkLength = END_OF_DATA;
1287
1288      return read();
1289    }
1290    else if (_chunkLength == END_OF_DATA) {
1291      _chunkLength = 0;
1292      return -1;
1293    }
1294    
1295    int tag = read();
1296
1297    switch (tag) {
1298    case 'N':
1299      return -1;
1300
1301    case 'B':
1302    case 'b':
1303      _isLastChunk = tag == 'B';
1304      _chunkLength = (read() << 8) + read();
1305
1306      int value = parseByte();
1307
1308      // special code so successive read byte won't
1309
// be read as a single object.
1310
if (_chunkLength == 0 && _isLastChunk)
1311        _chunkLength = END_OF_DATA;
1312
1313      return value;
1314      
1315    default:
1316      throw new IOException JavaDoc("expected 'B' at " + (char) tag);
1317    }
1318  }
1319
1320  /**
1321   * Reads a byte array from the stream.
1322   */

1323  public int readBytes(byte []buffer, int offset, int length)
1324    throws IOException JavaDoc
1325  {
1326    int readLength = 0;
1327
1328    if (_chunkLength == END_OF_DATA) {
1329      _chunkLength = 0;
1330      return -1;
1331    }
1332    else if (_chunkLength == 0) {
1333      int tag = read();
1334
1335      switch (tag) {
1336      case 'N':
1337        return -1;
1338      
1339      case 'B':
1340      case 'b':
1341        _isLastChunk = tag == 'B';
1342        _chunkLength = (read() << 8) + read();
1343        break;
1344      
1345      default:
1346        throw new IOException JavaDoc("expected 'B' at " + (char) tag);
1347      }
1348    }
1349
1350    while (length > 0) {
1351      if (_chunkLength > 0) {
1352        buffer[offset++] = (byte) read();
1353        _chunkLength--;
1354        length--;
1355        readLength++;
1356      }
1357      else if (_isLastChunk) {
1358        if (readLength == 0)
1359          return -1;
1360        else {
1361          _chunkLength = END_OF_DATA;
1362          return readLength;
1363        }
1364      }
1365      else {
1366        int tag = read();
1367
1368        switch (tag) {
1369        case 'B':
1370        case 'b':
1371          _isLastChunk = tag == 'B';
1372          _chunkLength = (read() << 8) + read();
1373          break;
1374      
1375        default:
1376          throw new IOException JavaDoc("expected 'B' at " + (char) tag);
1377        }
1378      }
1379    }
1380    
1381    if (readLength == 0)
1382      return -1;
1383    else if (_chunkLength > 0 || ! _isLastChunk)
1384      return readLength;
1385    else {
1386      _chunkLength = END_OF_DATA;
1387      return readLength;
1388    }
1389  }
1390
1391  /**
1392   * Reads a fault.
1393   */

1394  private HashMap JavaDoc readFault()
1395    throws IOException JavaDoc
1396  {
1397    HashMap JavaDoc map = new HashMap JavaDoc();
1398
1399    int code = read();
1400    for (; code > 0 && code != 'z'; code = read()) {
1401      _offset--;
1402      
1403      Object JavaDoc key = readObject();
1404      Object JavaDoc value = readObject();
1405
1406      if (key != null && value != null)
1407        map.put(key, value);
1408    }
1409
1410    if (code != 'z')
1411      throw expect("fault", code);
1412
1413    return map;
1414  }
1415
1416  /**
1417   * Reads an object from the input stream with an expected type.
1418   */

1419  public Object JavaDoc readObject(Class JavaDoc cl)
1420    throws IOException JavaDoc
1421  {
1422    if (cl == null || cl == Object JavaDoc.class)
1423      return readObject();
1424    
1425    int tag = _offset < _length ? (_buffer[_offset++] & 0xff) : read();
1426
1427    switch (tag) {
1428    case 'N':
1429      return null;
1430
1431    case 'M':
1432    {
1433      String JavaDoc type = readType();
1434      Deserializer reader;
1435      reader = findSerializerFactory().getObjectDeserializer(type);
1436
1437      if (cl != reader.getType() && cl.isAssignableFrom(reader.getType()))
1438        return reader.readMap(this);
1439
1440      reader = findSerializerFactory().getDeserializer(cl);
1441
1442      return reader.readMap(this);
1443    }
1444
1445    case 'O':
1446    {
1447      return readObjectDefinition(cl);
1448    }
1449
1450    case 'o':
1451    {
1452      int ref = readInt();
1453
1454      ObjectDefinition def = (ObjectDefinition) _classDefs.get(ref - 1);
1455
1456      return readObjectInstance(cl, def);
1457    }
1458
1459    case 'V':
1460    {
1461      String JavaDoc type = readType();
1462      int length = readLength();
1463      
1464      Deserializer reader;
1465      reader = findSerializerFactory().getObjectDeserializer(type);
1466      
1467      if (cl != reader.getType() && cl.isAssignableFrom(reader.getType()))
1468        return reader.readList(this, length);
1469
1470      reader = findSerializerFactory().getDeserializer(cl);
1471
1472      Object JavaDoc v = reader.readList(this, length);
1473
1474      return v;
1475    }
1476
1477    case 'v':
1478    {
1479      int ref = readInt();
1480      String JavaDoc type = (String JavaDoc) _types.get(ref);
1481      int length = readInt();
1482      
1483      Deserializer reader;
1484      reader = findSerializerFactory().getObjectDeserializer(type);
1485      
1486      if (cl != reader.getType() && cl.isAssignableFrom(reader.getType()))
1487        return reader.readLengthList(this, length);
1488
1489      reader = findSerializerFactory().getDeserializer(cl);
1490
1491      Object JavaDoc v = reader.readLengthList(this, length);
1492
1493      return v;
1494    }
1495
1496    case 'R':
1497    {
1498      int ref = parseInt();
1499
1500      return _refs.get(ref);
1501    }
1502
1503    case 'r':
1504    {
1505      String JavaDoc type = readType();
1506      String JavaDoc url = readString();
1507
1508      return resolveRemote(type, url);
1509    }
1510    }
1511
1512    if (tag >= 0)
1513      _offset--;
1514
1515    Object JavaDoc value = findSerializerFactory().getDeserializer(cl).readObject(this);
1516
1517    return value;
1518  }
1519  
1520  /**
1521   * Reads an arbitrary object from the input stream when the type
1522   * is unknown.
1523   */

1524  public Object JavaDoc readObject()
1525    throws IOException JavaDoc
1526  {
1527    int tag = _offset < _length ? (_buffer[_offset++] & 0xff) : read();
1528
1529    switch (tag) {
1530    case 'N':
1531      return null;
1532      
1533    case 'T':
1534      return new Boolean JavaDoc(true);
1535      
1536    case 'F':
1537      return new Boolean JavaDoc(false);
1538
1539      // direct integer
1540
case 0x80: case 0x81: case 0x82: case 0x83:
1541    case 0x84: case 0x85: case 0x86: case 0x87:
1542    case 0x88: case 0x89: case 0x8a: case 0x8b:
1543    case 0x8c: case 0x8d: case 0x8e: case 0x8f:
1544      
1545    case 0x90: case 0x91: case 0x92: case 0x93:
1546    case 0x94: case 0x95: case 0x96: case 0x97:
1547    case 0x98: case 0x99: case 0x9a: case 0x9b:
1548    case 0x9c: case 0x9d: case 0x9e: case 0x9f:
1549      
1550    case 0xa0: case 0xa1: case 0xa2: case 0xa3:
1551    case 0xa4: case 0xa5: case 0xa6: case 0xa7:
1552    case 0xa8: case 0xa9: case 0xaa: case 0xab:
1553    case 0xac: case 0xad: case 0xae: case 0xaf:
1554      
1555    case 0xb0: case 0xb1: case 0xb2: case 0xb3:
1556    case 0xb4: case 0xb5: case 0xb6: case 0xb7:
1557    case 0xb8: case 0xb9: case 0xba: case 0xbb:
1558    case 0xbc: case 0xbd: case 0xbe: case 0xbf:
1559      return new Integer JavaDoc(tag - INT_ZERO);
1560
1561      /* byte int */
1562    case 0xc0: case 0xc1: case 0xc2: case 0xc3:
1563    case 0xc4: case 0xc5: case 0xc6: case 0xc7:
1564    case 0xc8: case 0xc9: case 0xca: case 0xcb:
1565    case 0xcc: case 0xcd: case 0xce: case 0xcf:
1566      return new Integer JavaDoc(((tag - INT_BYTE_ZERO) << 8) + read());
1567      
1568      /* short int */
1569    case 0xd0: case 0xd1: case 0xd2: case 0xd3:
1570    case 0xd4: case 0xd5: case 0xd6: case 0xd7:
1571      return new Integer JavaDoc(((tag - INT_SHORT_ZERO) << 16) + 256 * read() + read());
1572      
1573    case 'I':
1574      return new Integer JavaDoc(parseInt());
1575
1576      // direct long
1577
case 0xd8: case 0xd9: case 0xda: case 0xdb:
1578    case 0xdc: case 0xdd: case 0xde: case 0xdf:
1579      
1580    case 0xe0: case 0xe1: case 0xe2: case 0xe3:
1581    case 0xe4: case 0xe5: case 0xe6: case 0xe7:
1582    case 0xe8: case 0xe9: case 0xea: case 0xeb:
1583    case 0xec: case 0xed: case 0xee: case 0xef:
1584      return new Long JavaDoc(tag - LONG_ZERO);
1585
1586      /* byte long */
1587    case 0xf0: case 0xf1: case 0xf2: case 0xf3:
1588    case 0xf4: case 0xf5: case 0xf6: case 0xf7:
1589    case 0xf8: case 0xf9: case 0xfa: case 0xfb:
1590    case 0xfc: case 0xfd: case 0xfe: case 0xff:
1591      return new Long JavaDoc(((tag - LONG_BYTE_ZERO) << 8) + read());
1592      
1593      /* short long */
1594    case 0x38: case 0x39: case 0x3a: case 0x3b:
1595    case 0x3c: case 0x3d: case 0x3e: case 0x3f:
1596      return new Long JavaDoc(((tag - LONG_SHORT_ZERO) << 16) + 256 * read() + read());
1597      
1598    case LONG_INT:
1599      return new Long JavaDoc(parseInt());
1600    
1601    case 'L':
1602      return new Long JavaDoc(parseLong());
1603
1604    case DOUBLE_ZERO:
1605      return new Double JavaDoc(0);
1606
1607    case DOUBLE_ONE:
1608      return new Double JavaDoc(1);
1609
1610    case DOUBLE_BYTE:
1611      return new Double JavaDoc((byte) read());
1612
1613    case DOUBLE_SHORT:
1614      return new Double JavaDoc((short) (256 * read() + read()));
1615      
1616    case DOUBLE_INT:
1617      return new Double JavaDoc(parseInt());
1618
1619    case DOUBLE_256_SHORT:
1620      return new Double JavaDoc(D_256 * ((short) (256 * read() + read())));
1621    
1622    case 'D':
1623      return new Double JavaDoc(parseDouble());
1624    
1625    case 'd':
1626      return new Date JavaDoc(parseLong());
1627    
1628    case 'x':
1629    case 'X': {
1630      _isLastChunk = tag == 'X';
1631      _chunkLength = (read() << 8) + read();
1632
1633      return parseXML();
1634    }
1635
1636    case 's':
1637    case 'S': {
1638      _isLastChunk = tag == 'S';
1639      _chunkLength = (read() << 8) + read();
1640
1641      int data;
1642      _sbuf.setLength(0);
1643      
1644      while ((data = parseChar()) >= 0)
1645        _sbuf.append((char) data);
1646
1647      return _sbuf.toString();
1648    }
1649
1650    case 0x00: case 0x01: case 0x02: case 0x03:
1651    case 0x04: case 0x05: case 0x06: case 0x07:
1652    case 0x08: case 0x09: case 0x0a: case 0x0b:
1653    case 0x0c: case 0x0d: case 0x0e: case 0x0f:
1654
1655    case 0x10: case 0x11: case 0x12: case 0x13:
1656    case 0x14: case 0x15: case 0x16: case 0x17:
1657    case 0x18: case 0x19: case 0x1a: case 0x1b:
1658    case 0x1c: case 0x1d: case 0x1e: case 0x1f:
1659      {
1660    _isLastChunk = true;
1661    _chunkLength = tag - 0x00;
1662
1663    int data;
1664    _sbuf.setLength(0);
1665      
1666    while ((data = parseChar()) >= 0)
1667      _sbuf.append((char) data);
1668
1669    return _sbuf.toString();
1670      }
1671
1672    case 'b':
1673    case 'B': {
1674      _isLastChunk = tag == 'B';
1675      _chunkLength = (read() << 8) + read();
1676
1677      int data;
1678      ByteArrayOutputStream JavaDoc bos = new ByteArrayOutputStream JavaDoc();
1679      
1680      while ((data = parseByte()) >= 0)
1681        bos.write(data);
1682
1683      return bos.toByteArray();
1684    }
1685
1686    case 0x20: case 0x21: case 0x22: case 0x23:
1687    case 0x24: case 0x25: case 0x26: case 0x27:
1688    case 0x28: case 0x29: case 0x2a: case 0x2b:
1689    case 0x2c: case 0x2d: case 0x2e: case 0x2f:
1690      {
1691    _isLastChunk = true;
1692    int len = tag - 0x20;
1693    _chunkLength = 0;
1694
1695    byte []data = new byte[len];
1696
1697    for (int i = 0; i < len; i++)
1698      data[i] = (byte) read();
1699
1700    return data;
1701      }
1702
1703    case 'V': {
1704      String JavaDoc type = readType();
1705      int length = readLength();
1706
1707      return findSerializerFactory().readList(this, length, type);
1708    }
1709
1710      // direct lists
1711
case 'v': {
1712      int ref = readInt();
1713      String JavaDoc type = (String JavaDoc) _types.get(ref);
1714      int length = readInt();
1715      
1716      Deserializer reader;
1717      reader = findSerializerFactory().getObjectDeserializer(type);
1718      
1719      return reader.readLengthList(this, length);
1720    }
1721
1722    case 'M': {
1723      String JavaDoc type = readType();
1724
1725      return findSerializerFactory().readMap(this, type);
1726    }
1727
1728    case 'O': {
1729      return readObjectDefinition(null);
1730    }
1731
1732    case 'o': {
1733      int ref = readInt();
1734
1735      ObjectDefinition def = (ObjectDefinition) _classDefs.get(ref - 1);
1736
1737      return readObjectInstance(null, def);
1738    }
1739
1740    case 'R': {
1741      int ref = parseInt();
1742
1743      return _refs.get(ref);
1744    }
1745
1746    case REF_BYTE: {
1747      int ref = read();
1748
1749      return _refs.get(ref);
1750    }
1751
1752    case REF_SHORT: {
1753      int ref = 256 * read() + read();
1754
1755      return _refs.get(ref);
1756    }
1757      
1758    case 'r': {
1759      String JavaDoc type = readType();
1760      String JavaDoc url = readString();
1761
1762      return resolveRemote(type, url);
1763    }
1764
1765    default:
1766      throw error("unknown code:" + tag + " " + (char) tag);
1767    }
1768  }
1769
1770  /**
1771   * Reads an object definition:
1772   *
1773   * <pre>
1774   * O type <int> (string)* <value>*
1775   * </pre>
1776   */

1777  private Object JavaDoc readObjectDefinition(Class JavaDoc cl)
1778    throws IOException JavaDoc
1779  {
1780    String JavaDoc type = readLenString();
1781    int len = readInt();
1782
1783    String JavaDoc []fieldNames = new String JavaDoc[len];
1784    for (int i = 0; i < len; i++)
1785      fieldNames[i] = readString();
1786
1787    ObjectDefinition def = new ObjectDefinition(type, fieldNames);
1788
1789    if (_classDefs == null)
1790      _classDefs = new ArrayList JavaDoc();
1791
1792    _classDefs.add(def);
1793
1794    return readObjectInstance(cl, def);
1795  }
1796
1797  private Object JavaDoc readObjectInstance(Class JavaDoc cl, ObjectDefinition def)
1798    throws IOException JavaDoc
1799  {
1800    String JavaDoc type = def.getType();
1801    String JavaDoc []fieldNames = def.getFieldNames();
1802    
1803    if (cl != null) {
1804      Deserializer reader;
1805      reader = findSerializerFactory().getObjectDeserializer(type);
1806
1807      if (cl != reader.getType() && cl.isAssignableFrom(reader.getType()))
1808    return reader.readObject(this, fieldNames);
1809
1810      reader = findSerializerFactory().getDeserializer(cl);
1811
1812      return reader.readObject(this, fieldNames);
1813    }
1814    else {
1815      return findSerializerFactory().readObject(this, type, fieldNames);
1816    }
1817  }
1818
1819  private String JavaDoc readLenString()
1820    throws IOException JavaDoc
1821  {
1822    int len = readInt();
1823    
1824    _isLastChunk = true;
1825    _chunkLength = len;
1826
1827    _sbuf.setLength(0);
1828    int ch;
1829    while ((ch = parseChar()) >= 0)
1830      _sbuf.append((char) ch);
1831
1832    return _sbuf.toString();
1833  }
1834
1835  private String JavaDoc readLenString(int len)
1836    throws IOException JavaDoc
1837  {
1838    _isLastChunk = true;
1839    _chunkLength = len;
1840
1841    _sbuf.setLength(0);
1842    int ch;
1843    while ((ch = parseChar()) >= 0)
1844      _sbuf.append((char) ch);
1845
1846    return _sbuf.toString();
1847  }
1848  
1849  /**
1850   * Reads a remote object.
1851   */

1852  public Object JavaDoc readRemote()
1853    throws IOException JavaDoc
1854  {
1855    String JavaDoc type = readType();
1856    String JavaDoc url = readString();
1857
1858    return resolveRemote(type, url);
1859  }
1860
1861  /**
1862   * Reads a reference.
1863   */

1864  public Object JavaDoc readRef()
1865    throws IOException JavaDoc
1866  {
1867    return _refs.get(parseInt());
1868  }
1869
1870  /**
1871   * Reads the start of a list.
1872   */

1873  public int readListStart()
1874    throws IOException JavaDoc
1875  {
1876    return read();
1877  }
1878
1879  /**
1880   * Reads the start of a list.
1881   */

1882  public int readMapStart()
1883    throws IOException JavaDoc
1884  {
1885    return read();
1886  }
1887
1888  /**
1889   * Returns true if this is the end of a list or a map.
1890   */

1891  public boolean isEnd()
1892    throws IOException JavaDoc
1893  {
1894    int code;
1895
1896    if (_offset < _length)
1897      code = (_buffer[_offset] & 0xff);
1898    else {
1899      code = read();
1900
1901      if (code >= 0)
1902    _offset--;
1903    }
1904
1905    return (code < 0 || code == 'z');
1906  }
1907
1908  /**
1909   * Reads the end byte.
1910   */

1911  public void readEnd()
1912    throws IOException JavaDoc
1913  {
1914    int code = _offset < _length ? (_buffer[_offset++] & 0xff) : read();
1915
1916    if (code != 'z')
1917      throw error("unknown code:" + (char) code);
1918  }
1919
1920  /**
1921   * Reads the end byte.
1922   */

1923  public void readMapEnd()
1924    throws IOException JavaDoc
1925  {
1926    int code = _offset < _length ? (_buffer[_offset++] & 0xff) : read();
1927
1928    if (code != 'z')
1929      throw error("expected end of map ('z') at '" + (char) code + "'");
1930  }
1931
1932  /**
1933   * Reads the end byte.
1934   */

1935  public void readListEnd()
1936    throws IOException JavaDoc
1937  {
1938    int code = _offset < _length ? (_buffer[_offset++] & 0xff) : read();
1939
1940    if (code != 'z')
1941      throw error("expected end of list ('z') at '" + (char) code + "'");
1942  }
1943
1944  /**
1945   * Adds a list/map reference.
1946   */

1947  public int addRef(Object JavaDoc ref)
1948  {
1949    if (_refs == null)
1950      _refs = new ArrayList JavaDoc();
1951    
1952    _refs.add(ref);
1953
1954    return _refs.size() - 1;
1955  }
1956
1957  /**
1958   * Adds a list/map reference.
1959   */

1960  public void setRef(int i, Object JavaDoc ref)
1961  {
1962    _refs.set(i, ref);
1963  }
1964
1965  /**
1966   * Resolves a remote object.
1967   */

1968  public Object JavaDoc resolveRemote(String JavaDoc type, String JavaDoc url)
1969    throws IOException JavaDoc
1970  {
1971    HessianRemoteResolver resolver = getRemoteResolver();
1972
1973    if (resolver != null)
1974      return resolver.lookup(type, url);
1975    else
1976      return new HessianRemote(type, url);
1977  }
1978
1979  /**
1980   * Parses a type from the stream.
1981   *
1982   * <pre>
1983   * t b16 b8
1984   * </pre>
1985   */

1986  public String JavaDoc readType()
1987    throws IOException JavaDoc
1988  {
1989    int code = _offset < _length ? (_buffer[_offset++] & 0xff) : read();
1990
1991    if (code == 't') {
1992      int len = 256 * read() + read();
1993      String JavaDoc type = readLenString(len);
1994
1995      if (_types == null)
1996    _types = new ArrayList JavaDoc();
1997
1998      _types.add(type);
1999
2000      return type;
2001    }
2002    else if (code == 'T') {
2003      int ref = readInt();
2004
2005      return (String JavaDoc) _types.get(ref);
2006    }
2007    else {
2008      if (code >= 0)
2009    _offset--;
2010      
2011      return "";
2012    }
2013  }
2014
2015  /**
2016   * Parses the length for an array
2017   *
2018   * <pre>
2019   * l b32 b24 b16 b8
2020   * </pre>
2021   */

2022  public int readLength()
2023    throws IOException JavaDoc
2024  {
2025    int code = read();
2026
2027    if (code == LENGTH_BYTE)
2028      return read();
2029    
2030    else if (code == 'l')
2031      return parseInt();
2032
2033    else {
2034      if (code >= 0)
2035    _offset--;
2036      
2037      return -1;
2038    }
2039  }
2040
2041  /**
2042   * Parses a 32-bit integer value from the stream.
2043   *
2044   * <pre>
2045   * b32 b24 b16 b8
2046   * </pre>
2047   */

2048  private int parseInt()
2049    throws IOException JavaDoc
2050  {
2051    int offset = _offset;
2052    
2053    if (offset + 3 < _length) {
2054      byte []buffer = _buffer;
2055      
2056      int b32 = buffer[offset + 0] & 0xff;
2057      int b24 = buffer[offset + 1] & 0xff;
2058      int b16 = buffer[offset + 2] & 0xff;
2059      int b8 = buffer[offset + 3] & 0xff;
2060
2061      _offset = offset + 4;
2062
2063      return (b32 << 24) + (b24 << 16) + (b16 << 8) + b8;
2064    }
2065    else {
2066      int b32 = read();
2067      int b24 = read();
2068      int b16 = read();
2069      int b8 = read();
2070
2071      return (b32 << 24) + (b24 << 16) + (b16 << 8) + b8;
2072    }
2073  }
2074
2075  /**
2076   * Parses a 64-bit long value from the stream.
2077   *
2078   * <pre>
2079   * b64 b56 b48 b40 b32 b24 b16 b8
2080   * </pre>
2081   */

2082  private long parseLong()
2083    throws IOException JavaDoc
2084  {
2085    long b64 = read();
2086    long b56 = read();
2087    long b48 = read();
2088    long b40 = read();
2089    long b32 = read();
2090    long b24 = read();
2091    long b16 = read();
2092    long b8 = read();
2093
2094    return ((b64 << 56) +
2095            (b56 << 48) +
2096            (b48 << 40) +
2097            (b40 << 32) +
2098            (b32 << 24) +
2099            (b24 << 16) +
2100            (b16 << 8) +
2101            b8);
2102  }
2103  
2104  /**
2105   * Parses a 64-bit double value from the stream.
2106   *
2107   * <pre>
2108   * b64 b56 b48 b40 b32 b24 b16 b8
2109   * </pre>
2110   */

2111  private double parseDouble()
2112    throws IOException JavaDoc
2113  {
2114    long bits = parseLong();
2115  
2116    return Double.longBitsToDouble(bits);
2117  }
2118
2119  org.w3c.dom.Node JavaDoc parseXML()
2120    throws IOException JavaDoc
2121  {
2122    throw new UnsupportedOperationException JavaDoc();
2123  }
2124  
2125  /**
2126   * Reads a character from the underlying stream.
2127   */

2128  private int parseChar()
2129    throws IOException JavaDoc
2130  {
2131    while (_chunkLength <= 0) {
2132      if (_isLastChunk)
2133        return -1;
2134
2135      int code = _offset < _length ? (_buffer[_offset++] & 0xff) : read();
2136
2137      switch (code) {
2138      case 's':
2139      case 'x':
2140        _isLastChunk = false;
2141
2142        _chunkLength = (read() << 8) + read();
2143        break;
2144        
2145      case 'S':
2146      case 'X':
2147        _isLastChunk = true;
2148
2149        _chunkLength = (read() << 8) + read();
2150        break;
2151    
2152      case 0x00: case 0x01: case 0x02: case 0x03:
2153      case 0x04: case 0x05: case 0x06: case 0x07:
2154      case 0x08: case 0x09: case 0x0a: case 0x0b:
2155      case 0x0c: case 0x0d: case 0x0e: case 0x0f:
2156
2157      case 0x10: case 0x11: case 0x12: case 0x13:
2158      case 0x14: case 0x15: case 0x16: case 0x17:
2159      case 0x18: case 0x19: case 0x1a: case 0x1b:
2160      case 0x1c: case 0x1d: case 0x1e: case 0x1f:
2161    _isLastChunk = true;
2162    _chunkLength = code - 0x00;
2163    break;
2164
2165      default:
2166        throw expect("string", code);
2167      }
2168
2169    }
2170
2171    _chunkLength--;
2172
2173    return parseUTF8Char();
2174  }
2175
2176  /**
2177   * Parses a single UTF8 character.
2178   */

2179  private int parseUTF8Char()
2180    throws IOException JavaDoc
2181  {
2182    int ch = _offset < _length ? (_buffer[_offset++] & 0xff) : read();
2183
2184    if (ch < 0x80)
2185      return ch;
2186    else if ((ch & 0xe0) == 0xc0) {
2187      int ch1 = read();
2188      int v = ((ch & 0x1f) << 6) + (ch1 & 0x3f);
2189
2190      return v;
2191    }
2192    else if ((ch & 0xf0) == 0xe0) {
2193      int ch1 = read();
2194      int ch2 = read();
2195      int v = ((ch & 0x0f) << 12) + ((ch1 & 0x3f) << 6) + (ch2 & 0x3f);
2196
2197      return v;
2198    }
2199    else
2200      throw error("bad utf-8 encoding");
2201  }
2202  
2203  /**
2204   * Reads a byte from the underlying stream.
2205   */

2206  private int parseByte()
2207    throws IOException JavaDoc
2208  {
2209    while (_chunkLength <= 0) {
2210      if (_isLastChunk) {
2211        return -1;
2212      }
2213
2214      int code = read();
2215
2216      switch (code) {
2217      case 'b':
2218        _isLastChunk = false;
2219
2220        _chunkLength = (read() << 8) + read();
2221        break;
2222        
2223      case 'B':
2224        _isLastChunk = true;
2225
2226        _chunkLength = (read() << 8) + read();
2227        break;
2228
2229      case 0x20: case 0x21: case 0x22: case 0x23:
2230      case 0x24: case 0x25: case 0x26: case 0x27:
2231      case 0x28: case 0x29: case 0x2a: case 0x2b:
2232      case 0x2c: case 0x2d: case 0x2e: case 0x2f:
2233        _isLastChunk = true;
2234
2235        _chunkLength = code - 0x20;
2236        break;
2237
2238      default:
2239        throw expect("byte[]", code);
2240      }
2241    }
2242
2243    _chunkLength--;
2244
2245    return read();
2246  }
2247
2248  /**
2249   * Reads bytes based on an input stream.
2250   */

2251  public InputStream JavaDoc readInputStream()
2252    throws IOException JavaDoc
2253  {
2254    int tag = read();
2255
2256    switch (tag) {
2257    case 'N':
2258      return null;
2259
2260    case 'B':
2261    case 'b':
2262      _isLastChunk = tag == 'B';
2263      _chunkLength = (read() << 8) + read();
2264      break;
2265      
2266    default:
2267      throw expect("inputStream", tag);
2268    }
2269    
2270    return new InputStream JavaDoc() {
2271    boolean _isClosed = false;
2272    
2273    public int read()
2274      throws IOException JavaDoc
2275    {
2276      if (_isClosed)
2277        return -1;
2278
2279      int ch = parseByte();
2280      if (ch < 0)
2281        _isClosed = true;
2282
2283      return ch;
2284    }
2285    
2286    public int read(byte []buffer, int offset, int length)
2287      throws IOException JavaDoc
2288    {
2289      if (_isClosed)
2290        return -1;
2291
2292      int len = Hessian2Input.this.read(buffer, offset, length);
2293      if (len < 0)
2294        _isClosed = true;
2295
2296      return len;
2297    }
2298
2299    public void close()
2300      throws IOException JavaDoc
2301    {
2302      while (read() >= 0) {
2303      }
2304    }
2305      };
2306  }
2307  
2308  /**
2309   * Reads bytes from the underlying stream.
2310   */

2311  int read(byte []buffer, int offset, int length)
2312    throws IOException JavaDoc
2313  {
2314    int readLength = 0;
2315    
2316    while (length > 0) {
2317      while (_chunkLength <= 0) {
2318        if (_isLastChunk)
2319          return readLength == 0 ? -1 : readLength;
2320
2321        int code = read();
2322
2323        switch (code) {
2324        case 'b':
2325          _isLastChunk = false;
2326
2327          _chunkLength = (read() << 8) + read();
2328          break;
2329        
2330        case 'B':
2331          _isLastChunk = true;
2332
2333          _chunkLength = (read() << 8) + read();
2334          break;
2335
2336        default:
2337          throw expect("byte[]", code);
2338        }
2339      }
2340
2341      int sublen = _chunkLength;
2342      if (length < sublen)
2343        sublen = length;
2344
2345      sublen = _is.read(buffer, offset, sublen);
2346      offset += sublen;
2347      readLength += sublen;
2348      length -= sublen;
2349      _chunkLength -= sublen;
2350    }
2351
2352    return readLength;
2353  }
2354
2355  /**
2356   * Normally, shouldn't be called externally, but needed for QA, e.g.
2357   * ejb/3b01.
2358   */

2359  public final int read()
2360    throws IOException JavaDoc
2361  {
2362    if (_length <= _offset && ! readBuffer())
2363      return -1;
2364
2365    return _buffer[_offset++] & 0xff;
2366  }
2367
2368  private final boolean readBuffer()
2369    throws IOException JavaDoc
2370  {
2371    byte []buffer = _buffer;
2372    int offset = _offset;
2373    int length = _length;
2374    
2375    if (offset < length) {
2376      System.arraycopy(buffer, offset, buffer, 0, length - offset);
2377      offset = length - offset;
2378    }
2379    else
2380      offset = 0;
2381    
2382    int len = _is.read(buffer, offset, SIZE - offset);
2383
2384    if (len <= 0) {
2385      _length = offset;
2386      _offset = 0;
2387      
2388      return offset > 0;
2389    }
2390
2391    _length = offset + len;
2392    _offset = 0;
2393
2394    return true;
2395  }
2396
2397  public Reader JavaDoc getReader()
2398  {
2399    return null;
2400  }
2401
2402  protected IOException JavaDoc expect(String JavaDoc expect, int ch)
2403  {
2404    if (ch < 0)
2405      return error("expected " + expect + " at end of file");
2406    else
2407      return error("expected " + expect + " at " + ch);
2408  }
2409  
2410  protected IOException JavaDoc error(String JavaDoc message)
2411  {
2412    if (_method != null)
2413      return new HessianProtocolException(_method + ": " + message);
2414    else
2415      return new HessianProtocolException(message);
2416  }
2417
2418  public void close()
2419  {
2420  }
2421
2422  final static class ObjectDefinition {
2423    private final String JavaDoc _type;
2424    private final String JavaDoc []_fields;
2425
2426    ObjectDefinition(String JavaDoc type, String JavaDoc []fields)
2427    {
2428      _type = type;
2429      _fields = fields;
2430    }
2431
2432    String JavaDoc getType()
2433    {
2434      return _type;
2435    }
2436
2437    String JavaDoc []getFieldNames()
2438    {
2439      return _fields;
2440    }
2441  }
2442
2443  static {
2444    try {
2445      _detailMessageField = Throwable JavaDoc.class.getDeclaredField("detailMessage");
2446      _detailMessageField.setAccessible(true);
2447    } catch (Throwable JavaDoc e) {
2448    }
2449  }
2450}
2451
Popular Tags