Source Code Cross Referenced for Hessian2Input.java in  » EJB-Server-resin-3.1.5 » hessian » com » caucho » hessian » io » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » EJB Server resin 3.1.5 » hessian » com.caucho.hessian.io 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright (c) 2001-2008 Caucho Technology, Inc.  All rights reserved.
0003:         *
0004:         * The Apache Software License, Version 1.1
0005:         *
0006:         * Redistribution and use in source and binary forms, with or without
0007:         * modification, are permitted provided that the following conditions
0008:         * are met:
0009:         *
0010:         * 1. Redistributions of source code must retain the above copyright
0011:         *    notice, this list of conditions and the following disclaimer.
0012:         *
0013:         * 2. Redistributions in binary form must reproduce the above copyright
0014:         *    notice, this list of conditions and the following disclaimer in
0015:         *    the documentation and/or other materials provided with the
0016:         *    distribution.
0017:         *
0018:         * 3. The end-user documentation included with the redistribution, if
0019:         *    any, must include the following acknowlegement:
0020:         *       "This product includes software developed by the
0021:         *        Caucho Technology (http://www.caucho.com/)."
0022:         *    Alternately, this acknowlegement may appear in the software itself,
0023:         *    if and wherever such third-party acknowlegements normally appear.
0024:         *
0025:         * 4. The names "Hessian", "Resin", and "Caucho" must not be used to
0026:         *    endorse or promote products derived from this software without prior
0027:         *    written permission. For written permission, please contact
0028:         *    info@caucho.com.
0029:         *
0030:         * 5. Products derived from this software may not be called "Resin"
0031:         *    nor may "Resin" appear in their names without prior written
0032:         *    permission of Caucho Technology.
0033:         *
0034:         * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
0035:         * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0036:         * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0037:         * DISCLAIMED.  IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS
0038:         * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
0039:         * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
0040:         * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
0041:         * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
0042:         * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
0043:         * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
0044:         * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0045:         *
0046:         * @author Scott Ferguson
0047:         */
0048:
0049:        package com.caucho.hessian.io;
0050:
0051:        import java.io.ByteArrayOutputStream;
0052:        import java.io.IOException;
0053:        import java.io.InputStream;
0054:        import java.io.Reader;
0055:        import java.lang.reflect.Field;
0056:        import java.util.ArrayList;
0057:        import java.util.Date;
0058:        import java.util.HashMap;
0059:        import java.util.logging.*;
0060:
0061:        /**
0062:         * Input stream for Hessian requests.
0063:         *
0064:         * <p>HessianInput is unbuffered, so any client needs to provide
0065:         * its own buffering.
0066:         *
0067:         * <pre>
0068:         * InputStream is = ...; // from http connection
0069:         * HessianInput in = new HessianInput(is);
0070:         * String value;
0071:         *
0072:         * in.startReply();         // read reply header
0073:         * value = in.readString(); // read string value
0074:         * in.completeReply();      // read reply footer
0075:         * </pre>
0076:         */
0077:        public class Hessian2Input extends AbstractHessianInput implements 
0078:                Hessian2Constants {
0079:            private static final Logger log = Logger
0080:                    .getLogger(Hessian2Input.class.getName());
0081:
0082:            private static final double D_256 = 1.0 / 256.0;
0083:            private static final int END_OF_DATA = -2;
0084:
0085:            private static Field _detailMessageField;
0086:
0087:            private static final int SIZE = 256;
0088:            private static final int GAP = 16;
0089:
0090:            // factory for deserializing objects in the input stream
0091:            protected SerializerFactory _serializerFactory;
0092:
0093:            private static boolean _isCloseStreamOnClose;
0094:
0095:            protected ArrayList _refs;
0096:            protected ArrayList _classDefs;
0097:            protected ArrayList _types;
0098:
0099:            // the underlying input stream
0100:            private InputStream _is;
0101:            private final byte[] _buffer = new byte[SIZE];
0102:
0103:            // a peek character
0104:            private int _offset;
0105:            private int _length;
0106:
0107:            // true for streaming data
0108:            private boolean _isStreaming;
0109:
0110:            // the method for a call
0111:            private String _method;
0112:
0113:            private Reader _chunkReader;
0114:            private InputStream _chunkInputStream;
0115:
0116:            private Throwable _replyFault;
0117:
0118:            private StringBuffer _sbuf = new StringBuffer();
0119:
0120:            // true if this is the last chunk
0121:            private boolean _isLastChunk;
0122:            // the chunk length
0123:            private int _chunkLength;
0124:
0125:            /**
0126:             * Creates a new Hessian input stream, initialized with an
0127:             * underlying input stream.
0128:             *
0129:             * @param is the underlying input stream.
0130:             */
0131:            public Hessian2Input(InputStream is) {
0132:                _is = is;
0133:            }
0134:
0135:            /**
0136:             * Sets the serializer factory.
0137:             */
0138:            public void setSerializerFactory(SerializerFactory factory) {
0139:                _serializerFactory = factory;
0140:            }
0141:
0142:            /**
0143:             * Gets the serializer factory.
0144:             */
0145:            public SerializerFactory getSerializerFactory() {
0146:                return _serializerFactory;
0147:            }
0148:
0149:            /**
0150:             * Gets the serializer factory, creating a default if necessary.
0151:             */
0152:            public final SerializerFactory findSerializerFactory() {
0153:                SerializerFactory factory = _serializerFactory;
0154:
0155:                if (factory == null)
0156:                    _serializerFactory = factory = new SerializerFactory();
0157:
0158:                return factory;
0159:            }
0160:
0161:            public void setCloseStreamOnClose(boolean isClose) {
0162:                _isCloseStreamOnClose = isClose;
0163:            }
0164:
0165:            public boolean isCloseStreamOnClose() {
0166:                return _isCloseStreamOnClose;
0167:            }
0168:
0169:            /**
0170:             * Returns the calls method
0171:             */
0172:            public String getMethod() {
0173:                return _method;
0174:            }
0175:
0176:            /**
0177:             * Returns any reply fault.
0178:             */
0179:            public Throwable getReplyFault() {
0180:                return _replyFault;
0181:            }
0182:
0183:            /**
0184:             * Starts reading the call
0185:             *
0186:             * <pre>
0187:             * c major minor
0188:             * </pre>
0189:             */
0190:            public int readCall() throws IOException {
0191:                int tag = read();
0192:
0193:                if (tag != 'c')
0194:                    throw error("expected hessian call ('c') at "
0195:                            + codeName(tag));
0196:
0197:                int major = read();
0198:                int minor = read();
0199:
0200:                return (major << 16) + minor;
0201:            }
0202:
0203:            /**
0204:             * Starts reading the envelope
0205:             *
0206:             * <pre>
0207:             * E major minor
0208:             * </pre>
0209:             */
0210:            public int readEnvelope() throws IOException {
0211:                int tag = read();
0212:
0213:                if (tag != 'E')
0214:                    throw error("expected hessian Envelope ('E') at "
0215:                            + codeName(tag));
0216:
0217:                int major = read();
0218:                int minor = read();
0219:
0220:                return (major << 16) + minor;
0221:            }
0222:
0223:            /**
0224:             * Completes reading the envelope
0225:             *
0226:             * <p>A successful completion will have a single value:
0227:             *
0228:             * <pre>
0229:             * z
0230:             * </pre>
0231:             */
0232:            public void completeEnvelope() throws IOException {
0233:                int tag = read();
0234:
0235:                if (tag != 'z')
0236:                    error("expected end of envelope at " + codeName(tag));
0237:            }
0238:
0239:            /**
0240:             * Starts reading the call
0241:             *
0242:             * <p>A successful completion will have a single value:
0243:             *
0244:             * <pre>
0245:             * m b16 b8 method
0246:             * </pre>
0247:             */
0248:            public String readMethod() throws IOException {
0249:                int tag = read();
0250:
0251:                if (tag != 'm')
0252:                    throw error("expected hessian method ('m') at "
0253:                            + codeName(tag));
0254:
0255:                int d1 = read();
0256:                int d2 = read();
0257:
0258:                _isLastChunk = true;
0259:                _chunkLength = d1 * 256 + d2;
0260:                _sbuf.setLength(0);
0261:                int ch;
0262:                while ((ch = parseChar()) >= 0)
0263:                    _sbuf.append((char) ch);
0264:
0265:                _method = _sbuf.toString();
0266:
0267:                return _method;
0268:            }
0269:
0270:            /**
0271:             * Starts reading the call, including the headers.
0272:             *
0273:             * <p>The call expects the following protocol data
0274:             *
0275:             * <pre>
0276:             * c major minor
0277:             * m b16 b8 method
0278:             * </pre>
0279:             */
0280:            public void startCall() throws IOException {
0281:                readCall();
0282:
0283:                while (readHeader() != null) {
0284:                    readObject();
0285:                }
0286:
0287:                readMethod();
0288:            }
0289:
0290:            /**
0291:             * Completes reading the call
0292:             *
0293:             * <p>A successful completion will have a single value:
0294:             *
0295:             * <pre>
0296:             * z
0297:             * </pre>
0298:             */
0299:            public void completeCall() throws IOException {
0300:                int tag = read();
0301:
0302:                if (tag == 'z') {
0303:                } else if (tag < 0)
0304:                    throw error("expected end of call ('z') at end of stream.");
0305:                else
0306:                    throw error("expected end of call ('z') at "
0307:                            + codeName(tag)
0308:                            + ".  Check method arguments and ensure method overloading is enabled if necessary");
0309:            }
0310:
0311:            /**
0312:             * Reads a reply as an object.
0313:             * If the reply has a fault, throws the exception.
0314:             */
0315:            @Override
0316:            public Object readReply(Class expectedClass) throws Throwable {
0317:                int tag = read();
0318:
0319:                if (tag != 'r') {
0320:                    StringBuilder sb = new StringBuilder();
0321:                    sb.append((char) tag);
0322:
0323:                    try {
0324:                        int ch;
0325:
0326:                        while ((ch = read()) >= 0) {
0327:                            sb.append((char) ch);
0328:                        }
0329:                    } catch (IOException e) {
0330:                        log.log(Level.FINE, e.toString(), e);
0331:                    }
0332:
0333:                    throw error("expected hessian reply at " + codeName(tag)
0334:                            + "\n" + sb);
0335:                }
0336:
0337:                int major = read();
0338:                int minor = read();
0339:
0340:                if (major > 2 || major == 2 && minor > 0)
0341:                    throw error("Cannot understand Hessian " + major + "."
0342:                            + minor + " response");
0343:                tag = read();
0344:                if (tag == 'f')
0345:                    throw prepareFault();
0346:                else {
0347:                    if (tag >= 0)
0348:                        _offset--;
0349:
0350:                    Object value = readObject(expectedClass);
0351:
0352:                    completeValueReply();
0353:
0354:                    return value;
0355:                }
0356:            }
0357:
0358:            /**
0359:             * Starts reading the reply
0360:             *
0361:             * <p>A successful completion will have a single value:
0362:             *
0363:             * <pre>
0364:             * r
0365:             * </pre>
0366:             */
0367:            public void startReply() throws Throwable {
0368:                int tag = read();
0369:
0370:                if (tag != 'r') {
0371:                    StringBuilder sb = new StringBuilder();
0372:                    sb.append((char) tag);
0373:
0374:                    try {
0375:                        int ch;
0376:
0377:                        while ((ch = read()) >= 0) {
0378:                            sb.append((char) ch);
0379:                        }
0380:                    } catch (IOException e) {
0381:                        log.log(Level.FINE, e.toString(), e);
0382:                    }
0383:
0384:                    throw error("expected hessian reply at " + codeName(tag)
0385:                            + "\n" + sb);
0386:                }
0387:
0388:                int major = read();
0389:                int minor = read();
0390:
0391:                if (major > 2 || major == 2 && minor > 0)
0392:                    throw error("Cannot understand Hessian " + major + "."
0393:                            + minor + " response");
0394:
0395:                tag = read();
0396:                if (tag == 'f')
0397:                    throw prepareFault();
0398:                else if (tag >= 0)
0399:                    _offset--;
0400:            }
0401:
0402:            /**
0403:             * Prepares the fault.
0404:             */
0405:            private Throwable prepareFault() throws IOException {
0406:                HashMap fault = readFault();
0407:
0408:                Object detail = fault.get("detail");
0409:                String message = (String) fault.get("message");
0410:
0411:                if (detail instanceof  Throwable) {
0412:                    _replyFault = (Throwable) detail;
0413:
0414:                    if (message != null && _detailMessageField != null) {
0415:                        try {
0416:                            _detailMessageField.set(_replyFault, message);
0417:                        } catch (Throwable e) {
0418:                        }
0419:                    }
0420:
0421:                    return _replyFault;
0422:                }
0423:
0424:                else {
0425:                    String code = (String) fault.get("code");
0426:
0427:                    _replyFault = new HessianServiceException(message, code,
0428:                            detail);
0429:
0430:                    return _replyFault;
0431:                }
0432:            }
0433:
0434:            /**
0435:             * Completes reading the call
0436:             *
0437:             * <p>A successful completion will have a single value:
0438:             *
0439:             * <pre>
0440:             * z
0441:             * </pre>
0442:             */
0443:            public void completeReply() throws IOException {
0444:                int tag = read();
0445:
0446:                if (tag != 'z')
0447:                    error("expected end of reply at " + codeName(tag));
0448:            }
0449:
0450:            /**
0451:             * Completes reading the call
0452:             *
0453:             * <p>A successful completion will have a single value:
0454:             *
0455:             * <pre>
0456:             * z
0457:             * </pre>
0458:             */
0459:            public void completeValueReply() throws IOException {
0460:                int tag = read();
0461:
0462:                if (tag != 'z')
0463:                    error("expected end of reply at " + codeName(tag));
0464:            }
0465:
0466:            /**
0467:             * Reads a header, returning null if there are no headers.
0468:             *
0469:             * <pre>
0470:             * H b16 b8 value
0471:             * </pre>
0472:             */
0473:            public String readHeader() throws IOException {
0474:                int tag = read();
0475:
0476:                if (tag == 'H') {
0477:                    _isLastChunk = true;
0478:                    _chunkLength = (read() << 8) + read();
0479:
0480:                    _sbuf.setLength(0);
0481:                    int ch;
0482:                    while ((ch = parseChar()) >= 0)
0483:                        _sbuf.append((char) ch);
0484:
0485:                    return _sbuf.toString();
0486:                }
0487:
0488:                if (tag >= 0)
0489:                    _offset--;
0490:
0491:                return null;
0492:            }
0493:
0494:            /**
0495:             * Starts reading the message
0496:             *
0497:             * <pre>
0498:             * p major minor
0499:             * </pre>
0500:             */
0501:            public int startMessage() throws IOException {
0502:                int tag = read();
0503:
0504:                if (tag == 'p')
0505:                    _isStreaming = false;
0506:                else if (tag == 'P')
0507:                    _isStreaming = true;
0508:                else
0509:                    throw error("expected Hessian message ('p') at "
0510:                            + codeName(tag));
0511:
0512:                int major = read();
0513:                int minor = read();
0514:
0515:                return (major << 16) + minor;
0516:            }
0517:
0518:            /**
0519:             * Completes reading the message
0520:             *
0521:             * <p>A successful completion will have a single value:
0522:             *
0523:             * <pre>
0524:             * z
0525:             * </pre>
0526:             */
0527:            public void completeMessage() throws IOException {
0528:                int tag = read();
0529:
0530:                if (tag != 'z')
0531:                    error("expected end of message at " + codeName(tag));
0532:            }
0533:
0534:            /**
0535:             * Reads a null
0536:             *
0537:             * <pre>
0538:             * N
0539:             * </pre>
0540:             */
0541:            public void readNull() throws IOException {
0542:                int tag = read();
0543:
0544:                switch (tag) {
0545:                case 'N':
0546:                    return;
0547:
0548:                default:
0549:                    throw expect("null", tag);
0550:                }
0551:            }
0552:
0553:            /**
0554:             * Reads a boolean
0555:             *
0556:             * <pre>
0557:             * T
0558:             * F
0559:             * </pre>
0560:             */
0561:            public boolean readBoolean() throws IOException {
0562:                int tag = _offset < _length ? (_buffer[_offset++] & 0xff)
0563:                        : read();
0564:
0565:                switch (tag) {
0566:                case 'T':
0567:                    return true;
0568:                case 'F':
0569:                    return false;
0570:
0571:                    // direct integer
0572:                case 0x80:
0573:                case 0x81:
0574:                case 0x82:
0575:                case 0x83:
0576:                case 0x84:
0577:                case 0x85:
0578:                case 0x86:
0579:                case 0x87:
0580:                case 0x88:
0581:                case 0x89:
0582:                case 0x8a:
0583:                case 0x8b:
0584:                case 0x8c:
0585:                case 0x8d:
0586:                case 0x8e:
0587:                case 0x8f:
0588:
0589:                case 0x90:
0590:                case 0x91:
0591:                case 0x92:
0592:                case 0x93:
0593:                case 0x94:
0594:                case 0x95:
0595:                case 0x96:
0596:                case 0x97:
0597:                case 0x98:
0598:                case 0x99:
0599:                case 0x9a:
0600:                case 0x9b:
0601:                case 0x9c:
0602:                case 0x9d:
0603:                case 0x9e:
0604:                case 0x9f:
0605:
0606:                case 0xa0:
0607:                case 0xa1:
0608:                case 0xa2:
0609:                case 0xa3:
0610:                case 0xa4:
0611:                case 0xa5:
0612:                case 0xa6:
0613:                case 0xa7:
0614:                case 0xa8:
0615:                case 0xa9:
0616:                case 0xaa:
0617:                case 0xab:
0618:                case 0xac:
0619:                case 0xad:
0620:                case 0xae:
0621:                case 0xaf:
0622:
0623:                case 0xb0:
0624:                case 0xb1:
0625:                case 0xb2:
0626:                case 0xb3:
0627:                case 0xb4:
0628:                case 0xb5:
0629:                case 0xb6:
0630:                case 0xb7:
0631:                case 0xb8:
0632:                case 0xb9:
0633:                case 0xba:
0634:                case 0xbb:
0635:                case 0xbc:
0636:                case 0xbd:
0637:                case 0xbe:
0638:                case 0xbf:
0639:                    return tag != INT_ZERO;
0640:
0641:                    // INT_BYTE = 0
0642:                case 0xc8:
0643:                    return read() != 0;
0644:
0645:                    // INT_BYTE != 0
0646:                case 0xc0:
0647:                case 0xc1:
0648:                case 0xc2:
0649:                case 0xc3:
0650:                case 0xc4:
0651:                case 0xc5:
0652:                case 0xc6:
0653:                case 0xc7:
0654:                case 0xc9:
0655:                case 0xca:
0656:                case 0xcb:
0657:                case 0xcc:
0658:                case 0xcd:
0659:                case 0xce:
0660:                case 0xcf:
0661:                    read();
0662:                    return true;
0663:
0664:                    // INT_SHORT = 0
0665:                case 0xd4:
0666:                    return (256 * read() + read()) != 0;
0667:
0668:                    // INT_SHORT != 0
0669:                case 0xd0:
0670:                case 0xd1:
0671:                case 0xd2:
0672:                case 0xd3:
0673:                case 0xd5:
0674:                case 0xd6:
0675:                case 0xd7:
0676:                    read();
0677:                    read();
0678:                    return true;
0679:
0680:                case 'I':
0681:                    return parseInt() != 0;
0682:
0683:                case 0xd8:
0684:                case 0xd9:
0685:                case 0xda:
0686:                case 0xdb:
0687:                case 0xdc:
0688:                case 0xdd:
0689:                case 0xde:
0690:                case 0xdf:
0691:
0692:                case 0xe0:
0693:                case 0xe1:
0694:                case 0xe2:
0695:                case 0xe3:
0696:                case 0xe4:
0697:                case 0xe5:
0698:                case 0xe6:
0699:                case 0xe7:
0700:                case 0xe8:
0701:                case 0xe9:
0702:                case 0xea:
0703:                case 0xeb:
0704:                case 0xec:
0705:                case 0xed:
0706:                case 0xee:
0707:                case 0xef:
0708:                    return tag != LONG_ZERO;
0709:
0710:                    // LONG_BYTE = 0
0711:                case 0xf8:
0712:                    return read() != 0;
0713:
0714:                    // LONG_BYTE != 0
0715:                case 0xf0:
0716:                case 0xf1:
0717:                case 0xf2:
0718:                case 0xf3:
0719:                case 0xf4:
0720:                case 0xf5:
0721:                case 0xf6:
0722:                case 0xf7:
0723:                case 0xf9:
0724:                case 0xfa:
0725:                case 0xfb:
0726:                case 0xfc:
0727:                case 0xfd:
0728:                case 0xfe:
0729:                case 0xff:
0730:                    read();
0731:                    return true;
0732:
0733:                    // INT_SHORT = 0
0734:                case 0x3c:
0735:                    return (256 * read() + read()) != 0;
0736:
0737:                    // INT_SHORT != 0
0738:                case 0x38:
0739:                case 0x39:
0740:                case 0x3a:
0741:                case 0x3b:
0742:                case 0x3d:
0743:                case 0x3e:
0744:                case 0x3f:
0745:                    read();
0746:                    read();
0747:                    return true;
0748:
0749:                case LONG_INT:
0750:                    return (0x1000000L * read() + 0x10000L * read() + 0x100
0751:                            * read() + read()) != 0;
0752:
0753:                case 'L':
0754:                    return parseLong() != 0;
0755:
0756:                case DOUBLE_ZERO:
0757:                    return false;
0758:
0759:                case DOUBLE_ONE:
0760:                    return true;
0761:
0762:                case DOUBLE_BYTE:
0763:                    return read() != 0;
0764:
0765:                case DOUBLE_SHORT:
0766:                    return (0x100 * read() + read()) != 0;
0767:
0768:                case DOUBLE_FLOAT: {
0769:                    int f = parseInt();
0770:
0771:                    return Float.intBitsToFloat(f) != 0;
0772:                }
0773:
0774:                case 'D':
0775:                    return parseDouble() != 0.0;
0776:
0777:                case 'N':
0778:                    return false;
0779:
0780:                default:
0781:                    throw expect("boolean", tag);
0782:                }
0783:            }
0784:
0785:            /**
0786:             * Reads a short
0787:             *
0788:             * <pre>
0789:             * I b32 b24 b16 b8
0790:             * </pre>
0791:             */
0792:            public short readShort() throws IOException {
0793:                return (short) readInt();
0794:            }
0795:
0796:            /**
0797:             * Reads an integer
0798:             *
0799:             * <pre>
0800:             * I b32 b24 b16 b8
0801:             * </pre>
0802:             */
0803:            public final int readInt() throws IOException {
0804:                //int tag = _offset < _length ? (_buffer[_offset++] & 0xff) : read();
0805:                int tag = read();
0806:
0807:                switch (tag) {
0808:                case 'N':
0809:                    return 0;
0810:
0811:                case 'F':
0812:                    return 0;
0813:
0814:                case 'T':
0815:                    return 1;
0816:
0817:                    // direct integer
0818:                case 0x80:
0819:                case 0x81:
0820:                case 0x82:
0821:                case 0x83:
0822:                case 0x84:
0823:                case 0x85:
0824:                case 0x86:
0825:                case 0x87:
0826:                case 0x88:
0827:                case 0x89:
0828:                case 0x8a:
0829:                case 0x8b:
0830:                case 0x8c:
0831:                case 0x8d:
0832:                case 0x8e:
0833:                case 0x8f:
0834:
0835:                case 0x90:
0836:                case 0x91:
0837:                case 0x92:
0838:                case 0x93:
0839:                case 0x94:
0840:                case 0x95:
0841:                case 0x96:
0842:                case 0x97:
0843:                case 0x98:
0844:                case 0x99:
0845:                case 0x9a:
0846:                case 0x9b:
0847:                case 0x9c:
0848:                case 0x9d:
0849:                case 0x9e:
0850:                case 0x9f:
0851:
0852:                case 0xa0:
0853:                case 0xa1:
0854:                case 0xa2:
0855:                case 0xa3:
0856:                case 0xa4:
0857:                case 0xa5:
0858:                case 0xa6:
0859:                case 0xa7:
0860:                case 0xa8:
0861:                case 0xa9:
0862:                case 0xaa:
0863:                case 0xab:
0864:                case 0xac:
0865:                case 0xad:
0866:                case 0xae:
0867:                case 0xaf:
0868:
0869:                case 0xb0:
0870:                case 0xb1:
0871:                case 0xb2:
0872:                case 0xb3:
0873:                case 0xb4:
0874:                case 0xb5:
0875:                case 0xb6:
0876:                case 0xb7:
0877:                case 0xb8:
0878:                case 0xb9:
0879:                case 0xba:
0880:                case 0xbb:
0881:                case 0xbc:
0882:                case 0xbd:
0883:                case 0xbe:
0884:                case 0xbf:
0885:                    return tag - INT_ZERO;
0886:
0887:                    /* byte int */
0888:                case 0xc0:
0889:                case 0xc1:
0890:                case 0xc2:
0891:                case 0xc3:
0892:                case 0xc4:
0893:                case 0xc5:
0894:                case 0xc6:
0895:                case 0xc7:
0896:                case 0xc8:
0897:                case 0xc9:
0898:                case 0xca:
0899:                case 0xcb:
0900:                case 0xcc:
0901:                case 0xcd:
0902:                case 0xce:
0903:                case 0xcf:
0904:                    return ((tag - INT_BYTE_ZERO) << 8) + read();
0905:
0906:                    /* short int */
0907:                case 0xd0:
0908:                case 0xd1:
0909:                case 0xd2:
0910:                case 0xd3:
0911:                case 0xd4:
0912:                case 0xd5:
0913:                case 0xd6:
0914:                case 0xd7:
0915:                    return ((tag - INT_SHORT_ZERO) << 16) + 256 * read()
0916:                            + read();
0917:
0918:                case 'I':
0919:                case LONG_INT:
0920:                    return ((read() << 24) + (read() << 16) + (read() << 8) + read());
0921:
0922:                    // direct long
0923:                case 0xd8:
0924:                case 0xd9:
0925:                case 0xda:
0926:                case 0xdb:
0927:                case 0xdc:
0928:                case 0xdd:
0929:                case 0xde:
0930:                case 0xdf:
0931:
0932:                case 0xe0:
0933:                case 0xe1:
0934:                case 0xe2:
0935:                case 0xe3:
0936:                case 0xe4:
0937:                case 0xe5:
0938:                case 0xe6:
0939:                case 0xe7:
0940:                case 0xe8:
0941:                case 0xe9:
0942:                case 0xea:
0943:                case 0xeb:
0944:                case 0xec:
0945:                case 0xed:
0946:                case 0xee:
0947:                case 0xef:
0948:                    return tag - LONG_ZERO;
0949:
0950:                    /* byte long */
0951:                case 0xf0:
0952:                case 0xf1:
0953:                case 0xf2:
0954:                case 0xf3:
0955:                case 0xf4:
0956:                case 0xf5:
0957:                case 0xf6:
0958:                case 0xf7:
0959:                case 0xf8:
0960:                case 0xf9:
0961:                case 0xfa:
0962:                case 0xfb:
0963:                case 0xfc:
0964:                case 0xfd:
0965:                case 0xfe:
0966:                case 0xff:
0967:                    return ((tag - LONG_BYTE_ZERO) << 8) + read();
0968:
0969:                    /* short long */
0970:                case 0x38:
0971:                case 0x39:
0972:                case 0x3a:
0973:                case 0x3b:
0974:                case 0x3c:
0975:                case 0x3d:
0976:                case 0x3e:
0977:                case 0x3f:
0978:                    return ((tag - LONG_SHORT_ZERO) << 16) + 256 * read()
0979:                            + read();
0980:
0981:                case 'L':
0982:                    return (int) parseLong();
0983:
0984:                case DOUBLE_ZERO:
0985:                    return 0;
0986:
0987:                case DOUBLE_ONE:
0988:                    return 1;
0989:
0990:                    //case LONG_BYTE:
0991:                case DOUBLE_BYTE:
0992:                    return (byte) (_offset < _length ? _buffer[_offset++]
0993:                            : read());
0994:
0995:                    //case INT_SHORT:
0996:                    //case LONG_SHORT:
0997:                case DOUBLE_SHORT:
0998:                    return (short) (256 * read() + read());
0999:
1000:                case DOUBLE_FLOAT: {
1001:                    int f = parseInt();
1002:
1003:                    return (int) Float.intBitsToFloat(f);
1004:                }
1005:
1006:                case 'D':
1007:                    return (int) parseDouble();
1008:
1009:                default:
1010:                    throw expect("integer", tag);
1011:                }
1012:            }
1013:
1014:            /**
1015:             * Reads a long
1016:             *
1017:             * <pre>
1018:             * L b64 b56 b48 b40 b32 b24 b16 b8
1019:             * </pre>
1020:             */
1021:            public long readLong() throws IOException {
1022:                int tag = read();
1023:
1024:                switch (tag) {
1025:                case 'N':
1026:                    return 0;
1027:
1028:                case 'F':
1029:                    return 0;
1030:
1031:                case 'T':
1032:                    return 1;
1033:
1034:                    // direct integer
1035:                case 0x80:
1036:                case 0x81:
1037:                case 0x82:
1038:                case 0x83:
1039:                case 0x84:
1040:                case 0x85:
1041:                case 0x86:
1042:                case 0x87:
1043:                case 0x88:
1044:                case 0x89:
1045:                case 0x8a:
1046:                case 0x8b:
1047:                case 0x8c:
1048:                case 0x8d:
1049:                case 0x8e:
1050:                case 0x8f:
1051:
1052:                case 0x90:
1053:                case 0x91:
1054:                case 0x92:
1055:                case 0x93:
1056:                case 0x94:
1057:                case 0x95:
1058:                case 0x96:
1059:                case 0x97:
1060:                case 0x98:
1061:                case 0x99:
1062:                case 0x9a:
1063:                case 0x9b:
1064:                case 0x9c:
1065:                case 0x9d:
1066:                case 0x9e:
1067:                case 0x9f:
1068:
1069:                case 0xa0:
1070:                case 0xa1:
1071:                case 0xa2:
1072:                case 0xa3:
1073:                case 0xa4:
1074:                case 0xa5:
1075:                case 0xa6:
1076:                case 0xa7:
1077:                case 0xa8:
1078:                case 0xa9:
1079:                case 0xaa:
1080:                case 0xab:
1081:                case 0xac:
1082:                case 0xad:
1083:                case 0xae:
1084:                case 0xaf:
1085:
1086:                case 0xb0:
1087:                case 0xb1:
1088:                case 0xb2:
1089:                case 0xb3:
1090:                case 0xb4:
1091:                case 0xb5:
1092:                case 0xb6:
1093:                case 0xb7:
1094:                case 0xb8:
1095:                case 0xb9:
1096:                case 0xba:
1097:                case 0xbb:
1098:                case 0xbc:
1099:                case 0xbd:
1100:                case 0xbe:
1101:                case 0xbf:
1102:                    return tag - INT_ZERO;
1103:
1104:                    /* byte int */
1105:                case 0xc0:
1106:                case 0xc1:
1107:                case 0xc2:
1108:                case 0xc3:
1109:                case 0xc4:
1110:                case 0xc5:
1111:                case 0xc6:
1112:                case 0xc7:
1113:                case 0xc8:
1114:                case 0xc9:
1115:                case 0xca:
1116:                case 0xcb:
1117:                case 0xcc:
1118:                case 0xcd:
1119:                case 0xce:
1120:                case 0xcf:
1121:                    return ((tag - INT_BYTE_ZERO) << 8) + read();
1122:
1123:                    /* short int */
1124:                case 0xd0:
1125:                case 0xd1:
1126:                case 0xd2:
1127:                case 0xd3:
1128:                case 0xd4:
1129:                case 0xd5:
1130:                case 0xd6:
1131:                case 0xd7:
1132:                    return ((tag - INT_SHORT_ZERO) << 16) + 256 * read()
1133:                            + read();
1134:
1135:                    //case LONG_BYTE:
1136:                case DOUBLE_BYTE:
1137:                    return (byte) (_offset < _length ? _buffer[_offset++]
1138:                            : read());
1139:
1140:                    //case INT_SHORT:
1141:                    //case LONG_SHORT:
1142:                case DOUBLE_SHORT:
1143:                    return (short) (256 * read() + read());
1144:
1145:                case 'I':
1146:                case LONG_INT:
1147:                    return parseInt();
1148:
1149:                    // direct long
1150:                case 0xd8:
1151:                case 0xd9:
1152:                case 0xda:
1153:                case 0xdb:
1154:                case 0xdc:
1155:                case 0xdd:
1156:                case 0xde:
1157:                case 0xdf:
1158:
1159:                case 0xe0:
1160:                case 0xe1:
1161:                case 0xe2:
1162:                case 0xe3:
1163:                case 0xe4:
1164:                case 0xe5:
1165:                case 0xe6:
1166:                case 0xe7:
1167:                case 0xe8:
1168:                case 0xe9:
1169:                case 0xea:
1170:                case 0xeb:
1171:                case 0xec:
1172:                case 0xed:
1173:                case 0xee:
1174:                case 0xef:
1175:                    return tag - LONG_ZERO;
1176:
1177:                    /* byte long */
1178:                case 0xf0:
1179:                case 0xf1:
1180:                case 0xf2:
1181:                case 0xf3:
1182:                case 0xf4:
1183:                case 0xf5:
1184:                case 0xf6:
1185:                case 0xf7:
1186:                case 0xf8:
1187:                case 0xf9:
1188:                case 0xfa:
1189:                case 0xfb:
1190:                case 0xfc:
1191:                case 0xfd:
1192:                case 0xfe:
1193:                case 0xff:
1194:                    return ((tag - LONG_BYTE_ZERO) << 8) + read();
1195:
1196:                    /* short long */
1197:                case 0x38:
1198:                case 0x39:
1199:                case 0x3a:
1200:                case 0x3b:
1201:                case 0x3c:
1202:                case 0x3d:
1203:                case 0x3e:
1204:                case 0x3f:
1205:                    return ((tag - LONG_SHORT_ZERO) << 16) + 256 * read()
1206:                            + read();
1207:
1208:                case 'L':
1209:                    return parseLong();
1210:
1211:                case DOUBLE_ZERO:
1212:                    return 0;
1213:
1214:                case DOUBLE_ONE:
1215:                    return 1;
1216:
1217:                case DOUBLE_FLOAT: {
1218:                    int f = parseInt();
1219:
1220:                    return (long) Float.intBitsToFloat(f);
1221:                }
1222:
1223:                case 'D':
1224:                    return (long) parseDouble();
1225:
1226:                default:
1227:                    throw expect("long", tag);
1228:                }
1229:            }
1230:
1231:            /**
1232:             * Reads a float
1233:             *
1234:             * <pre>
1235:             * D b64 b56 b48 b40 b32 b24 b16 b8
1236:             * </pre>
1237:             */
1238:            public float readFloat() throws IOException {
1239:                return (float) readDouble();
1240:            }
1241:
1242:            /**
1243:             * Reads a double
1244:             *
1245:             * <pre>
1246:             * D b64 b56 b48 b40 b32 b24 b16 b8
1247:             * </pre>
1248:             */
1249:            public double readDouble() throws IOException {
1250:                int tag = read();
1251:
1252:                switch (tag) {
1253:                case 'N':
1254:                    return 0;
1255:
1256:                case 'F':
1257:                    return 0;
1258:
1259:                case 'T':
1260:                    return 1;
1261:
1262:                    // direct integer
1263:                case 0x80:
1264:                case 0x81:
1265:                case 0x82:
1266:                case 0x83:
1267:                case 0x84:
1268:                case 0x85:
1269:                case 0x86:
1270:                case 0x87:
1271:                case 0x88:
1272:                case 0x89:
1273:                case 0x8a:
1274:                case 0x8b:
1275:                case 0x8c:
1276:                case 0x8d:
1277:                case 0x8e:
1278:                case 0x8f:
1279:
1280:                case 0x90:
1281:                case 0x91:
1282:                case 0x92:
1283:                case 0x93:
1284:                case 0x94:
1285:                case 0x95:
1286:                case 0x96:
1287:                case 0x97:
1288:                case 0x98:
1289:                case 0x99:
1290:                case 0x9a:
1291:                case 0x9b:
1292:                case 0x9c:
1293:                case 0x9d:
1294:                case 0x9e:
1295:                case 0x9f:
1296:
1297:                case 0xa0:
1298:                case 0xa1:
1299:                case 0xa2:
1300:                case 0xa3:
1301:                case 0xa4:
1302:                case 0xa5:
1303:                case 0xa6:
1304:                case 0xa7:
1305:                case 0xa8:
1306:                case 0xa9:
1307:                case 0xaa:
1308:                case 0xab:
1309:                case 0xac:
1310:                case 0xad:
1311:                case 0xae:
1312:                case 0xaf:
1313:
1314:                case 0xb0:
1315:                case 0xb1:
1316:                case 0xb2:
1317:                case 0xb3:
1318:                case 0xb4:
1319:                case 0xb5:
1320:                case 0xb6:
1321:                case 0xb7:
1322:                case 0xb8:
1323:                case 0xb9:
1324:                case 0xba:
1325:                case 0xbb:
1326:                case 0xbc:
1327:                case 0xbd:
1328:                case 0xbe:
1329:                case 0xbf:
1330:                    return tag - 0x90;
1331:
1332:                    /* byte int */
1333:                case 0xc0:
1334:                case 0xc1:
1335:                case 0xc2:
1336:                case 0xc3:
1337:                case 0xc4:
1338:                case 0xc5:
1339:                case 0xc6:
1340:                case 0xc7:
1341:                case 0xc8:
1342:                case 0xc9:
1343:                case 0xca:
1344:                case 0xcb:
1345:                case 0xcc:
1346:                case 0xcd:
1347:                case 0xce:
1348:                case 0xcf:
1349:                    return ((tag - INT_BYTE_ZERO) << 8) + read();
1350:
1351:                    /* short int */
1352:                case 0xd0:
1353:                case 0xd1:
1354:                case 0xd2:
1355:                case 0xd3:
1356:                case 0xd4:
1357:                case 0xd5:
1358:                case 0xd6:
1359:                case 0xd7:
1360:                    return ((tag - INT_SHORT_ZERO) << 16) + 256 * read()
1361:                            + read();
1362:
1363:                case 'I':
1364:                case LONG_INT:
1365:                    return parseInt();
1366:
1367:                    // direct long
1368:                case 0xd8:
1369:                case 0xd9:
1370:                case 0xda:
1371:                case 0xdb:
1372:                case 0xdc:
1373:                case 0xdd:
1374:                case 0xde:
1375:                case 0xdf:
1376:
1377:                case 0xe0:
1378:                case 0xe1:
1379:                case 0xe2:
1380:                case 0xe3:
1381:                case 0xe4:
1382:                case 0xe5:
1383:                case 0xe6:
1384:                case 0xe7:
1385:                case 0xe8:
1386:                case 0xe9:
1387:                case 0xea:
1388:                case 0xeb:
1389:                case 0xec:
1390:                case 0xed:
1391:                case 0xee:
1392:                case 0xef:
1393:                    return tag - LONG_ZERO;
1394:
1395:                    /* byte long */
1396:                case 0xf0:
1397:                case 0xf1:
1398:                case 0xf2:
1399:                case 0xf3:
1400:                case 0xf4:
1401:                case 0xf5:
1402:                case 0xf6:
1403:                case 0xf7:
1404:                case 0xf8:
1405:                case 0xf9:
1406:                case 0xfa:
1407:                case 0xfb:
1408:                case 0xfc:
1409:                case 0xfd:
1410:                case 0xfe:
1411:                case 0xff:
1412:                    return ((tag - LONG_BYTE_ZERO) << 8) + read();
1413:
1414:                    /* short long */
1415:                case 0x38:
1416:                case 0x39:
1417:                case 0x3a:
1418:                case 0x3b:
1419:                case 0x3c:
1420:                case 0x3d:
1421:                case 0x3e:
1422:                case 0x3f:
1423:                    return ((tag - LONG_SHORT_ZERO) << 16) + 256 * read()
1424:                            + read();
1425:
1426:                case 'L':
1427:                    return (double) parseLong();
1428:
1429:                case DOUBLE_ZERO:
1430:                    return 0;
1431:
1432:                case DOUBLE_ONE:
1433:                    return 1;
1434:
1435:                case DOUBLE_BYTE:
1436:                    return (byte) (_offset < _length ? _buffer[_offset++]
1437:                            : read());
1438:
1439:                case DOUBLE_SHORT:
1440:                    return (short) (256 * read() + read());
1441:
1442:                case DOUBLE_FLOAT: {
1443:                    int f = parseInt();
1444:
1445:                    return Float.intBitsToFloat(f);
1446:                }
1447:
1448:                case 'D':
1449:                    return parseDouble();
1450:
1451:                default:
1452:                    throw expect("double", tag);
1453:                }
1454:            }
1455:
1456:            /**
1457:             * Reads a date.
1458:             *
1459:             * <pre>
1460:             * T b64 b56 b48 b40 b32 b24 b16 b8
1461:             * </pre>
1462:             */
1463:            public long readUTCDate() throws IOException {
1464:                int tag = read();
1465:
1466:                if (tag != 'd')
1467:                    throw expect("date", tag);
1468:
1469:                long b64 = read();
1470:                long b56 = read();
1471:                long b48 = read();
1472:                long b40 = read();
1473:                long b32 = read();
1474:                long b24 = read();
1475:                long b16 = read();
1476:                long b8 = read();
1477:
1478:                return ((b64 << 56) + (b56 << 48) + (b48 << 40) + (b40 << 32)
1479:                        + (b32 << 24) + (b24 << 16) + (b16 << 8) + b8);
1480:            }
1481:
1482:            /**
1483:             * Reads a byte from the stream.
1484:             */
1485:            public int readChar() throws IOException {
1486:                if (_chunkLength > 0) {
1487:                    _chunkLength--;
1488:                    if (_chunkLength == 0 && _isLastChunk)
1489:                        _chunkLength = END_OF_DATA;
1490:
1491:                    int ch = parseUTF8Char();
1492:                    return ch;
1493:                } else if (_chunkLength == END_OF_DATA) {
1494:                    _chunkLength = 0;
1495:                    return -1;
1496:                }
1497:
1498:                int tag = read();
1499:
1500:                switch (tag) {
1501:                case 'N':
1502:                    return -1;
1503:
1504:                case 'S':
1505:                case 's':
1506:                case 'X':
1507:                case 'x':
1508:                    _isLastChunk = tag == 'S' || tag == 'X';
1509:                    _chunkLength = (read() << 8) + read();
1510:
1511:                    _chunkLength--;
1512:                    int value = parseUTF8Char();
1513:
1514:                    // special code so successive read byte won't
1515:                    // be read as a single object.
1516:                    if (_chunkLength == 0 && _isLastChunk)
1517:                        _chunkLength = END_OF_DATA;
1518:
1519:                    return value;
1520:
1521:                default:
1522:                    throw expect("char", tag);
1523:                }
1524:            }
1525:
1526:            /**
1527:             * Reads a byte array from the stream.
1528:             */
1529:            public int readString(char[] buffer, int offset, int length)
1530:                    throws IOException {
1531:                int readLength = 0;
1532:
1533:                if (_chunkLength == END_OF_DATA) {
1534:                    _chunkLength = 0;
1535:                    return -1;
1536:                } else if (_chunkLength == 0) {
1537:                    int tag = read();
1538:
1539:                    switch (tag) {
1540:                    case 'N':
1541:                        return -1;
1542:
1543:                    case 'S':
1544:                    case 's':
1545:                    case 'X':
1546:                    case 'x':
1547:                        _isLastChunk = tag == 'S' || tag == 'X';
1548:                        _chunkLength = (read() << 8) + read();
1549:                        break;
1550:
1551:                    case 0x00:
1552:                    case 0x01:
1553:                    case 0x02:
1554:                    case 0x03:
1555:                    case 0x04:
1556:                    case 0x05:
1557:                    case 0x06:
1558:                    case 0x07:
1559:                    case 0x08:
1560:                    case 0x09:
1561:                    case 0x0a:
1562:                    case 0x0b:
1563:                    case 0x0c:
1564:                    case 0x0d:
1565:                    case 0x0e:
1566:                    case 0x0f:
1567:
1568:                    case 0x10:
1569:                    case 0x11:
1570:                    case 0x12:
1571:                    case 0x13:
1572:                    case 0x14:
1573:                    case 0x15:
1574:                    case 0x16:
1575:                    case 0x17:
1576:                    case 0x18:
1577:                    case 0x19:
1578:                    case 0x1a:
1579:                    case 0x1b:
1580:                    case 0x1c:
1581:                    case 0x1d:
1582:                    case 0x1e:
1583:                    case 0x1f:
1584:                        _isLastChunk = true;
1585:                        _chunkLength = tag - 0x00;
1586:                        break;
1587:
1588:                    default:
1589:                        throw expect("string", tag);
1590:                    }
1591:                }
1592:
1593:                while (length > 0) {
1594:                    if (_chunkLength > 0) {
1595:                        buffer[offset++] = (char) parseUTF8Char();
1596:                        _chunkLength--;
1597:                        length--;
1598:                        readLength++;
1599:                    } else if (_isLastChunk) {
1600:                        if (readLength == 0)
1601:                            return -1;
1602:                        else {
1603:                            _chunkLength = END_OF_DATA;
1604:                            return readLength;
1605:                        }
1606:                    } else {
1607:                        int tag = read();
1608:
1609:                        switch (tag) {
1610:                        case 'S':
1611:                        case 's':
1612:                        case 'X':
1613:                        case 'x':
1614:                            _isLastChunk = tag == 'S' || tag == 'X';
1615:                            _chunkLength = (read() << 8) + read();
1616:                            break;
1617:
1618:                        default:
1619:                            throw expect("string", tag);
1620:                        }
1621:                    }
1622:                }
1623:
1624:                if (readLength == 0)
1625:                    return -1;
1626:                else if (_chunkLength > 0 || !_isLastChunk)
1627:                    return readLength;
1628:                else {
1629:                    _chunkLength = END_OF_DATA;
1630:                    return readLength;
1631:                }
1632:            }
1633:
1634:            /**
1635:             * Reads a string
1636:             *
1637:             * <pre>
1638:             * S b16 b8 string value
1639:             * </pre>
1640:             */
1641:            public String readString() throws IOException {
1642:                int tag = read();
1643:
1644:                switch (tag) {
1645:                case 'N':
1646:                    return null;
1647:                case 'T':
1648:                    return "true";
1649:                case 'F':
1650:                    return "false";
1651:
1652:                    // direct integer
1653:                case 0x80:
1654:                case 0x81:
1655:                case 0x82:
1656:                case 0x83:
1657:                case 0x84:
1658:                case 0x85:
1659:                case 0x86:
1660:                case 0x87:
1661:                case 0x88:
1662:                case 0x89:
1663:                case 0x8a:
1664:                case 0x8b:
1665:                case 0x8c:
1666:                case 0x8d:
1667:                case 0x8e:
1668:                case 0x8f:
1669:
1670:                case 0x90:
1671:                case 0x91:
1672:                case 0x92:
1673:                case 0x93:
1674:                case 0x94:
1675:                case 0x95:
1676:                case 0x96:
1677:                case 0x97:
1678:                case 0x98:
1679:                case 0x99:
1680:                case 0x9a:
1681:                case 0x9b:
1682:                case 0x9c:
1683:                case 0x9d:
1684:                case 0x9e:
1685:                case 0x9f:
1686:
1687:                case 0xa0:
1688:                case 0xa1:
1689:                case 0xa2:
1690:                case 0xa3:
1691:                case 0xa4:
1692:                case 0xa5:
1693:                case 0xa6:
1694:                case 0xa7:
1695:                case 0xa8:
1696:                case 0xa9:
1697:                case 0xaa:
1698:                case 0xab:
1699:                case 0xac:
1700:                case 0xad:
1701:                case 0xae:
1702:                case 0xaf:
1703:
1704:                case 0xb0:
1705:                case 0xb1:
1706:                case 0xb2:
1707:                case 0xb3:
1708:                case 0xb4:
1709:                case 0xb5:
1710:                case 0xb6:
1711:                case 0xb7:
1712:                case 0xb8:
1713:                case 0xb9:
1714:                case 0xba:
1715:                case 0xbb:
1716:                case 0xbc:
1717:                case 0xbd:
1718:                case 0xbe:
1719:                case 0xbf:
1720:                    return String.valueOf((tag - 0x90));
1721:
1722:                    /* byte int */
1723:                case 0xc0:
1724:                case 0xc1:
1725:                case 0xc2:
1726:                case 0xc3:
1727:                case 0xc4:
1728:                case 0xc5:
1729:                case 0xc6:
1730:                case 0xc7:
1731:                case 0xc8:
1732:                case 0xc9:
1733:                case 0xca:
1734:                case 0xcb:
1735:                case 0xcc:
1736:                case 0xcd:
1737:                case 0xce:
1738:                case 0xcf:
1739:                    return String
1740:                            .valueOf(((tag - INT_BYTE_ZERO) << 8) + read());
1741:
1742:                    /* short int */
1743:                case 0xd0:
1744:                case 0xd1:
1745:                case 0xd2:
1746:                case 0xd3:
1747:                case 0xd4:
1748:                case 0xd5:
1749:                case 0xd6:
1750:                case 0xd7:
1751:                    return String.valueOf(((tag - INT_SHORT_ZERO) << 16) + 256
1752:                            * read() + read());
1753:
1754:                case 'I':
1755:                case LONG_INT:
1756:                    return String.valueOf(parseInt());
1757:
1758:                    // direct long
1759:                case 0xd8:
1760:                case 0xd9:
1761:                case 0xda:
1762:                case 0xdb:
1763:                case 0xdc:
1764:                case 0xdd:
1765:                case 0xde:
1766:                case 0xdf:
1767:
1768:                case 0xe0:
1769:                case 0xe1:
1770:                case 0xe2:
1771:                case 0xe3:
1772:                case 0xe4:
1773:                case 0xe5:
1774:                case 0xe6:
1775:                case 0xe7:
1776:                case 0xe8:
1777:                case 0xe9:
1778:                case 0xea:
1779:                case 0xeb:
1780:                case 0xec:
1781:                case 0xed:
1782:                case 0xee:
1783:                case 0xef:
1784:                    return String.valueOf(tag - LONG_ZERO);
1785:
1786:                    /* byte long */
1787:                case 0xf0:
1788:                case 0xf1:
1789:                case 0xf2:
1790:                case 0xf3:
1791:                case 0xf4:
1792:                case 0xf5:
1793:                case 0xf6:
1794:                case 0xf7:
1795:                case 0xf8:
1796:                case 0xf9:
1797:                case 0xfa:
1798:                case 0xfb:
1799:                case 0xfc:
1800:                case 0xfd:
1801:                case 0xfe:
1802:                case 0xff:
1803:                    return String.valueOf(((tag - LONG_BYTE_ZERO) << 8)
1804:                            + read());
1805:
1806:                    /* short long */
1807:                case 0x38:
1808:                case 0x39:
1809:                case 0x3a:
1810:                case 0x3b:
1811:                case 0x3c:
1812:                case 0x3d:
1813:                case 0x3e:
1814:                case 0x3f:
1815:                    return String.valueOf(((tag - LONG_SHORT_ZERO) << 16) + 256
1816:                            * read() + read());
1817:
1818:                case 'L':
1819:                    return String.valueOf(parseLong());
1820:
1821:                case DOUBLE_ZERO:
1822:                    return "0.0";
1823:
1824:                case DOUBLE_ONE:
1825:                    return "1.0";
1826:
1827:                case DOUBLE_BYTE:
1828:                    return String
1829:                            .valueOf((byte) (_offset < _length ? _buffer[_offset++]
1830:                                    : read()));
1831:
1832:                case DOUBLE_SHORT:
1833:                    return String.valueOf(((short) (256 * read() + read())));
1834:
1835:                case DOUBLE_FLOAT: {
1836:                    int f = parseInt();
1837:
1838:                    return String.valueOf(Float.intBitsToFloat(f));
1839:                }
1840:
1841:                case 'D':
1842:                    return String.valueOf(parseDouble());
1843:
1844:                case 'S':
1845:                case 's':
1846:                case 'X':
1847:                case 'x':
1848:                    _isLastChunk = tag == 'S' || tag == 'X';
1849:                    _chunkLength = (read() << 8) + read();
1850:
1851:                    _sbuf.setLength(0);
1852:                    int ch;
1853:
1854:                    while ((ch = parseChar()) >= 0)
1855:                        _sbuf.append((char) ch);
1856:
1857:                    return _sbuf.toString();
1858:
1859:                    // 0-byte string
1860:                case 0x00:
1861:                case 0x01:
1862:                case 0x02:
1863:                case 0x03:
1864:                case 0x04:
1865:                case 0x05:
1866:                case 0x06:
1867:                case 0x07:
1868:                case 0x08:
1869:                case 0x09:
1870:                case 0x0a:
1871:                case 0x0b:
1872:                case 0x0c:
1873:                case 0x0d:
1874:                case 0x0e:
1875:                case 0x0f:
1876:
1877:                case 0x10:
1878:                case 0x11:
1879:                case 0x12:
1880:                case 0x13:
1881:                case 0x14:
1882:                case 0x15:
1883:                case 0x16:
1884:                case 0x17:
1885:                case 0x18:
1886:                case 0x19:
1887:                case 0x1a:
1888:                case 0x1b:
1889:                case 0x1c:
1890:                case 0x1d:
1891:                case 0x1e:
1892:                case 0x1f:
1893:                    _isLastChunk = true;
1894:                    _chunkLength = tag - 0x00;
1895:
1896:                    _sbuf.setLength(0);
1897:
1898:                    while ((ch = parseChar()) >= 0)
1899:                        _sbuf.append((char) ch);
1900:
1901:                    return _sbuf.toString();
1902:
1903:                default:
1904:                    throw expect("string", tag);
1905:                }
1906:            }
1907:
1908:            /**
1909:             * Reads an XML node.
1910:             *
1911:             * <pre>
1912:             * S b16 b8 string value
1913:             * </pre>
1914:             */
1915:            public org.w3c.dom.Node readNode() throws IOException {
1916:                int tag = read();
1917:
1918:                switch (tag) {
1919:                case 'N':
1920:                    return null;
1921:
1922:                case 'S':
1923:                case 's':
1924:                case 'X':
1925:                case 'x':
1926:                    _isLastChunk = tag == 'S' || tag == 'X';
1927:                    _chunkLength = (read() << 8) + read();
1928:
1929:                    throw error("XML is not supported");
1930:
1931:                case 0x00:
1932:                case 0x01:
1933:                case 0x02:
1934:                case 0x03:
1935:                case 0x04:
1936:                case 0x05:
1937:                case 0x06:
1938:                case 0x07:
1939:                case 0x08:
1940:                case 0x09:
1941:                case 0x0a:
1942:                case 0x0b:
1943:                case 0x0c:
1944:                case 0x0d:
1945:                case 0x0e:
1946:                case 0x0f:
1947:
1948:                case 0x10:
1949:                case 0x11:
1950:                case 0x12:
1951:                case 0x13:
1952:                case 0x14:
1953:                case 0x15:
1954:                case 0x16:
1955:                case 0x17:
1956:                case 0x18:
1957:                case 0x19:
1958:                case 0x1a:
1959:                case 0x1b:
1960:                case 0x1c:
1961:                case 0x1d:
1962:                case 0x1e:
1963:                case 0x1f:
1964:                    _isLastChunk = true;
1965:                    _chunkLength = tag - 0x00;
1966:
1967:                    throw error("XML is not supported");
1968:
1969:                default:
1970:                    throw expect("string", tag);
1971:                }
1972:            }
1973:
1974:            /**
1975:             * Reads a byte array
1976:             *
1977:             * <pre>
1978:             * B b16 b8 data value
1979:             * </pre>
1980:             */
1981:            public byte[] readBytes() throws IOException {
1982:                int tag = read();
1983:
1984:                switch (tag) {
1985:                case 'N':
1986:                    return null;
1987:
1988:                case 'B':
1989:                case 'b':
1990:                    _isLastChunk = tag == 'B';
1991:                    _chunkLength = (read() << 8) + read();
1992:
1993:                    ByteArrayOutputStream bos = new ByteArrayOutputStream();
1994:
1995:                    int data;
1996:                    while ((data = parseByte()) >= 0)
1997:                        bos.write(data);
1998:
1999:                    return bos.toByteArray();
2000:
2001:                case 0x20:
2002:                case 0x21:
2003:                case 0x22:
2004:                case 0x23:
2005:                case 0x24:
2006:                case 0x25:
2007:                case 0x26:
2008:                case 0x27:
2009:                case 0x28:
2010:                case 0x29:
2011:                case 0x2a:
2012:                case 0x2b:
2013:                case 0x2c:
2014:                case 0x2d:
2015:                case 0x2e:
2016:                case 0x2f:
2017:                    _isLastChunk = true;
2018:                    _chunkLength = tag - 0x20;
2019:
2020:                    bos = new ByteArrayOutputStream();
2021:
2022:                    while ((data = parseByte()) >= 0)
2023:                        bos.write(data);
2024:
2025:                    return bos.toByteArray();
2026:
2027:                default:
2028:                    throw expect("bytes", tag);
2029:                }
2030:            }
2031:
2032:            /**
2033:             * Reads a byte from the stream.
2034:             */
2035:            public int readByte() throws IOException {
2036:                if (_chunkLength > 0) {
2037:                    _chunkLength--;
2038:                    if (_chunkLength == 0 && _isLastChunk)
2039:                        _chunkLength = END_OF_DATA;
2040:
2041:                    return read();
2042:                } else if (_chunkLength == END_OF_DATA) {
2043:                    _chunkLength = 0;
2044:                    return -1;
2045:                }
2046:
2047:                int tag = read();
2048:
2049:                switch (tag) {
2050:                case 'N':
2051:                    return -1;
2052:
2053:                case 'B':
2054:                case 'b':
2055:                    _isLastChunk = tag == 'B';
2056:                    _chunkLength = (read() << 8) + read();
2057:
2058:                    int value = parseByte();
2059:
2060:                    // special code so successive read byte won't
2061:                    // be read as a single object.
2062:                    if (_chunkLength == 0 && _isLastChunk)
2063:                        _chunkLength = END_OF_DATA;
2064:
2065:                    return value;
2066:
2067:                default:
2068:                    throw expect("binary", tag);
2069:                }
2070:            }
2071:
2072:            /**
2073:             * Reads a byte array from the stream.
2074:             */
2075:            public int readBytes(byte[] buffer, int offset, int length)
2076:                    throws IOException {
2077:                int readLength = 0;
2078:
2079:                if (_chunkLength == END_OF_DATA) {
2080:                    _chunkLength = 0;
2081:                    return -1;
2082:                } else if (_chunkLength == 0) {
2083:                    int tag = read();
2084:
2085:                    switch (tag) {
2086:                    case 'N':
2087:                        return -1;
2088:
2089:                    case 'B':
2090:                    case 'b':
2091:                        _isLastChunk = tag == 'B';
2092:                        _chunkLength = (read() << 8) + read();
2093:                        break;
2094:
2095:                    default:
2096:                        throw expect("binary", tag);
2097:                    }
2098:                }
2099:
2100:                while (length > 0) {
2101:                    if (_chunkLength > 0) {
2102:                        buffer[offset++] = (byte) read();
2103:                        _chunkLength--;
2104:                        length--;
2105:                        readLength++;
2106:                    } else if (_isLastChunk) {
2107:                        if (readLength == 0)
2108:                            return -1;
2109:                        else {
2110:                            _chunkLength = END_OF_DATA;
2111:                            return readLength;
2112:                        }
2113:                    } else {
2114:                        int tag = read();
2115:
2116:                        switch (tag) {
2117:                        case 'B':
2118:                        case 'b':
2119:                            _isLastChunk = tag == 'B';
2120:                            _chunkLength = (read() << 8) + read();
2121:                            break;
2122:
2123:                        default:
2124:                            throw expect("binary", tag);
2125:                        }
2126:                    }
2127:                }
2128:
2129:                if (readLength == 0)
2130:                    return -1;
2131:                else if (_chunkLength > 0 || !_isLastChunk)
2132:                    return readLength;
2133:                else {
2134:                    _chunkLength = END_OF_DATA;
2135:                    return readLength;
2136:                }
2137:            }
2138:
2139:            /**
2140:             * Reads a fault.
2141:             */
2142:            private HashMap readFault() throws IOException {
2143:                HashMap map = new HashMap();
2144:
2145:                int code = read();
2146:                for (; code > 0 && code != 'z'; code = read()) {
2147:                    _offset--;
2148:
2149:                    Object key = readObject();
2150:                    Object value = readObject();
2151:
2152:                    if (key != null && value != null)
2153:                        map.put(key, value);
2154:                }
2155:
2156:                if (code != 'z')
2157:                    throw expect("fault", code);
2158:
2159:                return map;
2160:            }
2161:
2162:            /**
2163:             * Reads an object from the input stream with an expected type.
2164:             */
2165:            public Object readObject(Class cl) throws IOException {
2166:                if (cl == null || cl == Object.class)
2167:                    return readObject();
2168:
2169:                int tag = _offset < _length ? (_buffer[_offset++] & 0xff)
2170:                        : read();
2171:
2172:                switch (tag) {
2173:                case 'N':
2174:                    return null;
2175:
2176:                case 'M': {
2177:                    String type = readType();
2178:
2179:                    // hessian/3bb3
2180:                    if ("".equals(type)) {
2181:                        Deserializer reader;
2182:                        reader = findSerializerFactory().getDeserializer(cl);
2183:
2184:                        return reader.readMap(this );
2185:                    } else {
2186:                        Deserializer reader;
2187:                        reader = findSerializerFactory().getObjectDeserializer(
2188:                                type, cl);
2189:
2190:                        return reader.readMap(this );
2191:                    }
2192:                }
2193:
2194:                case 'O': {
2195:                    readObjectDefinition(cl);
2196:
2197:                    return readObject(cl);
2198:                }
2199:
2200:                case 'o': {
2201:                    int ref = readInt();
2202:                    int size = _classDefs.size();
2203:
2204:                    if (ref < 0 || size <= ref)
2205:                        throw new HessianProtocolException("'" + ref
2206:                                + "' is an unknown class definition");
2207:
2208:                    ObjectDefinition def = (ObjectDefinition) _classDefs
2209:                            .get(ref);
2210:
2211:                    return readObjectInstance(cl, def);
2212:                }
2213:
2214:                case 'V': {
2215:                    String type = readType();
2216:                    int length = readLength();
2217:
2218:                    Deserializer reader;
2219:                    reader = findSerializerFactory().getObjectDeserializer(
2220:                            type, cl);
2221:
2222:                    Object v = reader.readList(this , length);
2223:
2224:                    return v;
2225:                }
2226:
2227:                case 'v': {
2228:                    int ref = readInt();
2229:                    String type = (String) _types.get(ref);
2230:                    int length = readInt();
2231:
2232:                    Deserializer reader;
2233:                    reader = findSerializerFactory().getObjectDeserializer(
2234:                            type, cl);
2235:
2236:                    Object v = reader.readLengthList(this , length);
2237:
2238:                    return v;
2239:                }
2240:
2241:                case 'R': {
2242:                    int ref = parseInt();
2243:
2244:                    return _refs.get(ref);
2245:                }
2246:
2247:                case 'r': {
2248:                    String type = readType();
2249:                    String url = readString();
2250:
2251:                    return resolveRemote(type, url);
2252:                }
2253:
2254:                case REF_BYTE: {
2255:                    int ref = read();
2256:
2257:                    return _refs.get(ref);
2258:                }
2259:
2260:                case REF_SHORT: {
2261:                    int ref = 256 * read() + read();
2262:
2263:                    return _refs.get(ref);
2264:                }
2265:                }
2266:
2267:                if (tag >= 0)
2268:                    _offset--;
2269:
2270:                // hessian/3b2i vs hessian/3406
2271:                // return readObject();
2272:
2273:                Object value = findSerializerFactory().getDeserializer(cl)
2274:                        .readObject(this );
2275:                return value;
2276:            }
2277:
2278:            /**
2279:             * Reads an arbitrary object from the input stream when the type
2280:             * is unknown.
2281:             */
2282:            public Object readObject() throws IOException {
2283:                int tag = _offset < _length ? (_buffer[_offset++] & 0xff)
2284:                        : read();
2285:
2286:                switch (tag) {
2287:                case 'N':
2288:                    return null;
2289:
2290:                case 'T':
2291:                    return Boolean.valueOf(true);
2292:
2293:                case 'F':
2294:                    return Boolean.valueOf(false);
2295:
2296:                    // direct integer
2297:                case 0x80:
2298:                case 0x81:
2299:                case 0x82:
2300:                case 0x83:
2301:                case 0x84:
2302:                case 0x85:
2303:                case 0x86:
2304:                case 0x87:
2305:                case 0x88:
2306:                case 0x89:
2307:                case 0x8a:
2308:                case 0x8b:
2309:                case 0x8c:
2310:                case 0x8d:
2311:                case 0x8e:
2312:                case 0x8f:
2313:
2314:                case 0x90:
2315:                case 0x91:
2316:                case 0x92:
2317:                case 0x93:
2318:                case 0x94:
2319:                case 0x95:
2320:                case 0x96:
2321:                case 0x97:
2322:                case 0x98:
2323:                case 0x99:
2324:                case 0x9a:
2325:                case 0x9b:
2326:                case 0x9c:
2327:                case 0x9d:
2328:                case 0x9e:
2329:                case 0x9f:
2330:
2331:                case 0xa0:
2332:                case 0xa1:
2333:                case 0xa2:
2334:                case 0xa3:
2335:                case 0xa4:
2336:                case 0xa5:
2337:                case 0xa6:
2338:                case 0xa7:
2339:                case 0xa8:
2340:                case 0xa9:
2341:                case 0xaa:
2342:                case 0xab:
2343:                case 0xac:
2344:                case 0xad:
2345:                case 0xae:
2346:                case 0xaf:
2347:
2348:                case 0xb0:
2349:                case 0xb1:
2350:                case 0xb2:
2351:                case 0xb3:
2352:                case 0xb4:
2353:                case 0xb5:
2354:                case 0xb6:
2355:                case 0xb7:
2356:                case 0xb8:
2357:                case 0xb9:
2358:                case 0xba:
2359:                case 0xbb:
2360:                case 0xbc:
2361:                case 0xbd:
2362:                case 0xbe:
2363:                case 0xbf:
2364:                    return Integer.valueOf(tag - INT_ZERO);
2365:
2366:                    /* byte int */
2367:                case 0xc0:
2368:                case 0xc1:
2369:                case 0xc2:
2370:                case 0xc3:
2371:                case 0xc4:
2372:                case 0xc5:
2373:                case 0xc6:
2374:                case 0xc7:
2375:                case 0xc8:
2376:                case 0xc9:
2377:                case 0xca:
2378:                case 0xcb:
2379:                case 0xcc:
2380:                case 0xcd:
2381:                case 0xce:
2382:                case 0xcf:
2383:                    return Integer.valueOf(((tag - INT_BYTE_ZERO) << 8)
2384:                            + read());
2385:
2386:                    /* short int */
2387:                case 0xd0:
2388:                case 0xd1:
2389:                case 0xd2:
2390:                case 0xd3:
2391:                case 0xd4:
2392:                case 0xd5:
2393:                case 0xd6:
2394:                case 0xd7:
2395:                    return Integer.valueOf(((tag - INT_SHORT_ZERO) << 16) + 256
2396:                            * read() + read());
2397:
2398:                case 'I':
2399:                    return Integer.valueOf(parseInt());
2400:
2401:                    // direct long
2402:                case 0xd8:
2403:                case 0xd9:
2404:                case 0xda:
2405:                case 0xdb:
2406:                case 0xdc:
2407:                case 0xdd:
2408:                case 0xde:
2409:                case 0xdf:
2410:
2411:                case 0xe0:
2412:                case 0xe1:
2413:                case 0xe2:
2414:                case 0xe3:
2415:                case 0xe4:
2416:                case 0xe5:
2417:                case 0xe6:
2418:                case 0xe7:
2419:                case 0xe8:
2420:                case 0xe9:
2421:                case 0xea:
2422:                case 0xeb:
2423:                case 0xec:
2424:                case 0xed:
2425:                case 0xee:
2426:                case 0xef:
2427:                    return Long.valueOf(tag - LONG_ZERO);
2428:
2429:                    /* byte long */
2430:                case 0xf0:
2431:                case 0xf1:
2432:                case 0xf2:
2433:                case 0xf3:
2434:                case 0xf4:
2435:                case 0xf5:
2436:                case 0xf6:
2437:                case 0xf7:
2438:                case 0xf8:
2439:                case 0xf9:
2440:                case 0xfa:
2441:                case 0xfb:
2442:                case 0xfc:
2443:                case 0xfd:
2444:                case 0xfe:
2445:                case 0xff:
2446:                    return Long.valueOf(((tag - LONG_BYTE_ZERO) << 8) + read());
2447:
2448:                    /* short long */
2449:                case 0x38:
2450:                case 0x39:
2451:                case 0x3a:
2452:                case 0x3b:
2453:                case 0x3c:
2454:                case 0x3d:
2455:                case 0x3e:
2456:                case 0x3f:
2457:                    return Long.valueOf(((tag - LONG_SHORT_ZERO) << 16) + 256
2458:                            * read() + read());
2459:
2460:                case LONG_INT:
2461:                    return Long.valueOf(parseInt());
2462:
2463:                case 'L':
2464:                    return Long.valueOf(parseLong());
2465:
2466:                case DOUBLE_ZERO:
2467:                    return Double.valueOf(0);
2468:
2469:                case DOUBLE_ONE:
2470:                    return Double.valueOf(1);
2471:
2472:                case DOUBLE_BYTE:
2473:                    return Double.valueOf((byte) read());
2474:
2475:                case DOUBLE_SHORT:
2476:                    return Double.valueOf((short) (256 * read() + read()));
2477:
2478:                case DOUBLE_FLOAT: {
2479:                    int f = parseInt();
2480:
2481:                    return Double.valueOf(Float.intBitsToFloat(f));
2482:                }
2483:
2484:                case 'D':
2485:                    return Double.valueOf(parseDouble());
2486:
2487:                case 'd':
2488:                    return new Date(parseLong());
2489:
2490:                case 'x':
2491:                case 'X': {
2492:                    _isLastChunk = tag == 'X';
2493:                    _chunkLength = (read() << 8) + read();
2494:
2495:                    return parseXML();
2496:                }
2497:
2498:                case 's':
2499:                case 'S': {
2500:                    _isLastChunk = tag == 'S';
2501:                    _chunkLength = (read() << 8) + read();
2502:
2503:                    int data;
2504:                    _sbuf.setLength(0);
2505:
2506:                    while ((data = parseChar()) >= 0)
2507:                        _sbuf.append((char) data);
2508:
2509:                    return _sbuf.toString();
2510:                }
2511:
2512:                case 0x00:
2513:                case 0x01:
2514:                case 0x02:
2515:                case 0x03:
2516:                case 0x04:
2517:                case 0x05:
2518:                case 0x06:
2519:                case 0x07:
2520:                case 0x08:
2521:                case 0x09:
2522:                case 0x0a:
2523:                case 0x0b:
2524:                case 0x0c:
2525:                case 0x0d:
2526:                case 0x0e:
2527:                case 0x0f:
2528:
2529:                case 0x10:
2530:                case 0x11:
2531:                case 0x12:
2532:                case 0x13:
2533:                case 0x14:
2534:                case 0x15:
2535:                case 0x16:
2536:                case 0x17:
2537:                case 0x18:
2538:                case 0x19:
2539:                case 0x1a:
2540:                case 0x1b:
2541:                case 0x1c:
2542:                case 0x1d:
2543:                case 0x1e:
2544:                case 0x1f: {
2545:                    _isLastChunk = true;
2546:                    _chunkLength = tag - 0x00;
2547:
2548:                    int data;
2549:                    _sbuf.setLength(0);
2550:
2551:                    while ((data = parseChar()) >= 0)
2552:                        _sbuf.append((char) data);
2553:
2554:                    return _sbuf.toString();
2555:                }
2556:
2557:                case 'b':
2558:                case 'B': {
2559:                    _isLastChunk = tag == 'B';
2560:                    _chunkLength = (read() << 8) + read();
2561:
2562:                    int data;
2563:                    ByteArrayOutputStream bos = new ByteArrayOutputStream();
2564:
2565:                    while ((data = parseByte()) >= 0)
2566:                        bos.write(data);
2567:
2568:                    return bos.toByteArray();
2569:                }
2570:
2571:                case 0x20:
2572:                case 0x21:
2573:                case 0x22:
2574:                case 0x23:
2575:                case 0x24:
2576:                case 0x25:
2577:                case 0x26:
2578:                case 0x27:
2579:                case 0x28:
2580:                case 0x29:
2581:                case 0x2a:
2582:                case 0x2b:
2583:                case 0x2c:
2584:                case 0x2d:
2585:                case 0x2e:
2586:                case 0x2f: {
2587:                    _isLastChunk = true;
2588:                    int len = tag - 0x20;
2589:                    _chunkLength = 0;
2590:
2591:                    byte[] data = new byte[len];
2592:
2593:                    for (int i = 0; i < len; i++)
2594:                        data[i] = (byte) read();
2595:
2596:                    return data;
2597:                }
2598:
2599:                case 'V': {
2600:                    String type = readType();
2601:                    int length = readLength();
2602:
2603:                    return findSerializerFactory().readList(this , length, type);
2604:                }
2605:
2606:                    // direct lists
2607:                case 'v': {
2608:                    int ref = readInt();
2609:                    String type = (String) _types.get(ref);
2610:                    int length = readInt();
2611:
2612:                    Deserializer reader;
2613:                    reader = findSerializerFactory().getObjectDeserializer(
2614:                            type, null);
2615:
2616:                    return reader.readLengthList(this , length);
2617:                }
2618:
2619:                case 'M': {
2620:                    String type = readType();
2621:
2622:                    return findSerializerFactory().readMap(this , type);
2623:                }
2624:
2625:                case 'O': {
2626:                    readObjectDefinition(null);
2627:
2628:                    return readObject();
2629:                }
2630:
2631:                case 'o': {
2632:                    int ref = readInt();
2633:
2634:                    ObjectDefinition def = (ObjectDefinition) _classDefs
2635:                            .get(ref);
2636:
2637:                    return readObjectInstance(null, def);
2638:                }
2639:
2640:                case 'R': {
2641:                    int ref = parseInt();
2642:
2643:                    return _refs.get(ref);
2644:                }
2645:
2646:                case REF_BYTE: {
2647:                    int ref = read();
2648:
2649:                    return _refs.get(ref);
2650:                }
2651:
2652:                case REF_SHORT: {
2653:                    int ref = 256 * read() + read();
2654:
2655:                    return _refs.get(ref);
2656:                }
2657:
2658:                case 'r': {
2659:                    String type = readType();
2660:                    String url = readString();
2661:
2662:                    return resolveRemote(type, url);
2663:                }
2664:
2665:                default:
2666:                    if (tag < 0)
2667:                        throw error("readObject: unexpected end of file");
2668:                    else
2669:                        throw error("readObject: unknown code " + codeName(tag));
2670:                }
2671:            }
2672:
2673:            /**
2674:             * Reads an object definition:
2675:             *
2676:             * <pre>
2677:             * O string <int> (string)* <value>*
2678:             * </pre>
2679:             */
2680:            private void readObjectDefinition(Class cl) throws IOException {
2681:                String type = readString();
2682:                int len = readInt();
2683:
2684:                String[] fieldNames = new String[len];
2685:                for (int i = 0; i < len; i++)
2686:                    fieldNames[i] = readString();
2687:
2688:                ObjectDefinition def = new ObjectDefinition(type, fieldNames);
2689:
2690:                if (_classDefs == null)
2691:                    _classDefs = new ArrayList();
2692:
2693:                _classDefs.add(def);
2694:            }
2695:
2696:            private Object readObjectInstance(Class cl, ObjectDefinition def)
2697:                    throws IOException {
2698:                String type = def.getType();
2699:                String[] fieldNames = def.getFieldNames();
2700:
2701:                if (cl != null) {
2702:                    Deserializer reader;
2703:                    reader = findSerializerFactory().getObjectDeserializer(
2704:                            type, cl);
2705:
2706:                    return reader.readObject(this , fieldNames);
2707:                } else {
2708:                    return findSerializerFactory().readObject(this , type,
2709:                            fieldNames);
2710:                }
2711:            }
2712:
2713:            private String readLenString() throws IOException {
2714:                int len = readInt();
2715:
2716:                _isLastChunk = true;
2717:                _chunkLength = len;
2718:
2719:                _sbuf.setLength(0);
2720:                int ch;
2721:                while ((ch = parseChar()) >= 0)
2722:                    _sbuf.append((char) ch);
2723:
2724:                return _sbuf.toString();
2725:            }
2726:
2727:            private String readLenString(int len) throws IOException {
2728:                _isLastChunk = true;
2729:                _chunkLength = len;
2730:
2731:                _sbuf.setLength(0);
2732:                int ch;
2733:                while ((ch = parseChar()) >= 0)
2734:                    _sbuf.append((char) ch);
2735:
2736:                return _sbuf.toString();
2737:            }
2738:
2739:            /**
2740:             * Reads a remote object.
2741:             */
2742:            public Object readRemote() throws IOException {
2743:                String type = readType();
2744:                String url = readString();
2745:
2746:                return resolveRemote(type, url);
2747:            }
2748:
2749:            /**
2750:             * Reads a reference.
2751:             */
2752:            public Object readRef() throws IOException {
2753:                return _refs.get(parseInt());
2754:            }
2755:
2756:            /**
2757:             * Reads the start of a list.
2758:             */
2759:            public int readListStart() throws IOException {
2760:                return read();
2761:            }
2762:
2763:            /**
2764:             * Reads the start of a list.
2765:             */
2766:            public int readMapStart() throws IOException {
2767:                return read();
2768:            }
2769:
2770:            /**
2771:             * Returns true if this is the end of a list or a map.
2772:             */
2773:            public boolean isEnd() throws IOException {
2774:                int code;
2775:
2776:                if (_offset < _length)
2777:                    code = (_buffer[_offset] & 0xff);
2778:                else {
2779:                    code = read();
2780:
2781:                    if (code >= 0)
2782:                        _offset--;
2783:                }
2784:
2785:                return (code < 0 || code == 'z');
2786:            }
2787:
2788:            /**
2789:             * Reads the end byte.
2790:             */
2791:            public void readEnd() throws IOException {
2792:                int code = _offset < _length ? (_buffer[_offset++] & 0xff)
2793:                        : read();
2794:
2795:                if (code == 'z')
2796:                    return;
2797:                else if (code < 0)
2798:                    throw error("unexpected end of file");
2799:                else
2800:                    throw error("unknown code:" + codeName(code));
2801:            }
2802:
2803:            /**
2804:             * Reads the end byte.
2805:             */
2806:            public void readMapEnd() throws IOException {
2807:                int code = _offset < _length ? (_buffer[_offset++] & 0xff)
2808:                        : read();
2809:
2810:                if (code != 'z')
2811:                    throw error("expected end of map ('z') at '"
2812:                            + codeName(code) + "'");
2813:            }
2814:
2815:            /**
2816:             * Reads the end byte.
2817:             */
2818:            public void readListEnd() throws IOException {
2819:                int code = _offset < _length ? (_buffer[_offset++] & 0xff)
2820:                        : read();
2821:
2822:                if (code != 'z')
2823:                    throw error("expected end of list ('z') at '"
2824:                            + codeName(code) + "'");
2825:            }
2826:
2827:            /**
2828:             * Adds a list/map reference.
2829:             */
2830:            public int addRef(Object ref) {
2831:                if (_refs == null)
2832:                    _refs = new ArrayList();
2833:
2834:                _refs.add(ref);
2835:
2836:                return _refs.size() - 1;
2837:            }
2838:
2839:            /**
2840:             * Adds a list/map reference.
2841:             */
2842:            public void setRef(int i, Object ref) {
2843:                _refs.set(i, ref);
2844:            }
2845:
2846:            /**
2847:             * Resets the references for streaming.
2848:             */
2849:            public void resetReferences() {
2850:                if (_refs != null)
2851:                    _refs.clear();
2852:            }
2853:
2854:            public Object readStreamingObject() throws IOException {
2855:                if (_refs != null)
2856:                    _refs.clear();
2857:
2858:                return readObject();
2859:            }
2860:
2861:            /**
2862:             * Resolves a remote object.
2863:             */
2864:            public Object resolveRemote(String type, String url)
2865:                    throws IOException {
2866:                HessianRemoteResolver resolver = getRemoteResolver();
2867:
2868:                if (resolver != null)
2869:                    return resolver.lookup(type, url);
2870:                else
2871:                    return new HessianRemote(type, url);
2872:            }
2873:
2874:            /**
2875:             * Parses a type from the stream.
2876:             *
2877:             * <pre>
2878:             * t b16 b8
2879:             * </pre>
2880:             */
2881:            public String readType() throws IOException {
2882:                int code = _offset < _length ? (_buffer[_offset++] & 0xff)
2883:                        : read();
2884:
2885:                switch (code) {
2886:                case 't': {
2887:                    int len = 256 * read() + read();
2888:                    String type = readLenString(len);
2889:
2890:                    if (_types == null)
2891:                        _types = new ArrayList();
2892:
2893:                    _types.add(type);
2894:
2895:                    return type;
2896:                }
2897:
2898:                case 'T': {
2899:                    int ref = readInt();
2900:
2901:                    return (String) _types.get(ref);
2902:                }
2903:
2904:                case TYPE_REF: {
2905:                    int ref = readInt();
2906:
2907:                    return (String) _types.get(ref);
2908:                }
2909:
2910:                default: {
2911:                    if (code >= 0)
2912:                        _offset--;
2913:
2914:                    return "";
2915:                }
2916:                }
2917:            }
2918:
2919:            /**
2920:             * Parses the length for an array
2921:             *
2922:             * <pre>
2923:             * l b32 b24 b16 b8
2924:             * </pre>
2925:             */
2926:            public int readLength() throws IOException {
2927:                int code = read();
2928:
2929:                if (code == LENGTH_BYTE)
2930:                    return read();
2931:
2932:                else if (code == 'l')
2933:                    return parseInt();
2934:
2935:                else {
2936:                    if (code >= 0)
2937:                        _offset--;
2938:
2939:                    return -1;
2940:                }
2941:            }
2942:
2943:            /**
2944:             * Parses a 32-bit integer value from the stream.
2945:             *
2946:             * <pre>
2947:             * b32 b24 b16 b8
2948:             * </pre>
2949:             */
2950:            private int parseInt() throws IOException {
2951:                int offset = _offset;
2952:
2953:                if (offset + 3 < _length) {
2954:                    byte[] buffer = _buffer;
2955:
2956:                    int b32 = buffer[offset + 0] & 0xff;
2957:                    int b24 = buffer[offset + 1] & 0xff;
2958:                    int b16 = buffer[offset + 2] & 0xff;
2959:                    int b8 = buffer[offset + 3] & 0xff;
2960:
2961:                    _offset = offset + 4;
2962:
2963:                    return (b32 << 24) + (b24 << 16) + (b16 << 8) + b8;
2964:                } else {
2965:                    int b32 = read();
2966:                    int b24 = read();
2967:                    int b16 = read();
2968:                    int b8 = read();
2969:
2970:                    return (b32 << 24) + (b24 << 16) + (b16 << 8) + b8;
2971:                }
2972:            }
2973:
2974:            /**
2975:             * Parses a 64-bit long value from the stream.
2976:             *
2977:             * <pre>
2978:             * b64 b56 b48 b40 b32 b24 b16 b8
2979:             * </pre>
2980:             */
2981:            private long parseLong() throws IOException {
2982:                long b64 = read();
2983:                long b56 = read();
2984:                long b48 = read();
2985:                long b40 = read();
2986:                long b32 = read();
2987:                long b24 = read();
2988:                long b16 = read();
2989:                long b8 = read();
2990:
2991:                return ((b64 << 56) + (b56 << 48) + (b48 << 40) + (b40 << 32)
2992:                        + (b32 << 24) + (b24 << 16) + (b16 << 8) + b8);
2993:            }
2994:
2995:            /**
2996:             * Parses a 64-bit double value from the stream.
2997:             *
2998:             * <pre>
2999:             * b64 b56 b48 b40 b32 b24 b16 b8
3000:             * </pre>
3001:             */
3002:            private double parseDouble() throws IOException {
3003:                long bits = parseLong();
3004:
3005:                return Double.longBitsToDouble(bits);
3006:            }
3007:
3008:            org.w3c.dom.Node parseXML() throws IOException {
3009:                throw new UnsupportedOperationException();
3010:            }
3011:
3012:            /**
3013:             * Reads a character from the underlying stream.
3014:             */
3015:            private int parseChar() throws IOException {
3016:                while (_chunkLength <= 0) {
3017:                    if (_isLastChunk)
3018:                        return -1;
3019:
3020:                    int code = _offset < _length ? (_buffer[_offset++] & 0xff)
3021:                            : read();
3022:
3023:                    switch (code) {
3024:                    case 's':
3025:                    case 'x':
3026:                        _isLastChunk = false;
3027:
3028:                        _chunkLength = (read() << 8) + read();
3029:                        break;
3030:
3031:                    case 'S':
3032:                    case 'X':
3033:                        _isLastChunk = true;
3034:
3035:                        _chunkLength = (read() << 8) + read();
3036:                        break;
3037:
3038:                    case 0x00:
3039:                    case 0x01:
3040:                    case 0x02:
3041:                    case 0x03:
3042:                    case 0x04:
3043:                    case 0x05:
3044:                    case 0x06:
3045:                    case 0x07:
3046:                    case 0x08:
3047:                    case 0x09:
3048:                    case 0x0a:
3049:                    case 0x0b:
3050:                    case 0x0c:
3051:                    case 0x0d:
3052:                    case 0x0e:
3053:                    case 0x0f:
3054:
3055:                    case 0x10:
3056:                    case 0x11:
3057:                    case 0x12:
3058:                    case 0x13:
3059:                    case 0x14:
3060:                    case 0x15:
3061:                    case 0x16:
3062:                    case 0x17:
3063:                    case 0x18:
3064:                    case 0x19:
3065:                    case 0x1a:
3066:                    case 0x1b:
3067:                    case 0x1c:
3068:                    case 0x1d:
3069:                    case 0x1e:
3070:                    case 0x1f:
3071:                        _isLastChunk = true;
3072:                        _chunkLength = code - 0x00;
3073:                        break;
3074:
3075:                    default:
3076:                        throw expect("string", code);
3077:                    }
3078:
3079:                }
3080:
3081:                _chunkLength--;
3082:
3083:                return parseUTF8Char();
3084:            }
3085:
3086:            /**
3087:             * Parses a single UTF8 character.
3088:             */
3089:            private int parseUTF8Char() throws IOException {
3090:                int ch = _offset < _length ? (_buffer[_offset++] & 0xff)
3091:                        : read();
3092:
3093:                if (ch < 0x80)
3094:                    return ch;
3095:                else if ((ch & 0xe0) == 0xc0) {
3096:                    int ch1 = read();
3097:                    int v = ((ch & 0x1f) << 6) + (ch1 & 0x3f);
3098:
3099:                    return v;
3100:                } else if ((ch & 0xf0) == 0xe0) {
3101:                    int ch1 = read();
3102:                    int ch2 = read();
3103:                    int v = ((ch & 0x0f) << 12) + ((ch1 & 0x3f) << 6)
3104:                            + (ch2 & 0x3f);
3105:
3106:                    return v;
3107:                } else
3108:                    throw error("bad utf-8 encoding at " + codeName(ch));
3109:            }
3110:
3111:            /**
3112:             * Reads a byte from the underlying stream.
3113:             */
3114:            private int parseByte() throws IOException {
3115:                while (_chunkLength <= 0) {
3116:                    if (_isLastChunk) {
3117:                        return -1;
3118:                    }
3119:
3120:                    int code = read();
3121:
3122:                    switch (code) {
3123:                    case 'b':
3124:                        _isLastChunk = false;
3125:
3126:                        _chunkLength = (read() << 8) + read();
3127:                        break;
3128:
3129:                    case 'B':
3130:                        _isLastChunk = true;
3131:
3132:                        _chunkLength = (read() << 8) + read();
3133:                        break;
3134:
3135:                    case 0x20:
3136:                    case 0x21:
3137:                    case 0x22:
3138:                    case 0x23:
3139:                    case 0x24:
3140:                    case 0x25:
3141:                    case 0x26:
3142:                    case 0x27:
3143:                    case 0x28:
3144:                    case 0x29:
3145:                    case 0x2a:
3146:                    case 0x2b:
3147:                    case 0x2c:
3148:                    case 0x2d:
3149:                    case 0x2e:
3150:                    case 0x2f:
3151:                        _isLastChunk = true;
3152:
3153:                        _chunkLength = code - 0x20;
3154:                        break;
3155:
3156:                    default:
3157:                        throw expect("byte[]", code);
3158:                    }
3159:                }
3160:
3161:                _chunkLength--;
3162:
3163:                return read();
3164:            }
3165:
3166:            /**
3167:             * Reads bytes based on an input stream.
3168:             */
3169:            public InputStream readInputStream() throws IOException {
3170:                int tag = read();
3171:
3172:                switch (tag) {
3173:                case 'N':
3174:                    return null;
3175:
3176:                case 'B':
3177:                case 'b':
3178:                    _isLastChunk = tag == 'B';
3179:                    _chunkLength = (read() << 8) + read();
3180:                    break;
3181:
3182:                case 0x20:
3183:                case 0x21:
3184:                case 0x22:
3185:                case 0x23:
3186:                case 0x24:
3187:                case 0x25:
3188:                case 0x26:
3189:                case 0x27:
3190:                case 0x28:
3191:                case 0x29:
3192:                case 0x2a:
3193:                case 0x2b:
3194:                case 0x2c:
3195:                case 0x2d:
3196:                case 0x2e:
3197:                case 0x2f:
3198:                    _isLastChunk = true;
3199:                    _chunkLength = tag - 0x20;
3200:                    break;
3201:
3202:                default:
3203:                    throw expect("binary", tag);
3204:                }
3205:
3206:                return new ReadInputStream();
3207:
3208:            }
3209:
3210:            /**
3211:             * Reads bytes from the underlying stream.
3212:             */
3213:            int read(byte[] buffer, int offset, int length) throws IOException {
3214:                int readLength = 0;
3215:
3216:                while (length > 0) {
3217:                    while (_chunkLength <= 0) {
3218:                        if (_isLastChunk)
3219:                            return readLength == 0 ? -1 : readLength;
3220:
3221:                        int code = read();
3222:
3223:                        switch (code) {
3224:                        case 'b':
3225:                            _isLastChunk = false;
3226:
3227:                            _chunkLength = (read() << 8) + read();
3228:                            break;
3229:
3230:                        case 'B':
3231:                            _isLastChunk = true;
3232:
3233:                            _chunkLength = (read() << 8) + read();
3234:                            break;
3235:
3236:                        default:
3237:                            throw expect("byte[]", code);
3238:                        }
3239:                    }
3240:
3241:                    int sublen = _chunkLength;
3242:                    if (length < sublen)
3243:                        sublen = length;
3244:
3245:                    if (_length <= _offset && !readBuffer())
3246:                        return -1;
3247:
3248:                    if (_length - _offset < sublen)
3249:                        sublen = _length - _offset;
3250:
3251:                    System.arraycopy(_buffer, _offset, buffer, offset, sublen);
3252:
3253:                    _offset += sublen;
3254:
3255:                    offset += sublen;
3256:                    readLength += sublen;
3257:                    length -= sublen;
3258:                    _chunkLength -= sublen;
3259:                }
3260:
3261:                return readLength;
3262:            }
3263:
3264:            /**
3265:             * Normally, shouldn't be called externally, but needed for QA, e.g.
3266:             * ejb/3b01.
3267:             */
3268:            public final int read() throws IOException {
3269:                if (_length <= _offset && !readBuffer())
3270:                    return -1;
3271:
3272:                return _buffer[_offset++] & 0xff;
3273:            }
3274:
3275:            private final boolean readBuffer() throws IOException {
3276:                byte[] buffer = _buffer;
3277:                int offset = _offset;
3278:                int length = _length;
3279:
3280:                if (offset < length) {
3281:                    System
3282:                            .arraycopy(buffer, offset, buffer, 0, length
3283:                                    - offset);
3284:                    offset = length - offset;
3285:                } else
3286:                    offset = 0;
3287:
3288:                int len = _is.read(buffer, offset, SIZE - offset);
3289:
3290:                if (len <= 0) {
3291:                    _length = offset;
3292:                    _offset = 0;
3293:
3294:                    return offset > 0;
3295:                }
3296:
3297:                _length = offset + len;
3298:                _offset = 0;
3299:
3300:                return true;
3301:            }
3302:
3303:            public Reader getReader() {
3304:                return null;
3305:            }
3306:
3307:            protected IOException expect(String expect, int ch)
3308:                    throws IOException {
3309:                if (ch < 0)
3310:                    return error("expected " + expect + " at end of file");
3311:                else {
3312:                    _offset--;
3313:
3314:                    try {
3315:                        Object obj = readObject();
3316:
3317:                        if (obj != null) {
3318:                            return error("expected " + expect + " at 0x"
3319:                                    + Integer.toHexString(ch & 0xff) + " "
3320:                                    + obj.getClass().getName() + " (" + obj
3321:                                    + ")");
3322:                        } else
3323:                            return error("expected " + expect + " at 0x"
3324:                                    + Integer.toHexString(ch & 0xff) + " null");
3325:                    } catch (IOException e) {
3326:                        log.log(Level.FINE, e.toString(), e);
3327:
3328:                        return error("expected " + expect + " at 0x"
3329:                                + Integer.toHexString(ch & 0xff));
3330:                    }
3331:                }
3332:            }
3333:
3334:            protected String codeName(int ch) {
3335:                if (ch < 0)
3336:                    return "end of file";
3337:                else
3338:                    return "0x" + Integer.toHexString(ch & 0xff) + " ("
3339:                            + (char) +ch + ")";
3340:            }
3341:
3342:            protected IOException error(String message) {
3343:                if (_method != null)
3344:                    return new HessianProtocolException(_method + ": "
3345:                            + message);
3346:                else
3347:                    return new HessianProtocolException(message);
3348:            }
3349:
3350:            public void close() throws IOException {
3351:                InputStream is = _is;
3352:                _is = null;
3353:
3354:                if (_isCloseStreamOnClose && is != null)
3355:                    is.close();
3356:            }
3357:
3358:            class ReadInputStream extends InputStream {
3359:                boolean _isClosed = false;
3360:
3361:                public int read() throws IOException {
3362:                    if (_isClosed)
3363:                        return -1;
3364:
3365:                    int ch = parseByte();
3366:                    if (ch < 0)
3367:                        _isClosed = true;
3368:
3369:                    return ch;
3370:                }
3371:
3372:                public int read(byte[] buffer, int offset, int length)
3373:                        throws IOException {
3374:                    if (_isClosed)
3375:                        return -1;
3376:
3377:                    int len = Hessian2Input.this .read(buffer, offset, length);
3378:                    if (len < 0)
3379:                        _isClosed = true;
3380:
3381:                    return len;
3382:                }
3383:
3384:                public void close() throws IOException {
3385:                    while (read() >= 0) {
3386:                    }
3387:                }
3388:            };
3389:
3390:            final static class ObjectDefinition {
3391:                private final String _type;
3392:                private final String[] _fields;
3393:
3394:                ObjectDefinition(String type, String[] fields) {
3395:                    _type = type;
3396:                    _fields = fields;
3397:                }
3398:
3399:                String getType() {
3400:                    return _type;
3401:                }
3402:
3403:                String[] getFieldNames() {
3404:                    return _fields;
3405:                }
3406:            }
3407:
3408:            static {
3409:                try {
3410:                    _detailMessageField = Throwable.class
3411:                            .getDeclaredField("detailMessage");
3412:                    _detailMessageField.setAccessible(true);
3413:                } catch (Throwable e) {
3414:                }
3415:            }
3416:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.