Adding JMCR-Stable version
[Benchmarks_CSolver.git] / JMCR-Stable / real-world application / MyDerby-10.3 / java / drda / org / apache / derby / impl / drda / DDMReader.java
diff --git a/JMCR-Stable/real-world application/MyDerby-10.3/java/drda/org/apache/derby/impl/drda/DDMReader.java b/JMCR-Stable/real-world application/MyDerby-10.3/java/drda/org/apache/derby/impl/drda/DDMReader.java
new file mode 100644 (file)
index 0000000..37b279d
--- /dev/null
@@ -0,0 +1,1986 @@
+/*\r
+\r
+   Derby - Class org.apache.derby.impl.drda.DDMReader\r
+\r
+   Licensed to the Apache Software Foundation (ASF) under one or more\r
+   contributor license agreements.  See the NOTICE file distributed with\r
+   this work for additional information regarding copyright ownership.\r
+   The ASF licenses this file to You under the Apache License, Version 2.0\r
+   (the "License"); you may not use this file except in compliance with\r
+   the License.  You may obtain a copy of the License at\r
+\r
+      http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+\r
+ */\r
+\r
+package org.apache.derby.impl.drda;\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+import java.io.ByteArrayOutputStream;\r
+import java.io.ByteArrayInputStream;\r
+import java.math.BigDecimal;\r
+\r
+/**\r
+       The DDMReader is used to read DRDA protocol.   DRDA Protocol is divided into\r
+       three layers corresponding to the DDM three-tier architecture. For each layer,\r
+       their is a DSS (Data Stream Structure) defined.\r
+               Layer A         Communications management services\r
+               Layer B         Agent services\r
+               Layer C         Data management services\r
+       <P>\r
+       At layer A are request, reply and data correlation, structure chaining,\r
+       continuation or termination of chains when errors are detected, interleaving\r
+       and multi-leaving request, reply, and data DSSs for multitasking environments.\r
+       For TCP/IP, the format of the DDM envelope is\r
+               2 bytes         Length of the data\r
+               1 byte          'D0' - indicates DDM data\r
+               1 byte          DDM format byte(DSSFMT) - type of DSS(RQSDSS,RPYDSS), whether it is\r
+                                       chained, information about the next chained DSS\r
+               2 bytes         request correlation identifier\r
+       <P>\r
+       The correlation identifier ties together a request, the request data and the\r
+       reply.  In a chained DSS, each request has a correlation identifier which\r
+       is higher than the previous request (all correlation identifiers must\r
+       be greater than 0).\r
+       <P>\r
+       At layer B are object mapping, object validation and command routing.\r
+       Layer B objects with data 5 bytes less than 32K bytes consist of\r
+               2 bytes         Length\r
+               2 bytes         Type of the object (code point)\r
+               Object data\r
+       Object data is either SCALAR or COLLECTION data.  Scalar data consists of\r
+       a string of bytes formatted as the class description of the object required.\r
+       Collections consist of a set of objects in which the entries in the collection\r
+       are nested within the length/ code point of the collection.\r
+       <P>\r
+       Layer B objects with data >=32763 bytes long format is \r
+               2 bytes         Length - length of class, length, and extended total length fields\r
+                                       (high order bit set, indicating >=32763)\r
+               2 bytes         Type of the object (code point)\r
+               n bytes         Extended total length - length of the object\r
+                                       (n = Length - 4)\r
+               Object data\r
+       <P>\r
+       At layer C are services each class of DDM object provides.\r
+\r
+                   |-------------------------------------------|\r
+       Layer C | Specific      |       Specific        |       Specific        |\r
+                   | Commands  |       Replies         | Scalars and   |\r
+                       | and their |  and their    | Collections   |\r
+                       |-------------------------------------------|----------------|\r
+       Layer B | Commands  |    Reply          | Scalars and   | Communications |\r
+                       |                       |   Messages    | Collections   |                |\r
+                       |-----------|---------------|---------------|----------------|\r
+       Layer A |  RQSDSS   |   RPYDSS          | OBJDSS                | CMNDSS         |\r
+                       |           |               |               | Mapped Data    |\r
+                       |-----------|---------------|---------------|----------------|\r
+                       |                DDM Data Stream Structures                  |\r
+                       |------------------------------------------------------------|\r
+                       \r
+       DSS's may be chained so that more than one can be transmitted at a time\r
+       to improve performance.\r
+       For more details, see DRDA Volume 3 (Distributed Data Management(DDM)\r
+               Architecture (DDS definition)\r
+*/\r
+class DDMReader\r
+{\r
+       private final static int DEFAULT_BUFFER_SIZE = 32767;\r
+       private final static int MAX_MARKS_NESTING = 10;\r
+       private final static int NO_CODEPOINT = -1;\r
+       private final static int EMPTY_STACK = -1;\r
+       private final static boolean ADJUST_LENGTHS = true;\r
+       private final static boolean NO_ADJUST_LENGTHS = false;\r
+       private final static long MAX_EXTDTA_SIZE= Long.MAX_VALUE;\r
+       private static boolean internalTrace = true;\r
+    \r
+\r
+       // magnitude represented in an int array, used in BigDecimal conversion\r
+    private static final int[][] tenRadixMagnitude = {\r
+      { 0x3b9aca00 }, // 10^9\r
+      { 0x0de0b6b3, 0xa7640000 }, // 10^18\r
+      { 0x033b2e3c, 0x9fd0803c, 0xe8000000 }, // 10^27\r
+    };\r
+\r
+       private DRDAConnThread agent;\r
+       private CcsidManager ccsidManager;\r
+\r
+       // data buffer\r
+       private byte[] buffer;\r
+       private int pos;\r
+       private int count;\r
+\r
+       // DDM object collection\r
+       // top of stack\r
+       private int topDdmCollectionStack;\r
+       // length of each object in the stack\r
+       private long[] ddmCollectionLenStack;\r
+\r
+       // DDM object length\r
+       private long ddmScalarLen;\r
+\r
+       // DSS Length\r
+       private int dssLength;\r
+\r
+       // DSS is larger than 32762 (continuation bit is set) so DSS is continued\r
+       private boolean dssIsContinued;\r
+\r
+       private boolean terminateChainOnErr;\r
+\r
+       // next DSS in the chain has the same correlator\r
+       private boolean dssIsChainedWithSameID;\r
+\r
+       // next DSS in the chain has a different correlator\r
+       private boolean dssIsChainedWithDiffID;\r
+       \r
+       // correlation id for the current DSS\r
+       private int dssCorrelationID;\r
+\r
+       // previous corelation id\r
+       private int prevCorrelationID;\r
+\r
+       // current server codepoint\r
+       private int svrcod;\r
+\r
+       // trace object of the associated session\r
+       private DssTrace dssTrace;\r
+\r
+       // input stream\r
+       private InputStream inputStream;\r
+    \r
+    // State whether doing layer B Streaming or not.\r
+    private boolean doingLayerBStreaming = false;;\r
+\r
+       // constructor\r
+       DDMReader (DRDAConnThread agent, DssTrace dssTrace)\r
+       {\r
+               buffer = new byte[DEFAULT_BUFFER_SIZE];\r
+               ddmCollectionLenStack = new long[MAX_MARKS_NESTING];\r
+               initialize(agent, dssTrace);\r
+       }\r
+       /**\r
+        * This constructor is used for testing the protocol\r
+        * It is used by TestProto to read the protocol returned by the\r
+        * server \r
+        */\r
+       DDMReader(CcsidManager ccsidManager, InputStream inputStream)\r
+       {\r
+               buffer = new byte[DEFAULT_BUFFER_SIZE];\r
+               ddmCollectionLenStack = new long[MAX_MARKS_NESTING];\r
+               this.ccsidManager = ccsidManager;\r
+               this.inputStream = inputStream;\r
+               initialize(null, null);\r
+               // turn off tracing\r
+               internalTrace = false;\r
+       }\r
+       /**\r
+        * This initializer is used for testing the protocol\r
+        * It is used by TestProto for the reader it uses\r
+        */\r
+       protected void initialize(InputStream inputStream)\r
+       {\r
+               this.inputStream = inputStream;\r
+               initialize(null, null);\r
+       }\r
+\r
+       /**\r
+        * Initialize values for this session, the reader is reused so we need to\r
+        * set null and 0 values\r
+        */\r
+       protected void initialize(DRDAConnThread agent, DssTrace dssTrace)\r
+       {\r
+               this.agent = agent;\r
+               if (agent != null)\r
+               {\r
+                       ccsidManager = agent.ccsidManager;\r
+                       inputStream = agent.getInputStream();\r
+               }\r
+               topDdmCollectionStack = EMPTY_STACK;\r
+       svrcod = 0;\r
+               pos = 0;\r
+               count = 0;\r
+               ddmScalarLen = 0;\r
+               dssLength = 0;\r
+               prevCorrelationID = DssConstants.CORRELATION_ID_UNKNOWN;\r
+               dssCorrelationID = DssConstants.CORRELATION_ID_UNKNOWN;\r
+               this.dssTrace = dssTrace;\r
+       }\r
+\r
+       protected boolean terminateChainOnErr()\r
+       {\r
+               return terminateChainOnErr;\r
+       }\r
+\r
+       /**\r
+        * Next DSS has same correlator as current DSS\r
+        *\r
+        * @return true if next DSS has the same correlator as current DSS\r
+        */\r
+       protected boolean isChainedWithSameID()\r
+       {\r
+       return dssIsChainedWithSameID;\r
+       }\r
+\r
+       /**\r
+        * Next DSS has different correlator than current DSS\r
+        *\r
+        * @return true if next DSS has a different correlator than current DSS\r
+        */\r
+       protected boolean isChainedWithDiffID()\r
+       {\r
+       return dssIsChainedWithDiffID;\r
+       }\r
+\r
+       /**\r
+        * Length of current DDM object\r
+        *\r
+        * @return length of DDM object\r
+        */\r
+       protected long getDdmLength()\r
+       {\r
+               return ddmScalarLen;\r
+       }\r
+\r
+       /**\r
+        * Is there more in this DDM object\r
+        *\r
+        * @return true if DDM length is > 0\r
+        */\r
+       protected boolean moreDdmData()\r
+       {\r
+               return ddmScalarLen > 0;\r
+       }\r
+\r
+       /**\r
+        * Is there more in this DDS object\r
+        *\r
+        * @return true if DDS length is > 0\r
+        */\r
+       protected boolean moreDssData()\r
+       {\r
+               return dssLength > 0;\r
+       }\r
+\r
+       /** \r
+        * Is there more data in the buffer\r
+        *\r
+        * @return true if there is more data in the buffer\r
+        */\r
+       protected boolean moreData()\r
+       {\r
+               return (pos - count) > 0;\r
+       }\r
+\r
+       /**\r
+        * Check for the command protocol\r
+        *\r
+        * @return true if this is a command; false otherwise\r
+        *\r
+        * @exception DRDProtocolException\r
+        */\r
+       protected boolean isCmd() throws DRDAProtocolException, java.io.UnsupportedEncodingException\r
+       {\r
+               ensureALayerDataInBuffer(4);\r
+               String val = new String(buffer, 0, 4, NetworkServerControlImpl.DEFAULT_ENCODING);\r
+               return NetworkServerControlImpl.isCmd(val);\r
+       }\r
+\r
+       /**\r
+        * Read DSS header\r
+        * DSS Header format is \r
+        *      2 bytes - length\r
+        *      1 byte  - 'D0'  - indicates DDM data\r
+        *      1 byte  - DSS format \r
+        *              |---|---------|----------|\r
+        *              | 0     |  flags  |  type    |\r
+        *              |---|---------|----------|\r
+        *              | 0 | 1  2  3 | 4 5 6 7  |\r
+        *              |---|---------|----------|\r
+        *              bit 0 - '0'\r
+        *              bit 1 - '0' - unchained, '1' - chained\r
+        *              bit 2 - '0'     - do not continue on error, '1' - continue on error\r
+        *              bit 3 - '0' - next DSS has different correlator, '1' - next DSS has\r
+        *                                              same correlator\r
+        *              type - 1 - Request DSS\r
+        *                       - 2 - Reply DSS\r
+        *                       - 3 - Object DSS\r
+        *                       - 4 - Communications DSS\r
+        *                       - 5 - Request DSS where no reply is expected\r
+        *      2 bytes - request correlation id\r
+        *\r
+        * @exception DRDProtocolException\r
+        */\r
+       protected int readDssHeader () throws DRDAProtocolException\r
+       {\r
+               ensureALayerDataInBuffer (6);\r
+\r
+               // read out the DSS length\r
+               dssLength = ((buffer[pos] & 0xff) << 8) +\r
+                                       ((buffer[pos + 1] & 0xff) << 0);\r
+               pos += 2;\r
+               // check for the continuation bit and update length as needed.\r
+               if ((dssLength & DssConstants.CONTINUATION_BIT) == \r
+                               DssConstants.CONTINUATION_BIT) \r
+               {\r
+                       dssLength = DssConstants.MAX_DSS_LENGTH;\r
+                       dssIsContinued = true;\r
+               }\r
+               else \r
+               {\r
+                       dssIsContinued = false;\r
+               }\r
+\r
+               if (dssLength < 6)\r
+                       agent.throwSyntaxrm(CodePoint.SYNERRCD_DSS_LESS_THAN_6,\r
+                                                          DRDAProtocolException.NO_CODPNT_ARG);\r
+\r
+               // If the GDS id is not valid, or\r
+               // if the reply is not an RQSDSS nor\r
+               // a OBJDSS, then throw an exception.\r
+\r
+               if ((buffer[pos++] & 0xff) != DssConstants.DSS_ID)\r
+                       agent.throwSyntaxrm(CodePoint.SYNERRCD_CBYTE_NOT_D0,\r
+                                                          DRDAProtocolException.NO_CODPNT_ARG);\r
+\r
+               int gdsFormatter = buffer[pos++] & 0xff;\r
+               \r
+               if (((gdsFormatter & 0x0F) != DssConstants.DSSFMT_RQSDSS)\r
+                       &&((gdsFormatter & 0x0F) != DssConstants.DSSFMT_OBJDSS)) \r
+               {\r
+                       agent.throwSyntaxrm(CodePoint.SYNERRCD_FBYTE_NOT_SUPPORTED,\r
+                                                          DRDAProtocolException.NO_CODPNT_ARG);\r
+               }\r
+\r
+               // Determine if the current DSS is chained with the\r
+               // next DSS, with the same or different request ID.\r
+               if ((gdsFormatter & DssConstants.DSSCHAIN) == DssConstants.DSSCHAIN) \r
+               {       // on indicates structure chained to next structure\r
+                       if ((gdsFormatter & DssConstants.DSSCHAIN_SAME_ID) \r
+                                       == DssConstants.DSSCHAIN_SAME_ID) \r
+                       {\r
+                               dssIsChainedWithSameID = true;\r
+                               dssIsChainedWithDiffID = false;\r
+                       }\r
+                       else \r
+                       {\r
+                               dssIsChainedWithSameID = false;\r
+                               dssIsChainedWithDiffID = true;\r
+                       }\r
+                       if ((gdsFormatter & DssConstants.DSSCHAIN_ERROR_CONTINUE) \r
+                               == DssConstants.DSSCHAIN_ERROR_CONTINUE)\r
+                               terminateChainOnErr = false;\r
+                       else\r
+                               terminateChainOnErr = true;\r
+               }\r
+               else \r
+               {\r
+                       // chaining bit not b'1', make sure DSSFMT same id not b'1'\r
+                       if ((gdsFormatter & DssConstants.DSSCHAIN_SAME_ID) \r
+                                       == DssConstants.DSSCHAIN_SAME_ID)       \r
+                       {  // Next DSS can not have same correlator\r
+                               agent.throwSyntaxrm(CodePoint.SYNERRCD_CHAIN_OFF_SAME_NEXT_CORRELATOR,\r
+                                                                  DRDAProtocolException.NO_CODPNT_ARG);\r
+                       }\r
+                       // chaining bit not b'1', make sure no error continuation\r
+                       if ((gdsFormatter & DssConstants.DSSCHAIN_ERROR_CONTINUE) \r
+                               == DssConstants.DSSCHAIN_ERROR_CONTINUE) \r
+                       { // must be 'do not continue on error'\r
+                               agent.throwSyntaxrm(CodePoint.SYNERRCD_CHAIN_OFF_ERROR_CONTINUE,\r
+                                                                  DRDAProtocolException.NO_CODPNT_ARG);\r
+                       }\r
+\r
+                       dssIsChainedWithSameID = false;\r
+                       dssIsChainedWithDiffID = false;\r
+               }\r
+\r
+               dssCorrelationID =\r
+                       ((buffer[pos] & 0xff) << 8) +\r
+                       ((buffer[pos + 1] & 0xff) << 0);\r
+               pos += 2;\r
+               if (SanityManager.DEBUG)\r
+                       trace("dssLength = " + dssLength + " correlationID = " + dssCorrelationID);\r
+\r
+               //check that correlationID is the same as previous\r
+               if (prevCorrelationID != DssConstants.CORRELATION_ID_UNKNOWN && \r
+                       dssCorrelationID != prevCorrelationID)\r
+               {\r
+                       agent.throwSyntaxrm(CodePoint.SYNERRCD_CHAIN_OFF_ERROR_CONTINUE,\r
+                                                          DRDAProtocolException.NO_CODPNT_ARG);\r
+               }\r
+               \r
+               // set up previous correlation id to check that next DSS is correctly\r
+               // formatted\r
+               if (dssIsChainedWithSameID)\r
+                       prevCorrelationID = dssCorrelationID;\r
+               else\r
+                       prevCorrelationID = DssConstants.CORRELATION_ID_UNKNOWN;\r
+\r
+               dssLength -= 6;\r
+\r
+               return dssCorrelationID;\r
+       }\r
+       /**\r
+        * Read Reply DSS\r
+        * This is used in testing the protocol.  We shouldn't see a reply\r
+        * DSS when we are servicing DRDA commands\r
+        *\r
+        * @exception DRDProtocolException\r
+        */\r
+       protected void readReplyDss() throws DRDAProtocolException\r
+       {\r
+               ensureALayerDataInBuffer (6);\r
+\r
+               // read out the DSS length\r
+               dssLength = ((buffer[pos++] & 0xff) << 8) +\r
+                                       ((buffer[pos++] & 0xff) << 0);\r
+\r
+               // check for the continuation bit and update length as needed.\r
+               if ((dssLength & DssConstants.CONTINUATION_BIT) == \r
+                               DssConstants.CONTINUATION_BIT) \r
+               {\r
+                       dssLength = DssConstants.MAX_DSS_LENGTH;\r
+                       dssIsContinued = true;\r
+               }\r
+               else \r
+               {\r
+                       dssIsContinued = false;\r
+               }\r
+\r
+               if (dssLength < 6)\r
+                       agent.throwSyntaxrm(CodePoint.SYNERRCD_DSS_LESS_THAN_6,\r
+                                                          DRDAProtocolException.NO_CODPNT_ARG);\r
+\r
+               // If the GDS id is not valid, throw exception\r
+\r
+               if ((buffer[pos++] & 0xff) != DssConstants.DSS_ID)\r
+                       agent.throwSyntaxrm(CodePoint.SYNERRCD_CBYTE_NOT_D0,\r
+                                                          DRDAProtocolException.NO_CODPNT_ARG);\r
+\r
+               int gdsFormatter = buffer[pos++] & 0xff;\r
+               \r
+               // Determine if the current DSS is chained with the\r
+               // next DSS, with the same or different request ID.\r
+               if ((gdsFormatter & DssConstants.DSSCHAIN) == DssConstants.DSSCHAIN) \r
+               {       // on indicates structure chained to next structure\r
+                       if ((gdsFormatter & DssConstants.DSSCHAIN_SAME_ID) \r
+                                       == DssConstants.DSSCHAIN_SAME_ID) \r
+                       {\r
+                               dssIsChainedWithSameID = true;\r
+                               dssIsChainedWithDiffID = false;\r
+                       }\r
+                       else \r
+                       {\r
+                               dssIsChainedWithSameID = false;\r
+                               dssIsChainedWithDiffID = true;\r
+                       }\r
+               }\r
+               else \r
+               {\r
+                       dssIsChainedWithSameID = false;\r
+                       dssIsChainedWithDiffID = false;\r
+               }\r
+\r
+               dssCorrelationID =\r
+                       ((buffer[pos++] & 0xff) << 8) +\r
+                       ((buffer[pos++] & 0xff) << 0);\r
+\r
+               if (SanityManager.DEBUG)                                        \r
+                       trace("dssLength = " + dssLength + " correlationID = " + dssCorrelationID);\r
+\r
+               dssLength -= 6;\r
+\r
+       }\r
+\r
+       /**\r
+        * Read the DDM Length and CodePoint\r
+        *\r
+     * @param isLayerBStreamingPossible true only when layer B streaming is possible\r
+        * @return - returns codepoint\r
+        *\r
+        * @exception DRDProtocolException\r
+        */\r
+       protected int readLengthAndCodePoint( boolean isLayerBStreamingPossible ) \r
+        throws DRDAProtocolException\r
+       {\r
+               ensureBLayerDataInBuffer (4, NO_ADJUST_LENGTHS);\r
+\r
+               ddmScalarLen = readCodePoint();\r
+               int codePoint = readCodePoint();\r
+               \r
+               if (SanityManager.DEBUG)\r
+                       trace("length = "+ ddmScalarLen + " codepoint = " + java.lang.Integer.toHexString(codePoint));\r
+               // SYNERRCD 0x0D - Object code point index not supported.\r
+               // the object codepoint index will not be checked here since\r
+               // the parse methods will catch any incorrect/unexpected codepoint values\r
+               // and report them as unsupported objects or parameters.\r
+\r
+               // Check if this DDM has extended length field\r
+               if ((ddmScalarLen & DssConstants.CONTINUATION_BIT) == DssConstants.CONTINUATION_BIT) \r
+               {\r
+                       int numberOfExtendedLenBytes = ((int)ddmScalarLen - \r
+                                       DssConstants.CONTINUATION_BIT) - 4;\r
+                       int adjustSize = 0;\r
+                       ensureBLayerDataInBuffer (numberOfExtendedLenBytes, NO_ADJUST_LENGTHS);\r
+                       switch (numberOfExtendedLenBytes) {\r
+                       case 8:\r
+                                ddmScalarLen =\r
+                                       ((buffer[pos++] & 0xFFL) << 56) +\r
+                                       ((buffer[pos++] & 0xFFL) << 48) +\r
+                                       ((buffer[pos++] & 0xFFL) << 40) +\r
+                                       ((buffer[pos++] & 0xFFL) << 32) +\r
+                                       ((buffer[pos++] & 0xFFL) << 24) +\r
+                                       ((buffer[pos++] & 0xFFL) << 16) +\r
+                                       ((buffer[pos++] & 0xFFL) << 8) +\r
+                                       ((buffer[pos++] & 0xFFL) << 0);\r
+                               adjustSize = 12;\r
+                               break;\r
+                       case 6:\r
+                               ddmScalarLen =\r
+                                       ((buffer[pos++] & 0xFFL) << 40) +\r
+                                       ((buffer[pos++] & 0xFFL) << 32) +\r
+                                       ((buffer[pos++] & 0xFFL) << 24) +\r
+                                       ((buffer[pos++] & 0xFFL) << 16) +\r
+                                       ((buffer[pos++] & 0xFFL) << 8) +\r
+                                       ((buffer[pos++] & 0xFFL) << 0);\r
+                               adjustSize = 10;\r
+                               break;\r
+                       case 4:\r
+                               ddmScalarLen =\r
+                                       ((buffer[pos++] & 0xFFL) << 24) +\r
+                                       ((buffer[pos++] & 0xFFL) << 16) +\r
+                                       ((buffer[pos++] & 0xFFL) << 8) +\r
+                                       ((buffer[pos++] & 0xFFL) << 0);\r
+                               adjustSize = 8;\r
+                               break;\r
+                \r
+            case 0:\r
+                \r
+                if( isLayerBStreamingPossible &&\r
+                    ( codePoint == CodePoint.EXTDTA || \r
+                      codePoint == CodePoint.QRYDTA ) ){\r
+                    \r
+                    startLayerBStreaming();\r
+                    adjustSize = 4;\r
+                    \r
+                }else {\r
+                    agent.throwSyntaxrm(CodePoint.SYNERRCD_INCORRECT_EXTENDED_LEN,\r
+                                        DRDAProtocolException.NO_CODPNT_ARG);\r
+                }\r
+                \r
+                break;\r
+                \r
+                       default:\r
+                               agent.throwSyntaxrm(CodePoint.SYNERRCD_INCORRECT_EXTENDED_LEN,\r
+                                                          DRDAProtocolException.NO_CODPNT_ARG);\r
+               }\r
+\r
+                       // adjust the lengths here.     this is a special case since the\r
+                       // extended length bytes do not include their own length.\r
+                       for (int i = 0; i <= topDdmCollectionStack; i++) {\r
+                               ddmCollectionLenStack[i] -= adjustSize;\r
+                       }\r
+                       dssLength -= adjustSize;\r
+               }\r
+               else {\r
+                       if (ddmScalarLen < 4)\r
+                               agent.throwSyntaxrm(CodePoint.SYNERRCD_OBJ_LEN_LESS_THAN_4,\r
+                                                                  DRDAProtocolException.NO_CODPNT_ARG);\r
+                       adjustLengths (4);\r
+               }\r
+               return codePoint;\r
+       }\r
+\r
+       /**\r
+        * Read the CodePoint\r
+        *\r
+        * @return - returns codepoint\r
+        */\r
+       protected int readCodePoint()\r
+       {\r
+               return( ((buffer[pos++] & 0xff) << 8) +\r
+                 ((buffer[pos++] & 0xff) << 0));\r
+       }\r
+\r
+       /**\r
+        * Push DDM Length on to collection stack\r
+        */\r
+       protected void markCollection()\r
+       {\r
+               ddmCollectionLenStack[++topDdmCollectionStack] = ddmScalarLen;\r
+               ddmScalarLen = 0;\r
+       }\r
+\r
+       /**\r
+        *      Get the next CodePoint from a collection\r
+        *      @return NO_CODEPOINT if collection stack is empty or remaining length is\r
+        *              0; otherwise,  read length and code point\r
+        *\r
+        * @exception DRDProtocolException\r
+        */\r
+       protected int getCodePoint() throws DRDAProtocolException\r
+       {\r
+               if (topDdmCollectionStack == EMPTY_STACK) \r
+               {\r
+                       return NO_CODEPOINT;\r
+               }\r
+               else \r
+               {\r
+                       // if the collecion is exhausted then return NO_CODEPOINT\r
+                       if (ddmCollectionLenStack[topDdmCollectionStack] == 0) \r
+                {\r
+                               // done with this collection so remove it's length from the stack\r
+                               ddmCollectionLenStack[topDdmCollectionStack--] = 0;\r
+                               return NO_CODEPOINT;\r
+                       }\r
+                       else {\r
+                               return readLengthAndCodePoint( false );\r
+                       }\r
+               }\r
+       }\r
+       /**\r
+        * Get the next CodePoint from a collection and check that it matches the specified\r
+        *      CodePoint\r
+        * @param       codePointCheck  - codePoint to check against\r
+        * @return      codePoint\r
+        *\r
+        * @exception DRDProtocolException\r
+        */\r
+       protected int getCodePoint(int codePointCheck) throws DRDAProtocolException\r
+       {\r
+               int codePoint = getCodePoint();\r
+               if (codePoint != codePointCheck)\r
+                       agent.missingCodePoint(codePoint);\r
+               return codePoint;\r
+       }\r
+       /**\r
+        * The following routines read different types from the input stream\r
+        * Data can be in network order or platform order depending on whether the\r
+        * data is part of the protocol or data being received\r
+        * The platform is determined by EXCSAT protocol\r
+        */\r
+\r
+       /**\r
+        * Read byte value\r
+        * @return      value\r
+        *\r
+        * @exception DRDProtocolException\r
+        */\r
+       protected byte readByte () throws DRDAProtocolException\r
+       {\r
+               ensureBLayerDataInBuffer (1, ADJUST_LENGTHS);\r
+               return buffer[pos++];\r
+       }\r
+\r
+       /**\r
+        * Read byte value and mask out high order bytes before returning\r
+        * @return value\r
+        */\r
+       protected int readUnsignedByte () throws DRDAProtocolException\r
+       {\r
+               ensureBLayerDataInBuffer (1, ADJUST_LENGTHS);\r
+               return (int ) (buffer[pos++] & 0xff);\r
+       }\r
+\r
+       /**\r
+        * Read network short value\r
+        * @return      value\r
+        *\r
+        * @exception DRDProtocolException\r
+        */\r
+       protected int readNetworkShort () throws DRDAProtocolException\r
+       {\r
+               ensureBLayerDataInBuffer (2, ADJUST_LENGTHS);\r
+               return ((buffer[pos++] & 0xff) << 8) +\r
+                 ((buffer[pos++] & 0xff) << 0);\r
+       }\r
+\r
+       /**\r
+        * Read signed network short value\r
+        * @return      value\r
+        *\r
+        * @exception DRDProtocolException\r
+        */\r
+       protected int readSignedNetworkShort () throws DRDAProtocolException\r
+       {\r
+               ensureBLayerDataInBuffer (2, ADJUST_LENGTHS);\r
+               return (short)(((buffer[pos++] & 0xff) << 8) +\r
+                 ((buffer[pos++] & 0xff) << 0));\r
+       }\r
+       /**\r
+        * Read platform short value\r
+        * @return      value\r
+        *\r
+        * @exception DRDProtocolException\r
+        */\r
+       protected short readShort (int byteOrder) throws DRDAProtocolException\r
+       {\r
+               ensureBLayerDataInBuffer (2, ADJUST_LENGTHS);\r
+               short s = SignedBinary.getShort (buffer, pos, byteOrder);\r
+\r
+               pos += 2;\r
+\r
+               return s;\r
+       }\r
+\r
+       /**\r
+        * Read network int value\r
+        * @return      value\r
+        *\r
+        * @exception DRDProtocolException\r
+        */\r
+       protected int readNetworkInt () throws DRDAProtocolException\r
+       {\r
+               ensureBLayerDataInBuffer (4, ADJUST_LENGTHS);\r
+               return ((buffer[pos++] & 0xff) << 24) +\r
+                      ((buffer[pos++] & 0xff) << 16) +\r
+                      ((buffer[pos++] & 0xff) << 8) +\r
+                      ((buffer[pos++] & 0xff) << 0);\r
+       }\r
+\r
+       /**\r
+        * Read platform int value\r
+        * @return      value\r
+        *\r
+        * @exception DRDProtocolException\r
+        */\r
+       protected int readInt (int byteOrder) throws DRDAProtocolException\r
+       {\r
+               ensureBLayerDataInBuffer (4, ADJUST_LENGTHS);\r
+               int i = SignedBinary.getInt (buffer, pos, byteOrder);\r
+\r
+               pos += 4;\r
+\r
+               return i;\r
+       }\r
+\r
+       /**\r
+        * Read network long value\r
+        * @return      value\r
+        *\r
+        * @exception DRDProtocolException\r
+        */\r
+       protected long readNetworkLong () throws DRDAProtocolException\r
+       {\r
+               ensureBLayerDataInBuffer (8, ADJUST_LENGTHS);\r
+\r
+               return ((buffer[pos++] & 0xffL) << 56) +\r
+                      ((buffer[pos++] & 0xffL) << 48) +\r
+                      ((buffer[pos++] & 0xffL) << 40) +\r
+                      ((buffer[pos++] & 0xffL) << 32) +\r
+                      ((buffer[pos++] & 0xffL) << 24) +\r
+                      ((buffer[pos++] & 0xffL) << 16) +\r
+                      ((buffer[pos++] & 0xffL) << 8) +\r
+                      ((buffer[pos++] & 0xffL) << 0);\r
+       }\r
+\r
+       \r
+       /**\r
+        * Read network six byte value and put it in a long v\r
+        * @return      value\r
+        *\r
+        * @exception DRDProtocolException\r
+        */\r
+       protected long readNetworkSixByteLong() throws DRDAProtocolException\r
+       {\r
+               ensureBLayerDataInBuffer (6, ADJUST_LENGTHS);\r
+\r
+               return (\r
+                               ((buffer[pos++] & 0xffL) << 40) +\r
+                      ((buffer[pos++] & 0xffL) << 32) +\r
+                      ((buffer[pos++] & 0xffL) << 24) +\r
+                      ((buffer[pos++] & 0xffL) << 16) +\r
+                      ((buffer[pos++] & 0xffL) << 8) +\r
+                      ((buffer[pos++] & 0xffL) << 0));\r
+       }\r
+\r
+       /**\r
+        * Read platform long value\r
+        * @return      value\r
+        *\r
+        * @exception DRDProtocolException\r
+        */\r
+       protected long readLong (int byteOrder) throws DRDAProtocolException\r
+       {\r
+               ensureBLayerDataInBuffer (8, ADJUST_LENGTHS);\r
+               long l = SignedBinary.getLong (buffer, pos, byteOrder);\r
+\r
+               pos += 8;\r
+\r
+               return l;\r
+       }\r
+\r
+       /**\r
+        * Read platform float value\r
+        * @return      value\r
+        *\r
+        * @exception DRDProtocolException\r
+        */\r
+       protected float readFloat(int byteOrder) throws DRDAProtocolException\r
+       {\r
+               return Float.intBitsToFloat(readInt(byteOrder));\r
+       }\r
+\r
+       /**\r
+        * Read platform double value\r
+        * @return      value\r
+        *\r
+        * @exception DRDProtocolException\r
+        */\r
+       protected double readDouble(int byteOrder) throws DRDAProtocolException\r
+       {\r
+               return Double.longBitsToDouble(readLong(byteOrder));\r
+       }\r
+\r
+       /**\r
+        * Read a BigDecimal value\r
+        * @param       precision of the BigDecimal\r
+        * @param       scale of the BigDecimal\r
+        * @return      value\r
+        *\r
+        * @exception DRDProtocolException\r
+        */\r
+       protected BigDecimal readBigDecimal(int precision, int scale) throws DRDAProtocolException\r
+    {\r
+      // The byte-length of a packed decimal with precision p is always p/2 + 1\r
+      int length = precision / 2 + 1;\r
+\r
+         ensureBLayerDataInBuffer (length, ADJUST_LENGTHS);\r
+\r
+      // check for sign.\r
+      int signum;\r
+      if ((buffer[pos+length-1] & 0x0F) == 0x0D)\r
+        signum = -1;\r
+      else\r
+        signum =  1;\r
+\r
+      if (precision <= 9) {\r
+        // can be handled by int without overflow.\r
+        int value = packedNybblesToInt(buffer, pos, 0, length*2-1);\r
+\r
+        // convert value to a byte array of magnitude.\r
+        byte[] magnitude = new byte[4];\r
+        magnitude[0] = (byte)(value >>> 24);\r
+        magnitude[1] = (byte)(value >>> 16);\r
+        magnitude[2] = (byte)(value >>> 8);\r
+        magnitude[3] = (byte)(value);\r
+\r
+               pos += length;\r
+        return new java.math.BigDecimal (new java.math.BigInteger(signum, magnitude), scale);\r
+      }\r
+      else if (precision <= 18) {\r
+        // can be handled by long without overflow.\r
+        long value = packedNybblesToLong(buffer, pos, 0, length*2-1);\r
+\r
+        // convert value to a byte array of magnitude.\r
+        byte[] magnitude = new byte[8];\r
+        magnitude[0] = (byte)(value >>> 56);\r
+        magnitude[1] = (byte)(value >>> 48);\r
+        magnitude[2] = (byte)(value >>> 40);\r
+        magnitude[3] = (byte)(value >>> 32);\r
+        magnitude[4] = (byte)(value >>> 24);\r
+        magnitude[5] = (byte)(value >>> 16);\r
+        magnitude[6] = (byte)(value >>>  8);\r
+        magnitude[7] = (byte)(value);\r
+\r
+               pos += length;\r
+        return new java.math.BigDecimal (new java.math.BigInteger(signum, magnitude), scale);\r
+      }\r
+      else if (precision <= 27) {\r
+        // get the value of last 9 digits (5 bytes).\r
+        int lo = packedNybblesToInt(buffer, pos, (length-5)*2, 9);\r
+        // get the value of another 9 digits (5 bytes).\r
+        int me = packedNybblesToInt(buffer, pos, (length-10)*2+1, 9);\r
+        // get the value of the rest digits.\r
+        int hi = packedNybblesToInt(buffer, pos, 0, (length-10)*2+1);\r
+\r
+        // compute the int array of magnitude.\r
+        int[] value = computeMagnitude(new int[] {hi, me, lo});\r
+\r
+        // convert value to a byte array of magnitude.\r
+        byte[] magnitude = new byte[12];\r
+        magnitude[0]  = (byte)(value[0] >>> 24);\r
+        magnitude[1]  = (byte)(value[0] >>> 16);\r
+        magnitude[2]  = (byte)(value[0] >>> 8);\r
+        magnitude[3]  = (byte)(value[0]);\r
+        magnitude[4]  = (byte)(value[1] >>> 24);\r
+        magnitude[5]  = (byte)(value[1] >>> 16);\r
+        magnitude[6]  = (byte)(value[1] >>> 8);\r
+        magnitude[7]  = (byte)(value[1]);\r
+        magnitude[8]  = (byte)(value[2] >>> 24);\r
+        magnitude[9]  = (byte)(value[2] >>> 16);\r
+        magnitude[10] = (byte)(value[2] >>> 8);\r
+        magnitude[11] = (byte)(value[2]);\r
+\r
+               pos += length;\r
+        return new java.math.BigDecimal (new java.math.BigInteger(signum, magnitude), scale);\r
+      }\r
+      else if (precision <= 31) {\r
+        // get the value of last 9 digits (5 bytes).\r
+        int lo   = packedNybblesToInt(buffer, pos, (length-5)*2, 9);\r
+        // get the value of another 9 digits (5 bytes).\r
+        int meLo = packedNybblesToInt(buffer, pos, (length-10)*2+1, 9);\r
+        // get the value of another 9 digits (5 bytes).\r
+        int meHi = packedNybblesToInt(buffer, pos, (length-14)*2, 9);\r
+        // get the value of the rest digits.\r
+        int hi   = packedNybblesToInt(buffer, pos, 0, (length-14)*2);\r
+\r
+        // compute the int array of magnitude.\r
+        int[] value = computeMagnitude(new int[] {hi, meHi, meLo, lo});\r
+\r
+        // convert value to a byte array of magnitude.\r
+        byte[] magnitude = new byte[16];\r
+        magnitude[0]  = (byte)(value[0] >>> 24);\r
+        magnitude[1]  = (byte)(value[0] >>> 16);\r
+        magnitude[2]  = (byte)(value[0] >>> 8);\r
+        magnitude[3]  = (byte)(value[0]);\r
+        magnitude[4]  = (byte)(value[1] >>> 24);\r
+        magnitude[5]  = (byte)(value[1] >>> 16);\r
+        magnitude[6]  = (byte)(value[1] >>> 8);\r
+        magnitude[7]  = (byte)(value[1]);\r
+        magnitude[8]  = (byte)(value[2] >>> 24);\r
+        magnitude[9]  = (byte)(value[2] >>> 16);\r
+        magnitude[10] = (byte)(value[2] >>> 8);\r
+        magnitude[11] = (byte)(value[2]);\r
+        magnitude[12] = (byte)(value[3] >>> 24);\r
+        magnitude[13] = (byte)(value[3] >>> 16);\r
+        magnitude[14] = (byte)(value[3] >>> 8);\r
+        magnitude[15] = (byte)(value[3]);\r
+\r
+               pos += length;\r
+        return new java.math.BigDecimal (new java.math.BigInteger(signum, magnitude), scale);\r
+      }\r
+      else {\r
+               pos += length;\r
+        // throw an exception here if nibbles is greater than 31\r
+        throw new java.lang.IllegalArgumentException("Decimal may only be up to 31 digits!");\r
+      }\r
+    }\r
+\r
+       \r
+\r
+       byte[] getExtData (boolean checkNullability) throws DRDAProtocolException\r
+       {\r
+               return  getExtData(ddmScalarLen, checkNullability);\r
+       }\r
+\r
+       \r
+       /**\r
+        * Creates an InputStream which can stream EXTDTA objects.\r
+        * The InputStream uses this DDMReader to read data from network. The \r
+        * DDMReader should not be used before all data in the stream has been read.\r
+        * @param checkNullability used to check if the stream is null. If it is \r
+        * null, this method returns null\r
+        * @return EXTDTAReaderInputStream object which can be passed to prepared\r
+        *         statement as a binary stream.\r
+        * @exception DRDAProtocolException standard DRDA protocol exception\r
+        */\r
+       EXTDTAReaderInputStream getEXTDTAReaderInputStream\r
+               (final boolean checkNullability)\r
+               throws DRDAProtocolException\r
+       {\r
+               if (checkNullability && isEXTDTANull()) {\r
+                       return null;\r
+            \r
+               } else if ( doingLayerBStreaming ){\r
+                       return new LayerBStreamedEXTDTAReaderInputStream(this);\r
+        \r
+        } else {\r
+            return new StandardEXTDTAReaderInputStream(this);\r
+            \r
+        }\r
+\r
+       }\r
+    \r
+    /**\r
+        * This method is used by EXTDTAReaderInputStream to read the first chunk \r
+        * of data.\r
+     * This lengthless method must be called only when layer B streaming.\r
+     *\r
+        * @exception DRDAProtocolException standard DRDA protocol exception\r
+        */\r
+       ByteArrayInputStream readLOBInitStream() \r
+               throws DRDAProtocolException\r
+       {\r
+        if ( SanityManager.DEBUG ) {\r
+            SanityManager.ASSERT( doingLayerBStreaming );\r
+        }\r
+               \r
+        return readLOBInitStream( 0 );\r
+        \r
+       }\r
+       \r
+\r
+       /**\r
+        * This method is used by EXTDTAReaderInputStream to read the first chunk \r
+        * of data.\r
+        * @param desiredLength the desired length of chunk. This parameter is ignored when layerB Streaming is doing.\r
+        * @exception DRDAProtocolException standard DRDA protocol exception\r
+        */\r
+       ByteArrayInputStream readLOBInitStream(final long desiredLength) \r
+               throws DRDAProtocolException\r
+       {\r
+               return readLOBChunk(false, desiredLength);\r
+       }\r
+       \r
+    \r
+    /**\r
+        * This method is used by EXTDTAReaderInputStream to read the next chunk \r
+        * of data.\r
+     *\r
+     * Calling this method finishes layer B streaming \r
+     * if continuation of DSS segment was finished.\r
+     * This lengthless method must be called only when layer B streaming.\r
+     *\r
+        * @exception IOException IOException\r
+        */\r
+       ByteArrayInputStream readLOBContinuationStream ()\r
+               throws IOException\r
+       {               \r
+        if ( SanityManager.DEBUG ) {\r
+            SanityManager.ASSERT( doingLayerBStreaming );\r
+        }\r
+        return readLOBContinuationStream( 0 );\r
+       }\r
+    \r
+\r
+       /**\r
+        * This method is used by EXTDTAReaderInputStream to read the next chunk \r
+        * of data.\r
+     *\r
+     * Furthermore, when Layer B streaming is carried out,\r
+     * calling this method finishes layer B streaming \r
+     * if continuation of DSS segment was finished.\r
+     *\r
+        * @param desiredLength the desired length of chunk. This parameter is ignored when layerB Streaming is doing.\r
+        * @exception IOException IOException\r
+        */\r
+       ByteArrayInputStream readLOBContinuationStream (final long desiredLength)\r
+               throws IOException\r
+       {               \r
+               try {\r
+                       return readLOBChunk(true, desiredLength);\r
+               } catch (DRDAProtocolException e) {\r
+                       e.printStackTrace(agent.getServer().logWriter);\r
+                       throw new IOException(e.getMessage());\r
+               }\r
+       }\r
+\r
+       /**\r
+        * This method is used by EXTDTAReaderInputStream to read the next chunk \r
+        * of data.\r
+     *\r
+     * Furthermore, when Layer B streaming is carried out,\r
+     * calling this method may finish layer B streaming.\r
+     *\r
+        * @param readHeader set to true if the dss continuation should be read\r
+        * @param desiredLength the desired length of chunk. This parameter is ignored when layerB Streaming is doing.\r
+        * @exception DRDAProtocolException standard DRDA protocol exception\r
+        */\r
+       private ByteArrayInputStream readLOBChunk\r
+               (final boolean readHeader, final long desiredLength)\r
+               throws DRDAProtocolException\r
+       {               \r
+               if (readHeader) {                       \r
+                       readDSSContinuationHeader();\r
+               }\r
+               \r
+        int copySize = doingLayerBStreaming ? \r
+            dssLength : \r
+            (int) Math.min(dssLength, desiredLength);\r
+               \r
+               // read the segment\r
+               ensureALayerDataInBuffer (copySize);\r
+        \r
+        if( ! doingLayerBStreaming ){\r
+            adjustLengths (copySize);\r
+            \r
+        }else{\r
+            dssLength -= copySize;\r
+            \r
+        }\r
+               \r
+               // Create ByteArrayInputStream on top of buffer. \r
+               // This will not make a copy of the buffer.\r
+               ByteArrayInputStream bais = \r
+                       new ByteArrayInputStream(buffer, pos, copySize);\r
+               pos += copySize;\r
+               \r
+        if( doingLayerBStreaming && \r
+            ! dssIsContinued )\r
+            finishLayerBStreaming();\r
+        \r
+               return bais;\r
+       }\r
+\r
+       byte[] getExtData (long desiredLength, boolean checkNullability) throws DRDAProtocolException\r
+  {\r
+\r
+      if ( SanityManager.DEBUG ) {\r
+            SanityManager.ASSERT( ! doingLayerBStreaming );\r
+        }\r
+\r
+    boolean readHeader;\r
+    int copySize;\r
+    ByteArrayOutputStream baos;\r
+    boolean isLengthAndNullabilityUnknown = false;\r
+\r
+       \r
+       if (desiredLength != -1) {\r
+        // allocate a stream based on a known amount of data\r
+        baos = new ByteArrayOutputStream ((int) desiredLength);\r
+       }\r
+       else {\r
+        // allocate a stream to hold an unknown amount of data\r
+        baos = new ByteArrayOutputStream ();\r
+        //isLengthAndNullabilityUnknown = true;\r
+               // If we aren't given a  length get the whole thing.\r
+               desiredLength = MAX_EXTDTA_SIZE;\r
+       }\r
+       \r
+\r
+    // check for a null EXTDTA value, if it is nullable and if streaming\r
+    if (checkNullability)\r
+      if (isEXTDTANull())\r
+        return null;\r
+\r
+    // set the amount to read for the first segment\r
+       copySize = (int) Math.min(dssLength,desiredLength); //note: has already been adjusted for headers\r
+\r
+\r
+    //if (checkNullability)  // don't count the null byte we've already read\r
+       //copySize--;\r
+\r
+    do {\r
+      // determine if a continuation header needs to be read after the data\r
+      if (dssIsContinued)\r
+        readHeader = true;\r
+      else\r
+        readHeader = false;\r
+\r
+      // read the segment\r
+      ensureALayerDataInBuffer (copySize);\r
+      adjustLengths (copySize);\r
+      baos.write (buffer, pos, copySize);\r
+      pos += copySize;\r
+         desiredLength -= copySize;\r
+\r
+      // read the continuation header, if necessary\r
+      if (readHeader)\r
+        readDSSContinuationHeader ();\r
+\r
+         copySize = (int) Math.min(dssLength,desiredLength); //note: has already been adjusted for headers\r
+\r
+    }\r
+    while (readHeader == true && desiredLength > 0);\r
+\r
+    return baos.toByteArray();\r
+  }\r
+\r
+\r
+  // reads a DSS continuation header\r
+  // prereq: pos is positioned on the first byte of the two-byte header\r
+  // post:   dssIsContinued is set to true if the continuation bit is on, false otherwise\r
+  //         dssLength is set to DssConstants.MAXDSS_LEN - 2 (don't count the header for the next read)\r
+  // helper method for getEXTDTAData\r
+       private void readDSSContinuationHeader () throws DRDAProtocolException\r
+  {\r
+    ensureALayerDataInBuffer(2);\r
+\r
+    dssLength =\r
+      ((buffer[pos++]&0xFF) << 8) +\r
+      ((buffer[pos++]&0xFF) << 0);\r
+\r
+    if ((dssLength & 0x8000) == 0x8000) {\r
+      dssLength = DssConstants.MAX_DSS_LENGTH;\r
+      dssIsContinued = true;\r
+    }\r
+    else {\r
+      dssIsContinued = false;\r
+    }\r
+    // it is a syntax error if the dss continuation header length\r
+    // is less than or equal to two\r
+    if (dssLength <= 2) {\r
+               agent.throwSyntaxrm(CodePoint.SYNERRCD_DSS_CONT_LESS_OR_EQUAL_2,\r
+                                                          DRDAProtocolException.NO_CODPNT_ARG);\r
+    }\r
+\r
+    dssLength -= 2;  // avoid consuming the DSS cont header\r
+  }\r
+\r
+// checks the null EXTDTA byte\r
+  // returns true if null, false otherwise\r
+  // helper method for getEXTDTAData\r
+  private boolean isEXTDTANull () throws DRDAProtocolException\r
+  {\r
+    // make sure that the null byte is in the buffer\r
+    ensureALayerDataInBuffer (1);\r
+    adjustLengths (1);\r
+\r
+    // examine the null byte\r
+    byte nullByte = buffer[pos++];\r
+    if (nullByte == (byte)0x00)\r
+      return false;\r
+\r
+    return true;\r
+  }\r
+\r
+\r
+   /**\r
+    * Convert a range of packed nybbles (up to 9 digits without overflow) to an int.\r
+    * Note that for performance purpose, it does not do array-out-of-bound checking.\r
+       * @param buffer                 buffer to read from\r
+       * @param offset                 offset in the buffer\r
+       * @param startNybble            start nybble\r
+       * @param numberOfNybbles        number of nybbles\r
+       * @return       an int value\r
+    */\r
+    private int packedNybblesToInt (byte[] buffer,\r
+                                         int offset,\r
+                                         int startNybble,\r
+                                         int numberOfNybbles)\r
+    {\r
+      int value = 0;\r
+\r
+      int i = startNybble / 2;\r
+      if ((startNybble % 2) != 0) {\r
+        // process low nybble of the first byte if necessary.\r
+        value += buffer[offset+i] & 0x0F;\r
+        i++;\r
+      }\r
+\r
+      int endNybble = startNybble + numberOfNybbles -1;\r
+      for (; i<(endNybble+1)/2; i++) {\r
+        value = value*10 + ((buffer[offset+i] & 0xF0) >>> 4); // high nybble.\r
+        value = value*10 +  (buffer[offset+i] & 0x0F);        // low nybble.\r
+      }\r
+\r
+      if ((endNybble % 2) == 0) {\r
+        // process high nybble of the last byte if necessary.\r
+        value = value*10 + ((buffer[offset+i] & 0xF0) >>> 4);\r
+      }\r
+\r
+      return value;\r
+    }\r
+\r
+    /**\r
+     * Convert a range of packed nybbles (up to 18 digits without overflow) to a long.\r
+     * Note that for performance purpose, it does not do array-out-of-bound checking.\r
+        * @param buffer                buffer to read from\r
+        * @param offset                offset in the buffer\r
+        * @param startNybble           start nybble\r
+        * @param numberOfNybbles       number of nybbles\r
+        * @return      an long value\r
+     */\r
+    private long packedNybblesToLong (byte[] buffer,\r
+                                           int offset,\r
+                                           int startNybble,\r
+                                           int numberOfNybbles)\r
+    {\r
+      long value = 0;\r
+\r
+      int i = startNybble / 2;\r
+      if ((startNybble % 2) != 0) {\r
+        // process low nybble of the first byte if necessary.\r
+        value += buffer[offset+i] & 0x0F;\r
+        i++;\r
+      }\r
+\r
+      int endNybble = startNybble + numberOfNybbles -1;\r
+      for (; i<(endNybble+1)/2; i++) {\r
+        value = value*10 + ((buffer[offset+i] & 0xF0) >>> 4); // high nybble.\r
+        value = value*10 +  (buffer[offset+i] & 0x0F);        // low nybble.\r
+      }\r
+\r
+      if ((endNybble % 2) == 0) {\r
+        // process high nybble of the last byte if necessary.\r
+        value = value*10 + ((buffer[offset+i] & 0xF0) >>> 4);\r
+      }\r
+\r
+         return value;\r
+       }\r
+\r
+    /**\r
+     * Compute the int array of magnitude from input value segments.\r
+        * @param       input value segments\r
+        * @return      array of int magnitudes\r
+     */\r
+    private int[] computeMagnitude(int[] input)\r
+    {\r
+        int length = input.length;\r
+        int[] mag = new int[length];\r
+\r
+        mag[length-1] = input[length-1];\r
+        for (int i=0; i<length-1; i++) {\r
+          int carry = 0;\r
+          int j = tenRadixMagnitude[i].length-1;\r
+          int k = length-1;\r
+          for (; j>=0; j--, k--) {\r
+            long product = (input[length-2-i] & 0xFFFFFFFFL) * (tenRadixMagnitude[i][j] & 0xFFFFFFFFL)\r
+                         + (mag[k] & 0xFFFFFFFFL) // add previous value\r
+                         + (carry & 0xFFFFFFFFL); // add carry\r
+            carry  = (int) (product >>> 32);\r
+            mag[k] = (int) (product & 0xFFFFFFFFL);\r
+          }\r
+          mag[k] = (int) carry;\r
+        }\r
+        return mag;\r
+    }\r
+\r
+       /**\r
+        * Read boolean value\r
+        * @return      value\r
+        *\r
+        * @exception DRDProtocolException\r
+        */\r
+       protected boolean readBoolean () throws DRDAProtocolException\r
+       {\r
+               ensureBLayerDataInBuffer (1, ADJUST_LENGTHS);\r
+               return buffer[pos++] != 0;\r
+       }\r
+\r
+       /**\r
+        * Read encrypted string\r
+        * @param   decryptM  decryption manager\r
+        * @param   securityMechanism security mechanism\r
+        * @param   initVector   initialization vector for cipher\r
+        * @param   sourcePublicKey  public key (as in Deffie-Hellman algorithm)\r
+        *                           from source (encryptor)\r
+        * @return  decrypted string\r
+        *\r
+        * @exception DRDProtocolException, SQLException(wrapping any exception in decryption)\r
+        */\r
+       protected String readEncryptedString (DecryptionManager decryptM, int securityMechanism,\r
+                                                                                byte[] initVector, byte[] sourcePublicKey)\r
+                       throws DRDAProtocolException, java.sql.SQLException\r
+       {\r
+               byte[] cipherText = readBytes();\r
+               byte[] plainText = null;\r
+               plainText = decryptM.decryptData(cipherText, securityMechanism, initVector,\r
+                                                                                        sourcePublicKey);\r
+               if (plainText == null)\r
+                       return null;\r
+               else\r
+                       return ccsidManager.convertToUCS2(plainText);\r
+       }\r
+\r
+       /**\r
+        * Read string value\r
+        * Strings in DRDA protocol are encoded in EBCDIC by default so we\r
+        * need to convert to UCS2\r
+        * @param length  - length of string to read\r
+        * @return value\r
+        *\r
+        * @exception DRDProtocolException\r
+        */\r
+       protected String readString (int length) throws DRDAProtocolException\r
+       {\r
+               ensureBLayerDataInBuffer (length, ADJUST_LENGTHS);\r
+\r
+               String result = ccsidManager.convertToUCS2 (buffer, pos, length);\r
+               pos += length;\r
+               return result;\r
+       }\r
+\r
+       /**\r
+        * Read string value into a <code>DRDAString</code> object.\r
+        *\r
+        * @param dst  destination for the read string\r
+        * @param size size (in bytes) of string to read\r
+        * @param unpad if true, remove padding (trailing spaces)\r
+        *\r
+        * @exception DRDAProtocolException\r
+        */\r
+       protected void readString(DRDAString dst, int size, boolean unpad)\r
+               throws DRDAProtocolException\r
+       {\r
+               ensureBLayerDataInBuffer(size, ADJUST_LENGTHS);\r
+               int startPos = pos;\r
+               pos += size;\r
+               if (unpad) {\r
+                       while ((size > 0) &&\r
+                                  (buffer[startPos + size - 1] == ccsidManager.space)) {\r
+                               --size;\r
+                       }\r
+               }\r
+               dst.setBytes(buffer, startPos, size);\r
+       }\r
+\r
+       /**\r
+        * Read encoded string value\r
+        * @param length  - length of string to read\r
+        * @return value\r
+        *\r
+        * @exception DRDProtocolException\r
+        */\r
+       protected String readString (int length, String encoding) \r
+               throws DRDAProtocolException\r
+       {\r
+               ensureBLayerDataInBuffer (length, ADJUST_LENGTHS);\r
+               String s = null;\r
+\r
+               try {\r
+                 s = new String (buffer, pos, length, encoding);\r
+               }\r
+               catch (java.io.UnsupportedEncodingException e) {\r
+                       agent.agentError("UnsupportedEncodingException in readString, encoding = " \r
+                                       + encoding);\r
+                       e.printStackTrace(agent.getServer().logWriter);\r
+               }\r
+               \r
+               pos += length;\r
+               return s;\r
+       }\r
+\r
+       /**\r
+        * Read string value in DDM data with default encoding\r
+        * @return value\r
+        *\r
+        * @exception DRDProtocolException\r
+        */\r
+       protected String readStringData()\r
+               throws DRDAProtocolException\r
+       {\r
+               return readString((int)ddmScalarLen, NetworkServerControlImpl.DEFAULT_ENCODING);\r
+       }\r
+\r
+       /**\r
+        * Read specified length of string value in DDM data with default encoding\r
+        * @param length  - length of string to read\r
+        * @return value\r
+        *\r
+        * @exception DRDProtocolException\r
+        */\r
+       protected String readStringData(int length)\r
+               throws DRDAProtocolException\r
+       {\r
+               return readString(length, NetworkServerControlImpl.DEFAULT_ENCODING);\r
+       }\r
+\r
+       /**\r
+        * Read length delimited string value in DDM data with default encoding\r
+        * @return value\r
+        *\r
+        * @exception DRDProtocolException\r
+        */\r
+       protected String readLDStringData(String encoding)\r
+               throws DRDAProtocolException\r
+       {\r
+               int length = readNetworkShort();\r
+               return readString(length, encoding);\r
+       }\r
+\r
+       /**\r
+        * Read string value\r
+        *\r
+        * @exception DRDProtocolException\r
+        */\r
+       protected String readString () throws DRDAProtocolException\r
+       {\r
+               return readString((int)ddmScalarLen);\r
+       }\r
+\r
+       /**\r
+        * Read byte string value\r
+        * @param length  - length of string to read\r
+        * @return byte array\r
+        *\r
+        * @exception DRDProtocolException\r
+        */\r
+       protected byte[] readBytes (int length) throws DRDAProtocolException\r
+       {\r
+               byte[] b;\r
+\r
+               if (length < DssConstants.MAX_DSS_LENGTH)\r
+               {\r
+                       ensureBLayerDataInBuffer (length, ADJUST_LENGTHS);\r
+                   b = new byte[length];\r
+                       System.arraycopy(buffer,pos,b,0,length);\r
+                       pos +=length;\r
+               }\r
+               else\r
+                       b = getExtData(length,false);\r
+               return b;\r
+       }\r
+       \r
+       /**\r
+        * Read byte string value\r
+        * @return byte array\r
+        *\r
+        * @exception DRDProtocolException\r
+        */\r
+       protected byte[] readBytes () throws DRDAProtocolException\r
+       {\r
+               return readBytes((int)ddmScalarLen);\r
+       }\r
+\r
+       /**\r
+        * Skip byte string value\r
+        * @param length  - length of string to skip\r
+        *\r
+        * @exception DRDProtocolException\r
+        */\r
+       protected void skipBytes (int length) throws DRDAProtocolException\r
+       {\r
+               ensureBLayerDataInBuffer (length, ADJUST_LENGTHS);\r
+               pos += length;\r
+       }\r
+\r
+       /**\r
+        * Skip byte string value\r
+        *\r
+        * @exception DRDAProtocolException\r
+        */\r
+       protected void skipBytes () throws DRDAProtocolException\r
+       {\r
+               skipBytes((int)ddmScalarLen);\r
+       }\r
+\r
+       /**\r
+        * Skip remaining DSS\r
+        *\r
+        * @exception DRDAProtocolException\r
+        */\r
+       protected void skipDss() throws DRDAProtocolException\r
+       {\r
+               while (dssIsContinued)\r
+               {\r
+                       skipBytes((int)dssLength);\r
+                       readDSSContinuationHeader();\r
+               }\r
+               skipBytes((int)dssLength);\r
+               topDdmCollectionStack = EMPTY_STACK;\r
+               ddmScalarLen = 0;\r
+               dssLength = 0;\r
+\r
+       }\r
+\r
+       protected void clearBuffer() throws DRDAProtocolException\r
+       {\r
+               skipBytes(java.lang.Math.min(dssLength, count - pos));\r
+       dssIsChainedWithSameID = false;\r
+       dssIsChainedWithDiffID = false;\r
+       }\r
+\r
+       /**\r
+        * Convert EBCDIC byte array to unicode string\r
+        *\r
+        * @param       buf     - byte array\r
+        * @return string\r
+        */\r
+       protected String convertBytes(byte[] buf)\r
+       {\r
+               return ccsidManager.convertToUCS2 (buf, 0, buf.length);\r
+       }\r
+\r
+       // Private methods\r
+       /**\r
+        * Adjust remaining length\r
+        *\r
+        * @param length - adjustment length\r
+        */\r
+       private void adjustLengths(int length)\r
+       {\r
+               ddmScalarLen -= length;\r
+               for (int i = 0; i <= topDdmCollectionStack; i++) {\r
+                 ddmCollectionLenStack[i] -= length;\r
+               }\r
+               dssLength -= length;\r
+       }\r
+\r
+       /********************************************************************/\r
+       /*   NetworkServerControl  command protocol reading routines        \r
+        */\r
+       /********************************************************************/\r
+       /**\r
+        * Read string value\r
+        * @param length  - length of string to read\r
+        * @return value\r
+        *\r
+        * @exception DRDProtocolException\r
+        */\r
+       protected String readCmdString (int length) throws DRDAProtocolException, java.io.UnsupportedEncodingException\r
+       {\r
+               if (length == 0)\r
+                       return null;\r
+\r
+               ensureBLayerDataInBuffer (length, ADJUST_LENGTHS);\r
+               String result = new String (buffer, pos, length,\r
+                                                                               NetworkServerControlImpl.DEFAULT_ENCODING);\r
+               pos += length;\r
+               return result;\r
+       }\r
+       /**\r
+        * Read string value\r
+        * @return value\r
+        *\r
+        * @exception DRDProtocolException\r
+        */\r
+       protected String readCmdString () throws DRDAProtocolException, java.io.UnsupportedEncodingException\r
+       {\r
+               int length = readNetworkShort();\r
+               return readCmdString(length);\r
+               \r
+       }\r
+\r
+       /**************************************************************************/\r
+       /*   Private methods\r
+       /**************************************************************************/\r
+       /**\r
+        * Make sure a certain amount of Layer A data is in the buffer.\r
+        * The data will be in the buffer after this method is called.\r
+        *\r
+        * @param desiredDataSize - amount of data we need\r
+        *\r
+        * @exception   DRDAProtocolException\r
+        */\r
+       private void ensureALayerDataInBuffer (int desiredDataSize) \r
+               throws DRDAProtocolException\r
+       {\r
+               // calulate the the number of bytes in the buffer.\r
+               int avail = count - pos;\r
+\r
+               // read more bytes off the network if the data is not in the buffer already.\r
+               if (avail < desiredDataSize) \r
+               {\r
+                 fill (desiredDataSize - avail);\r
+               }\r
+       }\r
+       /**\r
+        * Make sure a certain amount of Layer B data is in the buffer.\r
+        * The data will be in the buffer after this method is called.\r
+        *\r
+        * @param desiredDataSize - amount of data we need\r
+        * @param adjustLen     - whether to adjust the remaining lengths\r
+        *\r
+        * @exception DRDProtocolException\r
+        */\r
+       private void ensureBLayerDataInBuffer (int desiredDataSize, boolean adjustLen) \r
+               throws DRDAProtocolException\r
+       {\r
+               ensureALayerDataInBuffer (desiredDataSize);\r
+               if (dssIsContinued) \r
+               {\r
+                       if (desiredDataSize > dssLength) \r
+                       {\r
+                               int continueDssHeaderCount =\r
+                                       (((desiredDataSize - dssLength) / DssConstants.MAX_DSS_LENGTH) + 1);\r
+                               compressBLayerData (continueDssHeaderCount);\r
+                       }\r
+               }\r
+               if (adjustLen)\r
+                       adjustLengths(desiredDataSize);\r
+       }\r
+\r
+       /**\r
+        * Compress B Layer data if extended total length is used\r
+        * by removing the continuation headers\r
+        *\r
+        * @param continueDssHeaderCount - amount of data we need\r
+        *\r
+        * @exception   throws DRDAProtocolException\r
+        */\r
+       private void compressBLayerData (int continueDssHeaderCount) \r
+               throws DRDAProtocolException\r
+       {\r
+\r
+               \r
+               // jump to the last continuation header.\r
+               int tempPos = 0;\r
+               for (int i = 0; i < continueDssHeaderCount; i++) \r
+               {\r
+                       // the first may be less than the size of a full DSS\r
+                       if (i == 0) \r
+                       {\r
+                               // only jump by the number of bytes remaining in the current DSS\r
+                               tempPos = pos + dssLength;\r
+                       }\r
+                       else \r
+                       {\r
+                               // all other jumps are for a full continued DSS\r
+                               tempPos += DssConstants.MAX_DSS_LENGTH;\r
+                       }\r
+               }\r
+\r
+\r
+               // for each of the DSS headers to remove,\r
+               // read out the continuation header and increment the DSS length by the\r
+               // size of the continuation bytes,      then shift the continuation data as needed.\r
+               int shiftSize = 0;\r
+               int bytesToShift = 0;\r
+               int continueHeaderLength = 0;\r
+               int newdssLength = 0;\r
+\r
+\r
+               for (int i = 0; i < continueDssHeaderCount; i++) \r
+               {\r
+                       continueHeaderLength = ((buffer[tempPos] & 0xff) << 8) +\r
+                               ((buffer[tempPos + 1] & 0xff) << 0);\r
+\r
+                       if (i == 0) \r
+                       {\r
+                               // if this is the last one (farthest down stream and first to strip out)\r
+\r
+                               if ((continueHeaderLength & DssConstants.CONTINUATION_BIT) \r
+                                               == DssConstants.CONTINUATION_BIT)\r
+                               {\r
+                                 // the last DSS header is again continued\r
+                                 continueHeaderLength = DssConstants.MAX_DSS_LENGTH;\r
+                                 dssIsContinued = true;\r
+                               }\r
+                               else \r
+                               {\r
+                                 // the last DSS header was not contiued so update continue state flag\r
+                                 dssIsContinued = false;\r
+                               }\r
+                               // the very first shift size is 2\r
+                               shiftSize = 2;\r
+                       }\r
+                       else \r
+                       {\r
+                               // already removed the last header so make sure the chaining flag is on\r
+                               if ((continueHeaderLength & DssConstants.CONTINUATION_BIT) == \r
+                                               DssConstants.CONTINUATION_BIT)\r
+                               {\r
+                                 continueHeaderLength = DssConstants.MAX_DSS_LENGTH;\r
+                               }\r
+                               else \r
+                               {\r
+                                 // this is a syntax error but not really certain which one.\r
+                                 // for now pick 0x02 which is DSS header Length does not \r
+                                 // match the number\r
+                                   // of bytes of data found.\r
+                                       agent.throwSyntaxrm(CodePoint.SYNERRCD_DSS_LENGTH_BYTE_NUMBER_MISMATCH,\r
+                                                                          DRDAProtocolException.NO_CODPNT_ARG);\r
+                               }\r
+                               // increase the shift size by 2\r
+                               shiftSize += 2;\r
+                       }\r
+\r
+                       // it is a syntax error if the DSS continuation is less \r
+                       // than or equal to two\r
+                       if (continueHeaderLength <= 2) \r
+                       {\r
+                               agent.throwSyntaxrm(CodePoint.SYNERRCD_DSS_CONT_LESS_OR_EQUAL_2,\r
+                                                          DRDAProtocolException.NO_CODPNT_ARG);\r
+                       }\r
+\r
+                       newdssLength += (continueHeaderLength-2);\r
+\r
+                       // calculate the number of bytes to shift\r
+                       if (i != (continueDssHeaderCount - 1))\r
+                               bytesToShift = DssConstants.MAX_DSS_LENGTH;\r
+                       else\r
+                               bytesToShift = dssLength;\r
+\r
+                       tempPos -= (bytesToShift - 2);\r
+                       System.arraycopy(buffer, tempPos - shiftSize, buffer, tempPos,\r
+                                                        bytesToShift);\r
+               }\r
+               // reposition the start of the data after the final DSS shift.\r
+               pos = tempPos;\r
+               dssLength += newdssLength;\r
+       }\r
+\r
+       /**\r
+        * Methods to manage the data buffer.\r
+        * Methods orginally from JCC\r
+        * RESOLVE: need to check if this is the best performing way of doing this\r
+        */\r
+\r
+       /**\r
+        * This is a helper method which shifts the buffered bytes from\r
+        * wherever they are in the current buffer to the beginning of\r
+        * different buffer (note these buffers could be the same).\r
+        * State information is updated as needed after the shift.\r
+        * @param destinationBuffer - buffer to shift data to\r
+        */\r
+       private void shiftBuffer (byte[] destinationBuffer)\r
+       {\r
+               // calculate the size of the data in the current buffer.\r
+               int sz = count - pos;\r
+               if (SanityManager.DEBUG) {\r
+                       if ((sz < 0 || pos < 0) )\r
+                       {\r
+                               SanityManager.THROWASSERT(\r
+                                             "Unexpected data size or position. sz=" + sz + \r
+                                                 " count=" + count +" pos=" + pos);\r
+                       }\r
+               }\r
+               \r
+               // copy this data to the new buffer startsing at position 0.\r
+               System.arraycopy (buffer, pos, destinationBuffer, 0, sz);\r
+\r
+               // update the state information for data in the new buffer.\r
+               pos = 0;\r
+               count = sz;\r
+\r
+               // replace the old buffer with the new buffer.\r
+               buffer = destinationBuffer;\r
+       }\r
+       /**\r
+        * This method makes sure there is enough room in the buffer\r
+        * for a certain number of bytes.  This method will allocate\r
+        * a new buffer if needed and shift the bytes in the current buffer\r
+        * to make ensure space is available for a fill.  Right now\r
+        * this method will shift bytes as needed to make sure there is\r
+        * as much room as possible in the buffer before trying to\r
+        * do the read.  The idea is to try to have space to get as much data as possible\r
+        * if we need to do a read on the socket's stream.\r
+        *\r
+        * @param desiredSpace - amount of data we need\r
+        */\r
+       private void ensureSpaceInBufferForFill (int desiredSpace)\r
+       {\r
+               // calculate the total unused space in the buffer.\r
+               // this includes any space at the end of the buffer and any free\r
+               // space at the beginning resulting from bytes already read.\r
+               int currentAvailableSpace = (buffer.length - count) + pos;\r
+\r
+               // check to see if there is enough free space.\r
+               if (currentAvailableSpace < desiredSpace) {\r
+\r
+                       // there is not enough free space so we need more storage.\r
+                       // we are going to double the buffer unless that happens to still be \r
+                       // too small. If more than double the buffer is needed, \r
+                       // use the smallest amount over this as possible.\r
+                       int doubleBufferSize = (2 * buffer.length);\r
+                       int minumNewBufferSize = (desiredSpace - currentAvailableSpace) + \r
+                               buffer.length;\r
+                       int newsz = minumNewBufferSize <= doubleBufferSize ? \r
+                               doubleBufferSize : minumNewBufferSize;\r
+\r
+                       byte[] newBuffer = new byte[newsz];\r
+\r
+                       // shift everything from the old buffer to the new buffer\r
+                       shiftBuffer (newBuffer);\r
+               }\r
+               else {\r
+\r
+                       // there is enough free space in the buffer but let's make sure\r
+                       // it is all at the end.\r
+                       // this is also important because if we are going to do a read, \r
+                       // it would be nice\r
+                       // to get as much data as possible and making room at the end \r
+                       // if the buffer helps to ensure this.\r
+                       if (pos != 0) {\r
+                               shiftBuffer (buffer);\r
+                       }\r
+               }\r
+       }\r
+\r
+       /**\r
+        * This method will attempt to read a minimum number of bytes\r
+        * from the underlying stream.  This method will keep trying to\r
+        * read bytes until it has obtained at least the minimum number.\r
+        * @param minimumBytesNeeded - minimum required bytes\r
+        *\r
+        * @exception DRDProtocolException\r
+        */\r
+       private void fill (int minimumBytesNeeded) throws DRDAProtocolException\r
+       {\r
+               // make sure that there is enough space in the buffer to hold\r
+               // the minimum number of bytes needed.\r
+               ensureSpaceInBufferForFill (minimumBytesNeeded);\r
+\r
+               // read until the minimum number of bytes needed is now in the buffer.\r
+               // hopefully the read method will return as many bytes as it can.\r
+               int totalBytesRead = 0;\r
+               int actualBytesRead = 0;\r
+               do {\r
+                       try {\r
+                               actualBytesRead = inputStream.read (//waiting for client request on the socket\r
+                                 buffer, count, buffer.length - count);\r
+                       } catch (java.net.SocketTimeoutException ste) {\r
+\r
+                // Transport the timeout out through the layers. This\r
+                // exception is caught in DRDAConnThread.run();\r
+                throw new DRDASocketTimeoutException(agent);\r
+\r
+                       } catch (java.io.IOException ioe) {\r
+                agent.markCommunicationsFailure("DDMReader.fill()",\r
+                                                "InputStream.read()", ioe.getMessage(), "*");\r
+                       } finally {\r
+                               if ((dssTrace != null) && dssTrace.isComBufferTraceOn())\r
+                                 dssTrace.writeComBufferData (buffer,\r
+                                                              count,\r
+                                                              actualBytesRead,\r
+                                                              DssTrace.TYPE_TRACE_RECEIVE,\r
+                                                              "Request",\r
+                                                              "fill",\r
+                                                              5);\r
+                       }\r
+                       if (actualBytesRead != -1)\r
+                       {\r
+                               count += actualBytesRead;\r
+                               totalBytesRead += actualBytesRead;\r
+                       }\r
+\r
+               } while ((totalBytesRead < minimumBytesNeeded) && (actualBytesRead != -1));\r
+\r
+               if (actualBytesRead == -1) \r
+               {\r
+                       if (totalBytesRead < minimumBytesNeeded) \r
+                       {\r
+                               agent.markCommunicationsFailure ("DDMReader.fill()",\r
+                                 "InputStream.read()", "insufficient data", "*");\r
+                       }\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Print a internal trace message\r
+        */\r
+       private void trace(String msg)\r
+       {\r
+               if (agent != null)\r
+                       agent.trace(msg);\r
+       }\r
+\r
+       protected String toDebugString(String indent)\r
+       {\r
+               String s = indent + "***** DDMReader toDebugString ******\n";\r
+               int buflen = 0;\r
+               if (buffer != null)\r
+                       buflen = buffer.length;\r
+          s += indent + "Reader buffer length = " + buffer.length + "\n";\r
+          return s;\r
+       }\r
+\r
+       /**\r
+        * Return chaining bit for current DSS.\r
+        */\r
+       protected byte getCurrChainState() {\r
+\r
+               if (!dssIsChainedWithSameID && !dssIsChainedWithDiffID)\r
+                       return DssConstants.DSS_NOCHAIN;\r
+\r
+               if (dssIsChainedWithSameID)\r
+                       return DssConstants.DSSCHAIN_SAME_ID;\r
+\r
+               return DssConstants.DSSCHAIN;\r
+\r
+       }\r
+    \r
+    \r
+    private void startLayerBStreaming() {\r
+        doingLayerBStreaming = true;\r
+    }\r
+    \r
+    \r
+    private void finishLayerBStreaming() {\r
+        doingLayerBStreaming = false;\r
+    }\r
+    \r
+    \r
+    boolean doingLayerBStreaming() {\r
+        return doingLayerBStreaming;\r
+    }\r
+    \r
+    \r
+}\r