KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2  * Copyright (c) 2001-2004 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.IOException JavaDoc;
52 import java.io.InputStream JavaDoc;
53 import java.io.PrintWriter JavaDoc;
54 import java.util.ArrayList JavaDoc;
55
56 /**
57  * Debugging input stream for Hessian requests.
58  */

59 public class HessianDebugInputStream extends InputStream JavaDoc {
60   private InputStream JavaDoc _is;
61   private PrintWriter JavaDoc _dbg;
62
63   private State _state;
64   private ArrayList JavaDoc<State> _stateStack = new ArrayList JavaDoc<State>();
65
66   private int _refId;
67   
68   /**
69    * Creates an uninitialized Hessian input stream.
70    */

71   public HessianDebugInputStream(InputStream JavaDoc is, PrintWriter JavaDoc dbg)
72   {
73     _is = is;
74     _dbg = dbg;
75
76     _state = new InitialState();
77   }
78
79   /**
80    * Reads a character.
81    */

82   public int read()
83     throws IOException JavaDoc
84   {
85     int ch;
86
87     InputStream JavaDoc is = _is;
88
89     if (is == null)
90       return -1;
91     else
92       ch = is.read();
93
94     _state = _state.next(ch);
95
96     return ch;
97   }
98
99   /**
100    * closes the stream.
101    */

102   public void close()
103     throws IOException JavaDoc
104   {
105     InputStream JavaDoc is = _is;
106     _is = null;
107     _dbg = null;
108
109     if (is != null)
110       is.close();
111   }
112
113   void println(String JavaDoc string)
114   {
115     println(0, string);
116   }
117
118   void println(int depth, String JavaDoc string)
119   {
120     for (int i = 0; i < _stateStack.size() + depth - 1; i++)
121       _dbg.print(" ");
122
123     _dbg.println(string);
124     _dbg.flush();
125   }
126
127   void pushStack(State state)
128   {
129     _stateStack.add(state);
130   }
131
132   State popStack()
133   {
134     return _stateStack.remove(_stateStack.size() - 1);
135   }
136
137   abstract class State {
138     abstract State next(int ch);
139     
140     protected State nextObject(int ch)
141     {
142       switch (ch) {
143       case -1:
144     return this;
145     
146       case 'N':
147     println(1, "N: null");
148     return this;
149     
150       case 'T':
151     println(1, "T: true");
152     return this;
153     
154       case 'F':
155     println(1, "F: false");
156     return this;
157
158       case 'I':
159     pushStack(this);
160     return new IntegerState("I");
161
162       case 'R':
163     pushStack(this);
164     return new IntegerState("Ref");
165
166       case 'r':
167     pushStack(this);
168     return new RemoteState();
169
170       case 'L':
171     pushStack(this);
172     return new LongState();
173
174       case 'd':
175     pushStack(this);
176     return new DateState();
177
178       case 'D':
179     pushStack(this);
180     return new DoubleState();
181
182       case 'S': case 'X':
183     pushStack(this);
184     return new StringState('S', true);
185
186       case 's': case 'x':
187     pushStack(this);
188     return new StringState('S', false);
189
190       case 'B':
191     pushStack(this);
192     return new ByteState(true);
193
194       case 'b':
195     pushStack(this);
196     return new ByteState(false);
197
198       case 'M':
199     println(1, "M: map/object #" + _refId++);
200     pushStack(this);
201     return new MapState();
202
203       case 'V':
204     println(1, "V: list #" + _refId++);
205     pushStack(this);
206     return new ListState();
207
208       case ' ': case '\n': case '\r': case '\t':
209     return this;
210     
211       default:
212     println(String.valueOf((char) ch) + ": unexpected character");
213     return this;
214       }
215     }
216   }
217   
218   class InitialState extends State {
219     State next(int ch)
220     {
221       if (ch == 'r') {
222     pushStack(this);
223     return new ReplyState();
224       }
225       else if (ch == 'c') {
226     pushStack(this);
227     return new CallState();
228       }
229       else
230     return nextObject(ch);
231     }
232   }
233   
234   class ObjectState extends State {
235     State next(int ch)
236     {
237       return nextObject(ch);
238     }
239   }
240   
241   class IntegerState extends State {
242     String JavaDoc _typeCode;
243     
244     int _length;
245     int _value;
246
247     IntegerState(String JavaDoc typeCode)
248     {
249       _typeCode = typeCode;
250     }
251     
252     State next(int ch)
253     {
254       _value = 256 * _value + (ch & 0xff);
255
256       if (++_length == 4) {
257     println(_typeCode + ": " + _value);
258     return popStack();
259       }
260       else
261     return this;
262     }
263   }
264   
265   class LongState extends State {
266     int _length;
267     long _value;
268     
269     State next(int ch)
270     {
271       _value = 256 * _value + (ch & 0xff);
272
273       if (++_length == 8) {
274     println("L: " + _value);
275     return popStack();
276       }
277       else
278     return this;
279     }
280   }
281   
282   class DateState extends State {
283     int _length;
284     long _value;
285     
286     State next(int ch)
287     {
288       _value = 256 * _value + (ch & 0xff);
289
290       if (++_length == 8) {
291     println("d: " + new java.util.Date JavaDoc(_value));
292     return popStack();
293       }
294       else
295     return this;
296     }
297   }
298   
299   class DoubleState extends State {
300     int _length;
301     long _value;
302     
303     State next(int ch)
304     {
305       _value = 256 * _value + (ch & 0xff);
306
307       if (++_length == 8) {
308     println("D: " + Double.longBitsToDouble(_value));
309     return popStack();
310       }
311       else
312     return this;
313     }
314   }
315   
316   class StringState extends State {
317     private static final int TOP = 0;
318     private static final int UTF_2_1 = 1;
319     private static final int UTF_3_1 = 2;
320     private static final int UTF_3_2 = 3;
321
322     char _typeCode;
323     
324     StringBuilder JavaDoc _value = new StringBuilder JavaDoc();
325     int _lengthIndex;
326     int _length;
327     boolean _isLastChunk;
328     
329     int _utfState;
330     char _ch;
331
332     StringState(char typeCode, boolean isLastChunk)
333     {
334       _typeCode = typeCode;
335       _isLastChunk = isLastChunk;
336     }
337     
338     State next(int ch)
339     {
340       if (_lengthIndex < 2) {
341     _length = 256 * _length + (ch & 0xff);
342     
343     if (++_lengthIndex == 2 && _length == 0 && _isLastChunk) {
344       println(_typeCode + ": " + _value);
345       return popStack();
346     }
347     else
348       return this;
349       }
350       else if (_length == 0) {
351     if (ch == 's' || ch == 'x') {
352       _isLastChunk = false;
353       _lengthIndex = 0;
354       return this;
355     }
356     else if (ch == 'S' || ch == 'X') {
357       _isLastChunk = true;
358       _lengthIndex = 0;
359       return this;
360     }
361     else {
362       println(String.valueOf((char) ch) + ": unexpected character");
363       return popStack();
364     }
365       }
366
367       switch (_utfState) {
368       case TOP:
369     if (ch < 0x80) {
370       _length--;
371
372       _value.append((char) ch);
373     }
374     else if (ch < 0xe0) {
375       _ch = (char) ((ch & 0x1f) << 6);
376       _utfState = UTF_2_1;
377     }
378     else {
379       _ch = (char) ((ch & 0xf) << 12);
380       _utfState = UTF_3_1;
381     }
382     break;
383
384       case UTF_2_1:
385       case UTF_3_2:
386     _ch += ch & 0x3f;
387     _value.append(_ch);
388     _length--;
389     _utfState = TOP;
390     break;
391
392       case UTF_3_1:
393     _ch += (char) ((ch & 0x3f) << 6);
394     _utfState = UTF_3_2;
395     break;
396       }
397
398       if (_length == 0) {
399     println(_typeCode + ": " + _value);
400     return popStack();
401       }
402       else
403     return this;
404     }
405   }
406   
407   class ByteState extends State {
408     int _lengthIndex;
409     int _length;
410     boolean _isLastChunk;
411
412     ByteState(boolean isLastChunk)
413     {
414       _isLastChunk = isLastChunk;
415     }
416     
417     State next(int ch)
418     {
419       if (_lengthIndex < 2) {
420     _length = 256 * _length + (ch & 0xff);
421     
422     if (++_lengthIndex == 2) {
423       if (_isLastChunk)
424         println("B: " + _length);
425       else
426         println("b: " + _length);
427     }
428
429     if (_lengthIndex == 2 && _length == 0 && _isLastChunk) {
430       return popStack();
431     }
432     else
433       return this;
434       }
435       else if (_length == 0) {
436     if (ch == 'b') {
437       _isLastChunk = false;
438       _lengthIndex = 0;
439       return this;
440     }
441     else if (ch == 'B') {
442       _isLastChunk = true;
443       _lengthIndex = 0;
444       return this;
445     }
446     else {
447       println(String.valueOf((char) ch) + ": unexpected character");
448       return popStack();
449     }
450       }
451
452       _length--;
453
454       if (_length == 0) {
455     return popStack();
456       }
457       else
458     return this;
459     }
460   }
461   
462   class MapState extends State {
463     private static final int TYPE = 0;
464     private static final int KEY = 1;
465     private static final int VALUE = 2;
466
467     private int _state;
468     
469     State next(int ch)
470     {
471       switch (_state) {
472       case TYPE:
473     if (ch == 't') {
474       _state = KEY;
475       pushStack(this);
476       return new StringState('t', true);
477     }
478     else if (ch == 'z') {
479       return popStack();
480     }
481     else {
482       _state = VALUE;
483       return nextObject(ch);
484     }
485     
486       case KEY:
487     if (ch == 'z') {
488       return popStack();
489     }
490     else {
491       _state = VALUE;
492       return nextObject(ch);
493     }
494     
495       case VALUE:
496     _state = KEY;
497     return nextObject(ch);
498
499       default:
500     throw new IllegalStateException JavaDoc();
501       }
502     }
503   }
504   
505   class ListState extends State {
506     private static final int TYPE = 0;
507     private static final int LENGTH = 1;
508     private static final int VALUE = 2;
509
510     private int _state;
511     
512     State next(int ch)
513     {
514       switch (_state) {
515       case TYPE:
516     if (ch == 'z') {
517       return popStack();
518     }
519     else if (ch == 't') {
520       _state = LENGTH;
521       pushStack(this);
522       return new StringState('t', true);
523     }
524     else if (ch == 'l') {
525       _state = VALUE;
526       pushStack(this);
527       return new IntegerState("l");
528     }
529     else {
530       _state = VALUE;
531       return nextObject(ch);
532     }
533     
534       case LENGTH:
535     if (ch == 'z') {
536       return popStack();
537     }
538     else if (ch == 'l') {
539       _state = VALUE;
540       pushStack(this);
541       return new IntegerState("len");
542     }
543     else {
544       _state = VALUE;
545       return nextObject(ch);
546     }
547     
548       case VALUE:
549     if (ch == 'z') {
550       return popStack();
551     }
552     else {
553       return nextObject(ch);
554     }
555
556       default:
557     throw new IllegalStateException JavaDoc();
558       }
559     }
560   }
561   
562   class CallState extends State {
563     private static final int MAJOR = 0;
564     private static final int MINOR = 1;
565     private static final int HEADER = 2;
566     private static final int VALUE = 3;
567     private static final int ARG = 4;
568
569     private int _state;
570     private int _major;
571     private int _minor;
572     
573     State next(int ch)
574     {
575       switch (_state) {
576       case MAJOR:
577     _major = ch;
578     _state = MINOR;
579     return this;
580     
581       case MINOR:
582     _minor = ch;
583     _state = HEADER;
584     println(-1, "call " + _major + "." + _minor);
585     return this;
586     
587       case HEADER:
588     if (ch == 'H') {
589       _state = VALUE;
590       pushStack(this);
591       return new StringState('H', true);
592     }
593     else if (ch == 'm') {
594       _state = ARG;
595       pushStack(this);
596       return new StringState('m', true);
597     }
598     else {
599       println((char) ch + ": unexpected char");
600       return popStack();
601     }
602     
603       case VALUE:
604     _state = HEADER;
605     return nextObject(ch);
606     
607       case ARG:
608     if (ch == 'z')
609       return popStack();
610     else
611       return nextObject(ch);
612
613       default:
614     throw new IllegalStateException JavaDoc();
615       }
616     }
617   }
618   
619   class ReplyState extends State {
620     private static final int MAJOR = 0;
621     private static final int MINOR = 1;
622     private static final int HEADER = 2;
623     private static final int VALUE = 3;
624     private static final int END = 4;
625
626     private int _state;
627     private int _major;
628     private int _minor;
629     
630     State next(int ch)
631     {
632       switch (_state) {
633       case MAJOR:
634     if (ch == 't' || ch == 'S')
635       return new RemoteState().next(ch);
636     
637     _major = ch;
638     _state = MINOR;
639     return this;
640     
641       case MINOR:
642     _minor = ch;
643     _state = HEADER;
644     println(-1, "reply " + _major + "." + _minor);
645     return this;
646     
647       case HEADER:
648     if (ch == 'H') {
649       _state = VALUE;
650       pushStack(this);
651       return new StringState('H', true);
652     }
653     else if (ch == 'f') {
654       println("f: fault");
655       _state = END;
656       return new MapState();
657     }
658     else {
659       _state = END;
660       return nextObject(ch);
661     }
662     
663       case VALUE:
664     _state = HEADER;
665     return nextObject(ch);
666     
667       case END:
668     return popStack().next(ch);
669
670       default:
671     throw new IllegalStateException JavaDoc();
672       }
673     }
674   }
675   
676   class RemoteState extends State {
677     private static final int TYPE = 0;
678     private static final int VALUE = 1;
679     private static final int END = 2;
680
681     private int _state;
682     private int _major;
683     private int _minor;
684     
685     State next(int ch)
686     {
687       switch (_state) {
688       case TYPE:
689     println(-1, "remote");
690     if (ch == 't') {
691       _state = VALUE;
692       pushStack(this);
693       return new StringState('t', false);
694     }
695     else {
696       _state = END;
697       return nextObject(ch);
698     }
699
700       case VALUE:
701     _state = END;
702     return nextObject(ch);
703
704       case END:
705     return popStack().next(ch);
706
707       default:
708     throw new IllegalStateException JavaDoc();
709       }
710     }
711   }
712 }
713
Popular Tags