Adding JMCR-Stable version
[Benchmarks_CSolver.git] / JMCR-Stable / real-world application / MyDerby-10.3 / java / drda / org / apache / derby / impl / drda / DDMWriter.java
diff --git a/JMCR-Stable/real-world application/MyDerby-10.3/java/drda/org/apache/derby/impl/drda/DDMWriter.java b/JMCR-Stable/real-world application/MyDerby-10.3/java/drda/org/apache/derby/impl/drda/DDMWriter.java
new file mode 100644 (file)
index 0000000..31e9658
--- /dev/null
@@ -0,0 +1,1997 @@
+/*\r
+\r
+   Derby - Class org.apache.derby.impl.drda.DDMWriter\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
+\r
+import java.io.OutputStream;\r
+import java.io.InputStream;\r
+import java.io.BufferedOutputStream;\r
+import java.io.UnsupportedEncodingException;\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+import java.sql.SQLException;\r
+import java.math.BigDecimal;\r
+import java.util.Arrays;\r
+import org.apache.derby.iapi.reference.Property;\r
+import org.apache.derby.iapi.services.property.PropertyUtil;\r
+\r
+import java.io.IOException;\r
+\r
+/**\r
+       The DDMWriter is used to write DRDA protocol.   The DRDA Protocol is\r
+       described in the DDMReader class.\r
+       For more details, see DRDA Volume 3 (Distributed Data Management(DDM)\r
+               Architecture (DDS definition)\r
+*/\r
+class DDMWriter\r
+{\r
+\r
+       // number of nesting levels for collections.  We need to mark the length\r
+       // location of the collection so that we can update it as we add more stuff\r
+       // to the collection\r
+       private final static int MAX_MARKS_NESTING = 10;\r
+\r
+       // Default buffer size\r
+       private final static int DEFAULT_BUFFER_SIZE = 32767;\r
+\r
+\r
+       static final BigDecimal ZERO = BigDecimal.valueOf(0L);\r
+        \r
+       private static final byte MULTI_BYTE_MASK = (byte) 0xC0;\r
+       private static final byte CONTINUATION_BYTE = (byte) 0x80;\r
+\r
+       // output buffer\r
+       private byte[] bytes;\r
+\r
+       // offset into output buffer\r
+       private int offset;\r
+\r
+       // A saved mark in the stream is saved temporarily to revisit the location.\r
+       private int[] markStack = new int[MAX_MARKS_NESTING];\r
+\r
+       // top of the stack\r
+       private int top;\r
+\r
+       // CCSID manager for translation of strings in the protocol to EBCDIC\r
+       private CcsidManager ccsidManager;\r
+\r
+       // DRDA connection thread for this writer\r
+       private DRDAConnThread agent;\r
+\r
+       //      This Object tracks the location of the current\r
+       //      Dss header length bytes.        This is done so\r
+       //      the length bytes can be automatically\r
+       //      updated as information is added to this stream.\r
+       private int dssLengthLocation;\r
+\r
+       // Current correlation ID\r
+       private int correlationID;\r
+\r
+       // Next correlation ID\r
+       private int nextCorrelationID;\r
+\r
+       // is this DRDA protocol or CMD protocol\r
+       private boolean isDRDAProtocol;\r
+       // trace object of the associated session\r
+       private DssTrace dssTrace;\r
+\r
+       // Location within the "bytes" array of the start of the header\r
+       // of the DSS most recently written to the buffer.\r
+       private int prevHdrLocation;\r
+\r
+       // Correlation id of the last DSS that was written to buffer.\r
+       private int previousCorrId;\r
+\r
+       // Chaining bit of the last DSS that was written to buffer.\r
+       private byte previousChainByte;\r
+\r
+       // Whether or not the current DSS is a continuation DSS.\r
+       private boolean isContinuationDss;\r
+\r
+       // In situations where we want to "mark" a buffer location so that\r
+       // we can "back-out" of a write to handle errors, this holds the\r
+       // location within the "bytes" array of the start of the header\r
+       // that immediately precedes the mark.\r
+       private int lastDSSBeforeMark;\r
+\r
+       // Constructors\r
+       DDMWriter (int minSize, CcsidManager ccsidManager, DRDAConnThread agent, DssTrace dssTrace)\r
+       {\r
+               this.bytes = new byte[minSize];\r
+               this.ccsidManager = ccsidManager;\r
+               this.agent = agent;\r
+               this.prevHdrLocation = -1;\r
+               this.previousCorrId = DssConstants.CORRELATION_ID_UNKNOWN;\r
+               this.previousChainByte = DssConstants.DSS_NOCHAIN;\r
+               this.isContinuationDss = false;\r
+               this.lastDSSBeforeMark = -1;\r
+               reset(dssTrace);\r
+       }\r
+\r
+       DDMWriter (CcsidManager ccsidManager, DRDAConnThread agent, DssTrace dssTrace)\r
+       {\r
+               this.bytes = new byte[DEFAULT_BUFFER_SIZE];\r
+               this.ccsidManager = ccsidManager;\r
+               this.agent = agent;\r
+               this.prevHdrLocation = -1;\r
+               this.previousCorrId = DssConstants.CORRELATION_ID_UNKNOWN;\r
+               this.previousChainByte = DssConstants.DSS_NOCHAIN;\r
+               this.isContinuationDss = false;\r
+               this.lastDSSBeforeMark = -1;\r
+               reset(dssTrace);\r
+       }\r
+\r
+       /**\r
+        * reset values for sending next message\r
+        *\r
+        */\r
+       protected void reset(DssTrace dssTrace)\r
+       {\r
+               offset = 0;\r
+               top = 0;\r
+               dssLengthLocation = 0;\r
+               nextCorrelationID = 1;\r
+               correlationID = DssConstants.CORRELATION_ID_UNKNOWN;\r
+               isDRDAProtocol = true;\r
+               this.dssTrace = dssTrace;\r
+       }\r
+\r
+       /**\r
+        * set protocol to CMD protocol\r
+        */\r
+       protected void setCMDProtocol()\r
+       {\r
+               isDRDAProtocol = false;\r
+       }\r
+\r
+       /**\r
+        * Create DSS reply object\r
+        */\r
+       protected void createDssReply()\r
+       {\r
+               beginDss(DssConstants.DSSFMT_RPYDSS, true);\r
+       }\r
+\r
+       /**\r
+        * Create DSS request object\r
+        * NOTE: This is _ONLY_ used for testing the protocol\r
+        * (via the TestProto.java file in this package)!\r
+        * We should never create a DSS request in normal\r
+        * DRDA processing (we should only create DSS replies\r
+        * and DSS objects).\r
+        */\r
+       protected void createDssRequest()\r
+       {\r
+               beginDss(DssConstants.DSSFMT_RQSDSS, true);\r
+       }\r
+\r
+       /**\r
+        * Create DSS data object\r
+        */\r
+       protected void createDssObject()\r
+       {\r
+               beginDss(DssConstants.DSSFMT_OBJDSS, true);\r
+       }\r
+\r
+       /**\r
+        * Mark the DSS that we're currently writing as\r
+        * a continued DSS, which is done by setting\r
+        * the high-order bit to "1", per DDM spec.\r
+        * This means:\r
+        *\r
+        *      1. One or more continuation DSSes will immediately\r
+        *              follow the current (continued) DSS.\r
+        *      2. All continuation DSSes will have a 2-byte\r
+        *              continuation header, followed by data; in\r
+        *              other words, chaining state, correlation\r
+        *              id, dss format info, and code point will\r
+        *              NOT be included.  All of that info is \r
+        *              present ONLY in the FIRST DSS in the\r
+        *              list of continued DSSes.\r
+        *\r
+        *      NOTE: A DSS can be a "continuation" DSS _and_\r
+        *      a "continued" DSS at the same time.  However,\r
+        *      the FIRST DSS to be continued canNOT be\r
+        *      a continuation DSS.\r
+        */\r
+       private void markDssAsContinued(boolean forLob)\r
+       {\r
+\r
+               if (!forLob) {\r
+               // continuation bit defaults to '1' for lobs, so\r
+               // we only have to switch it if we're not writing\r
+               // lobs.\r
+                       bytes[dssLengthLocation] |= 0x80;\r
+               }\r
+\r
+               // We need to set the chaining state, but ONLY\r
+               // IF this is the FIRST DSS in the continuation\r
+               // list (only the first one has chaining state\r
+               // in it's header; the others do not).\r
+               if (!isContinuationDss)\r
+                       endDss(!forLob);\r
+\r
+       }\r
+\r
+       /**\r
+        * End DSS header by writing the length in the length location\r
+        * and setting the chain bit.  Unlike the other two endDss\r
+        * methods, this one overrides the default chaining byte\r
+        * (which is set in beginDss) with the chaining byte that\r
+        * is passed in.  NOTE: This method is only used in\r
+        * association with createDssRequest, and thus is for\r
+        * TESTING purposes only (via TestProto.java).  No calls\r
+        * should be made to this method in normal DRDA processing\r
+        * (because for normal processing, chaining must be\r
+        * determined automatically based on DSS requests).\r
+        */\r
+       protected void endDss(byte chainByte)\r
+       {\r
+\r
+               // Do regular endDss processing.\r
+               endDss(true);\r
+\r
+               // Now override default chain state.\r
+               bytes[dssLengthLocation + 3] &= 0x0F;   // Zero out default\r
+               bytes[dssLengthLocation + 3] |= chainByte;\r
+               previousChainByte = chainByte;\r
+\r
+       }\r
+\r
+       /**\r
+        * End DSS header by writing the length in the length location\r
+        * and setting the chain bit.\r
+        */\r
+       protected void endDss() {\r
+               endDss(true);\r
+       }\r
+\r
+       /**\r
+        * End DSS header by writing the length in the length location\r
+        * and setting the chain bit.\r
+        */\r
+       private void endDss (boolean finalizeLength)\r
+       {\r
+\r
+               if (finalizeLength)\r
+                       finalizeDssLength();\r
+\r
+               if (isContinuationDss) {\r
+               // no chaining information for this DSS; so we're done.\r
+                       isContinuationDss = false;\r
+                       return;\r
+               }\r
+\r
+               previousCorrId = correlationID;\r
+               prevHdrLocation = dssLengthLocation;\r
+               previousChainByte = DssConstants.DSSCHAIN_SAME_ID;\r
+\r
+       }\r
+\r
+       /**\r
+        * End final DDM and DSS header by writing the length in the length location\r
+        *\r
+        */\r
+       protected void endDdmAndDss ()\r
+       {\r
+               endDdm();       // updates last DDM object\r
+               endDss();\r
+       }\r
+       /**\r
+        * Copy Data to End\r
+        * Create a buffer and copy from the position given to the end of data\r
+        *\r
+        * Note that the position given is treated as relative to the\r
+        * current DSS, for there may be other DSS blocks (chained, presumably)\r
+        * which are sitting unwritten in the buffer. The caller doesn't\r
+        * know this, though, and works only with the current DSS.\r
+        *\r
+        * getDSSLength, copyDSSDataToEnd, and truncateDSS work together to\r
+        * provide a sub-protocol for DRDAConnThread to use in its\r
+        * implementation of the LMTBLKPRC protocol. They enable the caller\r
+        * to determine when it has written too much data into the current\r
+        * DSS, to reclaim the extra data that won't fit, and to truncate\r
+        * that extra data once it has been reclaimed and stored elsewhere.\r
+        * Note that this support only works for the current DSS. Earlier,\r
+        * chained DSS blocks cannot be accessed using these methods. For\r
+        * additional background information, the interested reader should\r
+        * investigate bugs DERBY-491 and 492 at:\r
+        * http://issues.apache.org/jira/browse/DERBY-491 and\r
+        * http://issues.apache.org/jira/browse/DERBY-492\r
+        *\r
+        * @param start\r
+        */\r
+       protected byte [] copyDSSDataToEnd(int start)\r
+       {\r
+               start = start + dssLengthLocation;\r
+               int length = offset - start;\r
+               byte [] temp = new byte[length];\r
+               System.arraycopy(bytes,start,temp,0,length);\r
+               return temp;\r
+       }\r
+\r
+       // Collection methods\r
+\r
+       /**\r
+        * Mark the location of the length bytes for the collection so they\r
+        * can be updated later\r
+        *\r
+        */\r
+       protected void startDdm (int codePoint)\r
+       {\r
+               // save the location of the beginning of the collection so\r
+               // that we can come back and fill in the length bytes\r
+               markStack[top++] = offset;\r
+               ensureLength (4); // verify space for length bytes and code point\r
+               offset += 2; // move past the length bytes before writing the code point\r
+               bytes[offset] = (byte) ((codePoint >>> 8) & 0xff);\r
+               bytes[offset + 1] = (byte) (codePoint & 0xff);\r
+               offset += 2;\r
+       }\r
+\r
+       /**\r
+        * Erase all writes for the current ddm and reset the\r
+        * top\r
+        */\r
+       protected void clearDdm ()\r
+       {\r
+               offset = markStack[top--];\r
+       }\r
+\r
+       /**\r
+        * Clear the entire send buffer\r
+        *\r
+        */\r
+       protected void clearBuffer()\r
+       {\r
+               offset = 0;\r
+               top = 0;\r
+               dssLengthLocation = 0;\r
+               correlationID = DssConstants.CORRELATION_ID_UNKNOWN;\r
+               nextCorrelationID = 1;\r
+               isDRDAProtocol = true;\r
+       }\r
+\r
+       /**\r
+        * End the current DDM\r
+        *\r
+        */\r
+       protected void endDdm ()\r
+       {\r
+               // remove the top length location offset from the mark stack\r
+               // calculate the length based on the marked location and end of data.\r
+               int lengthLocation = markStack[--top];\r
+               int length = offset - lengthLocation;\r
+\r
+               // determine if any extended length bytes are needed.   the value returned\r
+               // from calculateExtendedLengthByteCount is the number of extended length\r
+               // bytes required. 0 indicates no exteneded length.\r
+               int extendedLengthByteCount = calculateExtendedLengthByteCount (length);\r
+               if (extendedLengthByteCount != 0)\r
+               {\r
+                       // ensure there is enough room in the buffer for the extended length bytes.\r
+                       ensureLength (extendedLengthByteCount);\r
+\r
+                       // calculate the length to be placed in the extended length bytes.\r
+                       // this length does not include the 4 byte llcp.\r
+                       int extendedLength = length - 4;\r
+\r
+                       // shift the data to the right by the number of extended\r
+                       // length bytes needed.\r
+                       int extendedLengthLocation = lengthLocation + 4;\r
+                       System.arraycopy (bytes,\r
+                                                     extendedLengthLocation,\r
+                                                     bytes,\r
+                                                     extendedLengthLocation + extendedLengthByteCount,\r
+                                                     extendedLength);\r
+\r
+                       // write the extended length\r
+                       int shiftSize = (extendedLengthByteCount -1) * 8;\r
+                       for (int i = 0; i < extendedLengthByteCount; i++)\r
+                       {\r
+                               bytes[extendedLengthLocation++] =\r
+                                       (byte) ((extendedLength >>> shiftSize ) & 0xff);\r
+                               shiftSize -= 8;\r
+                       }\r
+\r
+                       // adjust the offset to account for the shift and insert\r
+                       offset += extendedLengthByteCount;\r
+\r
+                       // the two byte length field before the codepoint contains the length\r
+                       // of itself, the length of the codepoint, and the number of bytes used\r
+                       // to hold the extended length. the 2 byte length field also has the first\r
+                       // bit on to indicate extended length bytes were used.\r
+                       length = extendedLengthByteCount + 4;\r
+                       length |= DssConstants.CONTINUATION_BIT;\r
+               }\r
+\r
+               // write the 2 byte length field (2 bytes before codepoint).\r
+               bytes[lengthLocation] = (byte) ((length >>> 8) & 0xff);\r
+               bytes[lengthLocation+1] = (byte) (length & 0xff);\r
+\r
+       }\r
+\r
+    /**\r
+     * Get the length of the current DSS block we're working on. This is\r
+     * used by the LMTBLKPRC protocol, which does its own conversational\r
+     * blocking protocol above the layer of the DRDA blocking. The LMTBLKPRC\r
+     * implementation (in DRDAConnThread) needs to be able to truncate a\r
+     * DSS block when splitting a QRYDTA response.\r
+     *\r
+     * @return current DSS block length\r
+    */\r
+    protected int getDSSLength()\r
+    {\r
+        return offset - dssLengthLocation;\r
+    }\r
\r
+    /**\r
+     * Truncate the current DSS. Before making this call, you should ensure\r
+     * that you have copied the data to be truncated somewhere else, by\r
+     * calling copyDSSDataToEnd\r
+     *\r
+     * @param value DSS length\r
+    */\r
+    protected void truncateDSS(int value)\r
+    {\r
+        offset = dssLengthLocation + value;\r
+    }\r
+\r
+\r
+       // Write routines\r
+\r
+       /**\r
+        * Write byte\r
+        *\r
+        * @param       value   byte to be written\r
+        */\r
+       protected void writeByte (int value)\r
+       {\r
+               if (SanityManager.DEBUG)\r
+               {\r
+                       if (value > 255)\r
+                               SanityManager.THROWASSERT(\r
+                                                                          "writeByte value: " + value +\r
+                                                                          " may not be > 255");\r
+               }\r
+\r
+               ensureLength (1);\r
+               bytes[offset++] = (byte) (value & 0xff);\r
+       }\r
+\r
+\r
+       /**\r
+        * Write network short\r
+        *\r
+        * @param       value   value to be written\r
+        */\r
+       protected void writeNetworkShort (int value)\r
+       {\r
+               ensureLength (2);\r
+               bytes[offset] = (byte) ((value >>> 8) & 0xff);\r
+               bytes[offset + 1] = (byte) (value & 0xff);\r
+               offset += 2;\r
+       }\r
+\r
+       /**\r
+        * Write network int\r
+        *\r
+        * @param       value   value to be written\r
+        */\r
+       protected void writeNetworkInt (int value)\r
+       {\r
+               ensureLength (4);\r
+               bytes[offset] = (byte) ((value >>> 24) & 0xff);\r
+               bytes[offset + 1] = (byte) ((value >>> 16) & 0xff);\r
+               bytes[offset + 2] = (byte) ((value >>> 8) & 0xff);\r
+               bytes[offset + 3] = (byte) (value & 0xff);\r
+               offset += 4;\r
+       }\r
+\r
+\r
+       /**\r
+        * Write byte array\r
+        *\r
+        * @param       buf     byte array to be written\r
+        * @param       length  - length to write\r
+        */\r
+       protected void writeBytes (byte[] buf, int length)\r
+       {\r
+               writeBytes(buf, 0,length);\r
+       }\r
+\r
+\r
+\r
+       /**\r
+        * Write byte array\r
+        *\r
+        * @param       buf     byte array to be written\r
+        * @param       start  - starting position\r
+        * @param       length  - length to write\r
+        */\r
+       protected void writeBytes (byte[] buf, int start, int length)\r
+       {\r
+\r
+               if (SanityManager.DEBUG)\r
+               {\r
+                       if (buf == null && length > 0)\r
+                       SanityManager.THROWASSERT("Buf is null");\r
+                       if (length + start - 1 > buf.length)\r
+                       SanityManager.THROWASSERT("Not enough bytes in buffer");\r
+\r
+               }\r
+               ensureLength (length);\r
+               System.arraycopy(buf,start,bytes,offset,length);\r
+               offset += length;\r
+       }\r
+       /**\r
+        * Write byte array\r
+        *\r
+        * @param       buf     byte array to be written\r
+        **/\r
+       protected void writeBytes (byte[] buf)\r
+       {\r
+               writeBytes(buf,buf.length);\r
+       }\r
+\r
+\r
+\r
+       protected void writeLDBytes(byte[] buf)\r
+       {\r
+               writeLDBytes(buf, 0);\r
+       }\r
+\r
+       protected void writeLDBytes(byte[] buf, int index)\r
+       {\r
+\r
+               int length = buf.length;\r
+               int writeLen =  buf.length;\r
+\r
+               writeShort(writeLen);\r
+\r
+               writeBytes(buf,0,writeLen);\r
+       }\r
+\r
+\r
+       /**\r
+        * Write code point and 4 bytes\r
+        *\r
+        * @param       codePoint - code point to write\r
+        * @param       value  - value to write after code point\r
+        */\r
+       void writeCodePoint4Bytes (int codePoint, int value)\r
+       {\r
+               ensureLength (4);\r
+               bytes[offset] = (byte) ((codePoint >>> 8) & 0xff);\r
+               bytes[offset + 1] = (byte) (codePoint & 0xff);\r
+               bytes[offset + 2] = (byte) ((value >>> 8) & 0xff);\r
+               bytes[offset + 3] = (byte) (value & 0xff);\r
+               offset += 4;\r
+       }\r
+\r
+       /**\r
+        * Write scalar 1 byte object includes length, codepoint and value\r
+        *\r
+        * @param       codePoint - code point to write\r
+        * @param       value  - value to write after code point\r
+        */\r
+       void writeScalar1Byte (int codePoint, int value)\r
+       {\r
+               ensureLength (5);\r
+               bytes[offset] = 0x00;\r
+               bytes[offset + 1] = 0x05;\r
+               bytes[offset + 2] = (byte) ((codePoint >>> 8) & 0xff);\r
+               bytes[offset + 3] = (byte) (codePoint & 0xff);\r
+               bytes[offset + 4] = (byte) (value & 0xff);\r
+               offset += 5;\r
+       }\r
+\r
+       /**\r
+        * Write scalar 2 byte object includes length, codepoint and value\r
+        *\r
+        * @param       codePoint - code point to write\r
+        * @param       value  - value to write after code point\r
+        */\r
+       protected void writeScalar2Bytes (int codePoint, int value)\r
+       {\r
+               ensureLength (6);\r
+               bytes[offset] = 0x00;\r
+               bytes[offset + 1] = 0x06;\r
+               bytes[offset + 2] = (byte) ((codePoint >>> 8) & 0xff);\r
+               bytes[offset + 3] = (byte) (codePoint & 0xff);\r
+               bytes[offset + 4] = (byte) ((value >>> 8) & 0xff);\r
+               bytes[offset + 5] = (byte) (value & 0xff);\r
+               offset += 6;\r
+       }\r
+\r
+       protected void writeScalar2Bytes ( int value)\r
+       {\r
+               ensureLength (2);\r
+               bytes[offset] = (byte) ((value >>> 8) & 0xff);\r
+               bytes[offset + 1] = (byte) (value & 0xff);\r
+               offset += 2;\r
+       }\r
+\r
+       /**\r
+        * Write length and codepoint\r
+        *\r
+        * @param       length - length of object\r
+        * @param       codePoint - code point to write\r
+        */\r
+       protected void startDdm (int length, int codePoint)\r
+       {\r
+               ensureLength (4);\r
+               bytes[offset] = (byte) ((length >>> 8) & 0xff);\r
+               bytes[offset + 1] = (byte) (length & 0xff);\r
+               bytes[offset + 2] = (byte) ((codePoint >>> 8) & 0xff);\r
+               bytes[offset + 3] = (byte) (codePoint & 0xff);\r
+               offset += 4;\r
+       }\r
+\r
+       /**\r
+        * Write scalar byte array object includes length, codepoint and value\r
+        *\r
+        * @param       codePoint - code point to write\r
+        * @param       buf  - value to write after code point\r
+        * @param       length - number of bytes to write\r
+        */\r
+       protected void writeScalarBytes (int codePoint, byte[] buf, int length)\r
+       {\r
+               if (SanityManager.DEBUG)\r
+               {\r
+                       if (buf == null && length > 0)\r
+                       SanityManager.THROWASSERT("Buf is null");\r
+                       if (length > buf.length)\r
+                       SanityManager.THROWASSERT("Not enough bytes in buffer");\r
+               }\r
+               ensureLength (length + 4);\r
+               bytes[offset] = (byte) (((length+4) >>> 8) & 0xff);\r
+               bytes[offset + 1] = (byte) ((length+4) & 0xff);\r
+               bytes[offset + 2] = (byte) ((codePoint >>> 8) & 0xff);\r
+               bytes[offset + 3] = (byte) (codePoint & 0xff);\r
+               System.arraycopy(buf,0,bytes,offset + 4, length);\r
+               offset += length + 4;\r
+       }\r
+\r
+\r
+    \r
+    protected void writeScalarStream (boolean chainedWithSameCorrelator,\r
+                                                                         int codePoint,\r
+                                     EXTDTAInputStream in,\r
+                                                                         boolean writeNullByte) \r
+               throws DRDAProtocolException\r
+       {\r
+\r
+           \r
+\r
+               // Stream equivalent of "beginDss"...\r
+           int spareDssLength = prepScalarStream( chainedWithSameCorrelator,\r
+                                                                                       codePoint,\r
+                                                                                       writeNullByte);\r
+           \r
+               // write the data\r
+               int bytesRead = 0;\r
+               int totalBytesRead = 0;\r
+\r
+                               try {\r
+                                   \r
+               OutputStream out = \r
+                   placeLayerBStreamingBuffer( agent.getOutputStream() );\r
+               \r
+               boolean isLastSegment = false;\r
+               \r
+               while( !isLastSegment ){\r
+                   \r
+                   int spareBufferLength = bytes.length - offset;\r
+                   \r
+                   if( SanityManager.DEBUG ){\r
+               \r
+                       if( PropertyUtil.getSystemBoolean("derby.debug.suicideOfLayerBStreaming") )\r
+                           throw new IOException();\r
+                               }\r
+                   \r
+                   bytesRead = in.read(bytes,\r
+                                       offset,\r
+                                       Math.min(spareDssLength,\r
+                                                spareBufferLength));\r
+                   \r
+                                       totalBytesRead += bytesRead;\r
+                                       offset += bytesRead;\r
+                   spareDssLength -= bytesRead;\r
+                   spareBufferLength -= bytesRead;\r
+\r
+                   isLastSegment = peekStream(in) < 0;\r
+                   \r
+                   if(isLastSegment || \r
+                      spareDssLength == 0){\r
+                       \r
+                       flushScalarStreamSegment (isLastSegment, \r
+                                                 out);\r
+                       \r
+                       if( ! isLastSegment )\r
+                           spareDssLength = DssConstants.MAX_DSS_LENGTH - 2;\r
+\r
+                       }\r
+                   \r
+               }\r
+               \r
+               out.flush();\r
+               \r
+           }catch(IOException e){\r
+               agent.markCommunicationsFailure ("DDMWriter.writeScalarStream()",\r
+                                                "",\r
+                                                e.getMessage(),\r
+                                                "*");\r
+               }\r
+                               \r
+       }\r
+       \r
+       /**\r
+        * Begins a DSS stream (for writing LOB data).\r
+        */\r
+       private void beginDss (boolean chainedToNextStructure,\r
+                                                  int dssType)\r
+       {\r
+               beginDss(dssType, false);       // false => don't ensure length.\r
+\r
+               // always turn on continuation flags... this is helpful for lobs...\r
+               // these bytes will get rest if dss lengths are finalized.\r
+               bytes[dssLengthLocation] = (byte) 0xFF;\r
+               bytes[dssLengthLocation + 1] = (byte) 0xFF;\r
+\r
+               // Set whether or not this DSS should be chained to\r
+               // the next one.  If it's chained, it has to be chained\r
+               // with same id (that's the nature of EXTDTA chaining).\r
+               if (chainedToNextStructure) {\r
+                       dssType |= DssConstants.GDSCHAIN_SAME_ID;\r
+               }\r
+\r
+               bytes[dssLengthLocation + 3] = (byte) (dssType & 0xff);\r
+       }\r
+\r
+\r
+    /**\r
+     * prepScalarStream does the following prep for writing stream data:\r
+     * 1.  Flushes an existing DSS segment, if necessary\r
+     * 2.  Determines if extended length bytes are needed\r
+     * 3.  Creates a new DSS/DDM header and a null byte indicator, if applicable\r
+     *\r
+     * If value of length was less than 0, this method processes streaming as Layer B Streaming.\r
+     * cf. page 315 of specification of DRDA, Version 3, Volume 3 \r
+     *\r
+     */\r
+  private int prepScalarStream( boolean chainedWithSameCorrelator,\r
+                                   int codePoint,\r
+                                   boolean writeNullByte) throws DRDAProtocolException\r
+  {\r
+\r
+      ensureLength( DEFAULT_BUFFER_SIZE - offset );\r
+      \r
+      final int nullIndicatorSize = writeNullByte ? 1:0;\r
+\r
+    \r
+      // flush the existing DSS segment ,\r
+      // if this stream will not fit in the send buffer or \r
+      // length of this stream is unknown.\r
+      // Here, 10 stands for sum of headers of layer A and B.\r
+\r
+      try {\r
+           // The existing DSS segment was finalized by endDss; all\r
+           // we have to do is send it across the wire.\r
+        sendBytes(agent.getOutputStream());\r
+      }\r
+      catch (java.io.IOException e) {\r
+         agent.markCommunicationsFailure ("DDMWriter.writeScalarStream()",\r
+                                              "OutputStream.flush()",\r
+                                              e.getMessage(),"*");\r
+      }\r
+\r
+    // buildStreamDss should not call ensure length.\r
+       beginDss(chainedWithSameCorrelator, DssConstants.GDSFMT_OBJDSS);\r
+\r
+      writeLengthCodePoint(0x8004,codePoint);\r
+\r
+\r
+    // write the null byte, if necessary\r
+    if (writeNullByte)\r
+      writeByte(0x0);\r
+\r
+      //Here, 6 stands for header of layer A and \r
+      //4 stands for header of layer B.\r
+      return DssConstants.MAX_DSS_LENGTH - 6 - 4 - nullIndicatorSize;\r
+\r
+\r
+  }\r
+\r
+\r
+  // method to determine if any data is in the request.\r
+  // this indicates there is a dss object already in the buffer.\r
+       protected boolean doesRequestContainData()\r
+       {\r
+               return offset != 0;\r
+       }\r
+\r
+\r
+       // Writes out a scalar stream DSS segment, along with DSS continuation\r
+       // headers if necessary.\r
+       private void flushScalarStreamSegment ( boolean lastSegment,\r
+                                               OutputStream out)\r
+               throws DRDAProtocolException\r
+       {\r
+\r
+               // either at end of data, end of dss segment, or both.\r
+           if (! lastSegment) {\r
+\r
+               // 32k segment filled and not at end of data.\r
+                               try {\r
+                               // Mark current DSS as continued, set its chaining state,\r
+                               // then send the data across.\r
+                                       markDssAsContinued(true);       // true => for lobs\r
+                                       sendBytes (out,\r
+                                                  false);\r
+                           \r
+                       }catch (java.io.IOException ioe) {\r
+                                       agent.markCommunicationsFailure ("DDMWriter.flushScalarStreamSegment()",\r
+                                               "",\r
+                                               ioe.getMessage(),\r
+                                               "*");\r
+                               }\r
+\r
+\r
+                       // Prepare a DSS continuation header for next DSS.\r
+                       dssLengthLocation = offset;\r
+                       bytes[offset++] = (byte) (0xff);\r
+                       bytes[offset++] = (byte) (0xff);\r
+                       isContinuationDss = true;\r
+           }else{\r
+               // we're done writing the data, so end the DSS.\r
+                       endDss();\r
+\r
+       }\r
+\r
+  }\r
+\r
+\r
+       private void writeExtendedLengthBytes (int extendedLengthByteCount, long length)\r
+       {\r
+       int shiftSize = (extendedLengthByteCount -1) * 8;\r
+    for (int i = 0; i < extendedLengthByteCount; i++) {\r
+      bytes[offset + i] = (byte) ((length >>> shiftSize) & 0xff);\r
+      shiftSize -= 8;\r
+    }\r
+       offset += extendedLengthByteCount;\r
+  }\r
+\r
+\r
+  // insert a 4 byte length/codepoint pair into the buffer.\r
+  // total of 4 bytes inserted in buffer.\r
+  // Note: the length value inserted in the buffer is the same as the value\r
+  // passed in as an argument (this value is NOT incremented by 4 before being\r
+  // inserted).\r
+  void writeLengthCodePoint (int length, int codePoint)\r
+  {\r
+    ensureLength (4);\r
+    bytes[offset] = (byte) ((length >>> 8) & 0xff);\r
+    bytes[offset + 1] = (byte) (length & 0xff);\r
+    bytes[offset + 2] = (byte) ((codePoint >>> 8) & 0xff);\r
+    bytes[offset + 3] = (byte) (codePoint & 0xff);\r
+       offset +=4;\r
+  }\r
+\r
+       /**\r
+        * Write scalar object header includes length and codepoint\r
+        *\r
+        * @param       codePoint - code point to write\r
+        * @param       dataLength - length of object data\r
+        */\r
+       protected void writeScalarHeader (int codePoint, int dataLength)\r
+       {\r
+               ensureLength (dataLength + 4);\r
+               bytes[offset] = (byte) (((dataLength+4) >>> 8) & 0xff);\r
+               bytes[offset + 1] = (byte) ((dataLength+4) & 0xff);\r
+               bytes[offset + 2] = (byte) ((codePoint >>> 8) & 0xff);\r
+               bytes[offset + 3] = (byte) (codePoint & 0xff);\r
+               offset += 4;\r
+       }\r
+\r
+       /**\r
+        * Write scalar string object includes length, codepoint and value\r
+        * the string is converted into the appropriate codeset (EBCDIC)\r
+        *\r
+        * @param       codePoint - code point to write\r
+        * @param       string - string to be written\r
+        */\r
+       void writeScalarString (int codePoint, String string)\r
+       {\r
+               int stringLength = string.length();\r
+               ensureLength ((stringLength * 2)  + 4);\r
+               bytes[offset] = (byte) (((stringLength+4) >>> 8) & 0xff);\r
+               bytes[offset + 1] = (byte) ((stringLength+4) & 0xff);\r
+               bytes[offset + 2] = (byte) ((codePoint >>> 8) & 0xff);\r
+               bytes[offset + 3] = (byte) (codePoint & 0xff);\r
+               offset = ccsidManager.convertFromUCS2 (string, bytes, offset + 4);\r
+       }\r
+\r
+       /**\r
+        * Write padded scalar string object includes length, codepoint and value\r
+        * the string is converted into the appropriate codeset (EBCDIC)\r
+        *\r
+        * @param       codePoint - code point to write\r
+        * @param       string - string to be written\r
+        * @param       paddedLength - length to pad string to\r
+        */\r
+       void writeScalarPaddedString (int codePoint, String string, int paddedLength)\r
+       {\r
+               int stringLength = string.length();\r
+               int fillLength = paddedLength - stringLength;\r
+               ensureLength (paddedLength + 4);\r
+               bytes[offset] = (byte) (((paddedLength+4) >>> 8) & 0xff);\r
+               bytes[offset + 1] = (byte) ((paddedLength+4) & 0xff);\r
+               bytes[offset + 2] = (byte) ((codePoint >>> 8) & 0xff);\r
+               bytes[offset + 3] = (byte) (codePoint & 0xff);\r
+               offset = ccsidManager.convertFromUCS2 (string, bytes, offset + 4);\r
+               Arrays.fill(bytes,offset, offset + fillLength,ccsidManager.space);\r
+               offset += fillLength;\r
+       }\r
+\r
+       /**\r
+        * Write padded scalar string object value\r
+        * the string is converted into the appropriate codeset (EBCDIC)\r
+        *\r
+        * @param       string - string to be written\r
+        * @param       paddedLength - length to pad string to\r
+        */\r
+       protected void writeScalarPaddedString (String string, int paddedLength)\r
+       {\r
+               int stringLength = string.length();\r
+\r
+               int fillLength = paddedLength -stringLength;\r
+               ensureLength (paddedLength);\r
+               offset = ccsidManager.convertFromUCS2 (string, bytes, offset);\r
+               Arrays.fill(bytes,offset, offset + fillLength,ccsidManager.space);\r
+               offset += fillLength;\r
+       }\r
+\r
+       /**\r
+        * Write padded scalar <code>DRDAString</code> object value. The\r
+        * string is converted into the appropriate codeset.\r
+        *\r
+        * @param drdaString string to be written\r
+        * @param paddedLength length to pad string to\r
+        */\r
+       protected void writeScalarPaddedString (DRDAString drdaString, int paddedLength)\r
+       {\r
+               int stringLength = drdaString.length();\r
+               int fillLength = paddedLength - stringLength;\r
+               ensureLength(paddedLength);\r
+               System.arraycopy(drdaString.getBytes(), 0, bytes, offset, stringLength);\r
+               offset += stringLength;\r
+               Arrays.fill(bytes, offset, offset + fillLength, ccsidManager.space);\r
+               offset += fillLength;\r
+       }\r
+\r
+       /**\r
+        * Write padded scalar byte array object includes length, codepoint and value\r
+        *\r
+        * @param       codePoint - code point to write\r
+        * @param       buf - byte array to be written\r
+        * @param       paddedLength - length to pad string to\r
+        * @param       padByte - byte to be used for padding\r
+        */\r
+       protected void writeScalarPaddedBytes (int codePoint, byte[] buf, int paddedLength, byte padByte)\r
+       {\r
+               int bufLength = buf.length;\r
+               ensureLength (paddedLength + 4);\r
+               bytes[offset] = (byte) (((paddedLength+4) >>> 8) & 0xff);\r
+               bytes[offset + 1] = (byte) ((paddedLength+4) & 0xff);\r
+               bytes[offset + 2] = (byte) ((codePoint >>> 8) & 0xff);\r
+               bytes[offset + 3] = (byte) (codePoint & 0xff);\r
+               offset += 4;\r
+               System.arraycopy(buf,0,bytes,offset,bufLength);\r
+               offset += bufLength;\r
+               int fillLength = paddedLength - bufLength;\r
+               Arrays.fill(bytes,offset,offset + fillLength,padByte);\r
+               offset += fillLength;\r
+       }\r
+\r
+       /**\r
+        * Write padded scalar byte array object  value\r
+        *\r
+        * @param       buf - byte array to be written\r
+        * @param       paddedLength - length to pad string to\r
+        * @param       padByte - byte to be used for padding\r
+        */\r
+       protected void writeScalarPaddedBytes (byte[] buf, int paddedLength, byte padByte)\r
+       {\r
+               int bufLength = buf.length;\r
+               int fillLength = paddedLength - bufLength;\r
+               ensureLength (paddedLength);\r
+               System.arraycopy(buf,0,bytes,offset,bufLength);\r
+               offset +=bufLength;\r
+               Arrays.fill(bytes,offset,offset + fillLength,padByte);\r
+               offset += fillLength;\r
+       }\r
+\r
+       /**\r
+        * Write scalar byte array object includes length, codepoint and value\r
+        *\r
+        * @param       codePoint - code point to write\r
+        * @param       buf - byte array to be written\r
+        */\r
+       protected void writeScalarBytes (int codePoint, byte[] buf)\r
+       {\r
+               int bufLength = buf.length;\r
+               ensureLength (bufLength + 4);\r
+               bytes[offset] = (byte) (((bufLength+4) >>> 8) & 0xff);\r
+               bytes[offset + 1] = (byte) ((bufLength+4) & 0xff);\r
+               bytes[offset + 2] = (byte) ((codePoint >>> 8) & 0xff);\r
+               bytes[offset + 3] = (byte) (codePoint & 0xff);\r
+               System.arraycopy(buf,0,bytes,offset + 4,bufLength);\r
+               offset += bufLength + 4;\r
+       }\r
+\r
+       /**\r
+        * Write scalar byte array object includes length, codepoint and value\r
+        *\r
+        * @param       codePoint - code point to write\r
+        * @param       buf - byte array to be written\r
+        * @param       start - starting point\r
+        * @param       length - length to write\r
+        */\r
+       protected void writeScalarBytes (int codePoint, byte[] buf, int start, int length)\r
+       {\r
+               if (SanityManager.DEBUG)\r
+               {\r
+                       if (buf == null && length > start)\r
+                       SanityManager.THROWASSERT("Buf is null");\r
+                       if (length - start > buf.length)\r
+                               SanityManager.THROWASSERT("Not enough bytes in buffer");\r
+               }\r
+               int numBytes = length - start;\r
+               ensureLength (numBytes + 4);\r
+               bytes[offset] = (byte) (((numBytes+4) >>> 8) & 0xff);\r
+               bytes[offset + 1] = (byte) ((numBytes+4) & 0xff);\r
+               bytes[offset + 2] = (byte) ((codePoint >>> 8) & 0xff);\r
+               bytes[offset + 3] = (byte) (codePoint & 0xff);\r
+               offset += 4;\r
+               System.arraycopy(buf,start,bytes,offset,numBytes);\r
+               offset += numBytes;\r
+       }\r
+       // The following methods write data in the platform format\r
+       // The platform format was indicated during connection time as ASC since\r
+       // JCC doesn't read JVM platform (yet)\r
+\r
+       /**\r
+        * Write platform short\r
+        *\r
+        * @param       v       value to be written\r
+        */\r
+       protected void writeShort (int v)\r
+       {\r
+               writeNetworkShort(v);\r
+       }\r
+\r
+       /**\r
+        * Write boolean as short\r
+        * @param b boolean value true = 1 false = 0\r
+        *\r
+        */\r
+       protected void writeShort(boolean b)\r
+       {\r
+               writeNetworkShort(b ? 1 : 0);\r
+       }\r
+\r
+       /**\r
+        * Write platform int\r
+        *\r
+        * @param       v       value to be written\r
+        */\r
+       protected void writeInt (int v)\r
+       {\r
+               writeNetworkInt(v);\r
+       }\r
+\r
+       /**\r
+        * Write platform long\r
+        *\r
+        * @param       v       value to be written\r
+        */\r
+       protected void writeLong (long v)\r
+       {\r
+               ensureLength (8);\r
+               bytes[offset] = (byte) ((v >>> 56) & 0xff);\r
+               bytes[offset + 1] =     (byte) ((v >>> 48) & 0xff);\r
+               bytes[offset + 2] =     (byte) ((v >>> 40) & 0xff);\r
+               bytes[offset + 3] =     (byte) ((v >>> 32) & 0xff);\r
+               bytes[offset + 4] =     (byte) ((v >>> 24) & 0xff);\r
+               bytes[offset + 5] =     (byte) ((v >>> 16) & 0xff);\r
+               bytes[offset + 6] =     (byte) ((v >>>  8) & 0xff);\r
+               bytes[offset + 7] =     (byte) ((v >>>  0) & 0xff);\r
+               offset += 8;\r
+       }\r
+\r
+       /**\r
+        * Write platform float\r
+        *\r
+        * @param       v       value to be written\r
+        */\r
+       protected void writeFloat (float v)\r
+       {\r
+               writeInt (Float.floatToIntBits (v));\r
+       }\r
+\r
+       /**\r
+        * Write platform double\r
+        *\r
+        * @param       v       value to be written\r
+        */\r
+       protected void writeDouble (double v)\r
+       {\r
+               writeLong (Double.doubleToLongBits (v));\r
+       }\r
+\r
+       /**\r
+        * Write big decimal to buffer\r
+        *\r
+        * @param v value to write\r
+        * @param precision Precison of decimal or numeric type\r
+        * @param scale declared scale\r
+        * @exception SQLException thrown if number of digits > 31\r
+        */\r
+       protected void writeBigDecimal (java.math.BigDecimal v, int precision, int scale)\r
+               throws SQLException\r
+       {\r
+               int length = precision / 2 + 1;\r
+               ensureLength (offset + length);\r
+               bigDecimalToPackedDecimalBytes (v,precision, scale);\r
+               offset += length;\r
+       }\r
+\r
+       /**\r
+        * Write platform boolean\r
+        *\r
+        * @param       v       value to be written\r
+        */\r
+       protected void writeBoolean (boolean v)\r
+       {\r
+               ensureLength (1);\r
+               bytes[offset++] = (byte) ((v ? 1 : 0) & 0xff);\r
+       }\r
+\r
+       /**\r
+        * Write length delimited string\r
+        *\r
+        * @param s value to be written with integer\r
+        *\r
+        * @exception DRDAProtocolException\r
+        */\r
+       protected void writeLDString(String s) throws DRDAProtocolException\r
+       {\r
+               writeLDString(s,0);\r
+       }\r
+\r
+\r
+       /**\r
+        * Write length delimited string\r
+        *\r
+        * @param s              value to be written with integer\r
+        * @param index          column index to put in warning\r
+        * @exception DRDAProtocolException\r
+        */\r
+       protected void writeLDString(String s, int index) throws DRDAProtocolException\r
+       {\r
+               try {\r
+                       byte [] byteval = s.getBytes(NetworkServerControlImpl.DEFAULT_ENCODING);\r
+                       int origLen = byteval.length;\r
+                       int writeLen =\r
+                               java.lang.Math.min(FdocaConstants.LONGVARCHAR_MAX_LEN,\r
+                                                                  origLen);\r
+                       /*\r
+                       Need to make sure we truncate on character boundaries.\r
+                       We are assuming\r
+                       http://www.sun.com/developers/gadc/technicalpublications/articles/utf8.html\r
+                       To find the beginning of a multibyte character:\r
+                       1) Does the current byte start with the bit pattern 10xxxxxx?\r
+                       2) If yes, move left and go to step #1.\r
+                       3) Finished\r
+                       We assume that NetworkServerControlImpl.DEFAULT_ENCODING remains UTF-8\r
+                       */\r
+\r
+                       if (SanityManager.DEBUG)\r
+                       {\r
+                               if (!(NetworkServerControlImpl.DEFAULT_ENCODING.equals("UTF8")))\r
+                                       SanityManager.THROWASSERT("Encoding assumed to be UTF8, but is actually" + NetworkServerControlImpl.DEFAULT_ENCODING);\r
+                       }\r
+\r
+                       if (writeLen != origLen) {\r
+                               //find the first byte of the multibyte char in case\r
+                               //the last byte is part of a multibyte char\r
+                               while (isContinuationChar (byteval [writeLen])) {\r
+                                       writeLen--;\r
+                               }\r
+                               //\r
+                               // Now byteval[ writeLen ] is either a standalone 1-byte char\r
+                               // or the first byte of a multi-byte character. That means that\r
+                               // byteval[ writeLen -1 ] is the last (perhaps only) byte of the\r
+                               // previous character.\r
+                               //\r
+                       }\r
+                        \r
+\r
+                       writeShort(writeLen);\r
+                       writeBytes(byteval,writeLen);\r
+               }\r
+               catch (UnsupportedEncodingException e) {\r
+                       //this should never happen\r
+                       agent.agentError("Encoding " + NetworkServerControlImpl.DEFAULT_ENCODING + " not supported");\r
+               }\r
+       }\r
+       private boolean isContinuationChar( byte b ) {    \r
+               return ( (b & MULTI_BYTE_MASK) == CONTINUATION_BYTE );\r
+       }\r
+\r
+       /**\r
+        * Write string with default encoding\r
+        *\r
+        * @param s value to be written\r
+        *\r
+        * @exception DRDAProtocolException\r
+        */\r
+       protected void writeString(String s) throws DRDAProtocolException\r
+       {\r
+               try {\r
+                       writeBytes(s.getBytes(NetworkServerControlImpl.DEFAULT_ENCODING));\r
+               } catch (UnsupportedEncodingException e) {\r
+                       //this should never happen\r
+                       agent.agentError("Encoding " + NetworkServerControlImpl.DEFAULT_ENCODING + " not supported");\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Write string with default encoding and specified length\r
+        *\r
+        * @param s value to be written\r
+        * @param length number of bytes to be written\r
+        *\r
+        * @exception DRDAProtocolException\r
+        */\r
+       protected void writeString(String s, int length) throws DRDAProtocolException\r
+       {\r
+               byte[] bs = null;\r
+               try {\r
+                       bs = s.getBytes(NetworkServerControlImpl.DEFAULT_ENCODING);\r
+               } catch (UnsupportedEncodingException e) {\r
+                       //this should never happen\r
+                       agent.agentError("Encoding " + NetworkServerControlImpl.DEFAULT_ENCODING + " not supported");\r
+               }\r
+               int len = bs.length;\r
+               if (len >= length)\r
+                       writeBytes(bs, length);\r
+               else\r
+               {\r
+                       writeBytes(bs);\r
+                       padBytes(NetworkServerControlImpl.SPACE_CHAR, length-len);\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Write pad bytes using spaceChar\r
+        *\r
+        * @param   val value to be written\r
+        * @param       length          length to be written\r
+        */\r
+       protected void padBytes (byte val, int length)\r
+       {\r
+               Arrays.fill(bytes,offset, offset + length,val);\r
+               offset += length;\r
+       }\r
+\r
+       /**\r
+        * Flush buffer to outputstream\r
+        *\r
+        *\r
+        * @exception IOException\r
+        */\r
+       protected void flush () throws java.io.IOException\r
+       {\r
+               flush(agent.getOutputStream());\r
+       }\r
+\r
+       /**\r
+        * Flush buffer to specified stream\r
+        *\r
+        * @param socketOutputStream\r
+        *\r
+        * @exception IOException\r
+        */\r
+       protected void flush(OutputStream socketOutputStream)\r
+               throws java.io.IOException\r
+       {\r
+               try {\r
+                       socketOutputStream.write (bytes, 0, offset);\r
+                       socketOutputStream.flush();\r
+               }\r
+               finally {\r
+                       if ((dssTrace != null) && dssTrace.isComBufferTraceOn()) {\r
+                         dssTrace.writeComBufferData (bytes,\r
+                                                      0,\r
+                                                      offset,\r
+                                                      DssTrace.TYPE_TRACE_SEND,\r
+                                                      "Reply",\r
+                                                      "flush",\r
+                                                      5);\r
+                       }\r
+                       reset(dssTrace);\r
+               }\r
+       }\r
+\r
+       // private methods\r
+\r
+       /**\r
+        * Write 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
+        */\r
+       private void beginDss (int dssType, boolean ensureLen)\r
+       {\r
+\r
+               // save length position, the length will be written at the end\r
+               dssLengthLocation = offset;\r
+\r
+               // Should this really only be for non-stream DSSes?\r
+               if (ensureLen)\r
+                       ensureLength(6);\r
+\r
+               // Skip past length; we'll come back and set it later.\r
+               offset += 2;\r
+\r
+               // write gds info\r
+               bytes[offset] = (byte) 0xD0;\r
+\r
+               // Write DSS type, and default chain bit to be \r
+               // DssConstants.DSSCHAIN_SAME_ID.  This default\r
+               // will be overridden by calls to "finalizeChain()"\r
+               // and/or calls to "beginDss(boolean, int)" for\r
+               // writing LOB data.\r
+               bytes[offset + 1] = (byte) dssType;\r
+               bytes[offset + 1] |= DssConstants.DSSCHAIN_SAME_ID;\r
+\r
+               // save correlationID for use in error messages while processing\r
+               // this DSS\r
+               correlationID = getCorrelationID();\r
+\r
+               // write the reply correlation id\r
+               bytes[offset + 2] = (byte) ((correlationID >>> 8) & 0xff);\r
+               bytes[offset + 3] = (byte) (correlationID & 0xff);\r
+               offset += 4;\r
+       }\r
+\r
+       /**\r
+     * Finish a DSS Layer A object.\r
+        * The length of dss object will be calculated based on the difference between the\r
+        * start of the dss, saved on the beginDss call, and the current\r
+        * offset into the buffer which marks the end of the data.      In the event\r
+        * the length requires the use of continuation Dss headers, one for each 32k\r
+        * chunk of data, the data will be shifted and the continuation headers\r
+        * will be inserted with the correct values as needed.\r
+        */\r
+       private void finalizeDssLength ()\r
+       {\r
+               // calculate the total size of the dss and the number of bytes which would\r
+               // require continuation dss headers.    The total length already includes the\r
+               // the 6 byte dss header located at the beginning of the dss.   It does not\r
+               // include the length of any continuation headers.\r
+               int totalSize = offset - dssLengthLocation;\r
+               int bytesRequiringContDssHeader = totalSize - DssConstants.MAX_DSS_LENGTH;\r
+\r
+               // determine if continuation headers are needed\r
+               if (bytesRequiringContDssHeader > 0)\r
+               {\r
+                       // the continuation headers are needed, so calculate how many.\r
+                       // after the first 32767 worth of data, a continuation header is\r
+                       // needed for every 32765 bytes (32765 bytes of data + 2 bytes of\r
+                       // continuation header = 32767 Dss Max Size).\r
+                       int contDssHeaderCount = bytesRequiringContDssHeader / 32765;\r
+                       if (bytesRequiringContDssHeader % 32765 != 0)\r
+                               contDssHeaderCount++;\r
+\r
+                       // right now the code will shift to the right.  In the future we may want\r
+                       // to try something fancier to help reduce the copying (maybe keep\r
+                       // space in the beginning of the buffer??).\r
+                       // the offset points to the next available offset in the buffer to place\r
+                       // a piece of data, so the last dataByte is at offset -1.\r
+                       // various bytes will need to be shifted by different amounts\r
+                       // depending on how many dss headers to insert so the amount to shift\r
+                       // will be calculated and adjusted as needed.   ensure there is enough room\r
+                       // for all the conutinuation headers and adjust the offset to point to the\r
+                       // new end of the data.\r
+                       int dataByte = offset - 1;\r
+                       int shiftSize = contDssHeaderCount * 2;\r
+                       ensureLength (shiftSize);\r
+                       offset += shiftSize;\r
+\r
+                       // Notes on the behavior of the Layer B segmenting loop below:\r
+                       //\r
+                       // We start with the right most chunk. For a 3-segment object we'd\r
+                       // shift 2 segments: shift the first (rightmost) one 4 bytes and \r
+                       // the second one 2. Note that by 'first' we mean 'first time\r
+                       // through the loop', but that is actually the last segment\r
+                       // of data since we are moving right-to-left. For an object\r
+                       // of K segments we will pass through this loop K-1 times.\r
+                       // The 0th (leftmost) segment is not shifted, as it is\r
+                       // already in the right place. When we are done, we will\r
+                       // have made room in each segment for an additional\r
+                       // 2 bytes for the continuation header. Thus, each\r
+                       // segment K is shifted K*2 bytes to the right.\r
+                       //\r
+                       // Each time through the loop, "dataByte" points to the\r
+                       // last byte in the segment; "dataToShift" is the amount of\r
+                       // data that we need to shift, and "shiftSize" is the\r
+                       // distance that we need to shift it. Since dataByte points\r
+                       // at the last byte, not one byte beyond it (as with the\r
+                       // "offset" variable used elsewhere in DDMWriter), the start\r
+                       // of the segement is actually at (dataByte-dataToShift+1).\r
+                       //\r
+                       // After we have shifted the segment, we move back to the\r
+                       // start of the segment and set the value of the 2-byte DSS\r
+                       // continuation header, which needs to hold the length of\r
+                       // this segment's data, together with the continuation flag\r
+                       // if this is not the rightmost (passOne) segment.\r
+                       //\r
+                       // In general, each segment except the rightmost will contain\r
+                       // 32765 bytes of data, plus the 2-byte header, and its\r
+                       // continuation flag will be set, so the header value will\r
+                       // be 0xFFFF. The rightmost segment will not have the\r
+                       // continuation flag set, so its value may be anything from\r
+                       // 0x0001 to 0x7FFF, depending on the amount of data in that\r
+                       // segment.\r
+                       //\r
+                       // Note that the 0th (leftmost) segment also has a 2-byte\r
+                       // DSS header, which needs to have its continuation flag set.\r
+                       // This is done by resetting the "totalSize" variable below,\r
+                       // at which point that variable no longer holds the total size\r
+                       // of the object, but rather just the length of segment 0. The\r
+                       // total size of the object was written using extended length\r
+                       // bytes by the endDdm() method earlier.\r
+                       //\r
+                       // Additional information about this routine is available in the\r
+                       // bug notes for DERBY-125:\r
+                       // http://issues.apache.org/jira/browse/DERBY-125\r
+                       \r
+                       // mark passOne to help with calculating the length of the final (first or\r
+                       // rightmost) continuation header.\r
+                       boolean passOne = true;\r
+                       do {\r
+                               // calculate chunk of data to shift\r
+                               int dataToShift = bytesRequiringContDssHeader % 32765;\r
+                               if (dataToShift == 0)\r
+                                       dataToShift = 32765;\r
+                               int startOfCopyData = dataByte - dataToShift + 1;\r
+                               System.arraycopy(bytes,startOfCopyData, bytes, \r
+                                                                startOfCopyData + shiftSize, dataToShift);\r
+                               dataByte -= dataToShift;\r
+\r
+\r
+                               // calculate the value the value of the 2 byte continuation dss\r
+                               // header which includes the length of itself.  On the first pass,\r
+                               // if the length is 32767\r
+                               // we do not want to set the continuation dss header flag.\r
+                               int twoByteContDssHeader = dataToShift + 2;\r
+                               if (passOne)\r
+                                       passOne = false;\r
+                               else\r
+                               {\r
+                                       if (twoByteContDssHeader == DssConstants.MAX_DSS_LENGTH)\r
+                                       twoByteContDssHeader = (twoByteContDssHeader |\r
+                                               DssConstants.CONTINUATION_BIT);\r
+\r
+                               }\r
+\r
+                               // insert the header's length bytes\r
+                               bytes[dataByte + shiftSize - 1] = (byte)\r
+                                       ((twoByteContDssHeader >>> 8) & 0xff);\r
+                               bytes[dataByte + shiftSize] = (byte)\r
+                                       (twoByteContDssHeader & 0xff);\r
+\r
+                               // adjust the bytesRequiringContDssHeader and the amount to shift for\r
+                               // data in upstream headers.\r
+                               bytesRequiringContDssHeader -= dataToShift;\r
+                               shiftSize -= 2;\r
+\r
+                               // shift and insert another header for more data.\r
+                       }\r
+                       while (bytesRequiringContDssHeader > 0);\r
+\r
+                       // set the continuation dss header flag on for the first header\r
+                       totalSize = (DssConstants.MAX_DSS_LENGTH |\r
+                                       DssConstants.CONTINUATION_BIT);\r
+\r
+\r
+               }\r
+\r
+               // insert the length bytes in the 6 byte dss header.\r
+               bytes[dssLengthLocation] = (byte) ((totalSize >>> 8) & 0xff);\r
+               bytes[dssLengthLocation + 1] = (byte) (totalSize & 0xff);\r
+       }\r
+\r
+       protected void writeExtendedLength(long size)\r
+       {\r
+               int numbytes = calculateExtendedLengthByteCount(size);\r
+               if (size > 0)\r
+                       writeInt(0x8000 | numbytes);\r
+               else\r
+                       writeInt(numbytes);\r
+       }\r
+\r
+\r
+       /**\r
+        * Calculate extended length byte count which follows the DSS header\r
+        * for extended DDM.\r
+        *\r
+        * @param ddmSize - size of DDM command\r
+        * @return minimum number of extended length bytes needed. 0 indicates no\r
+        *      extended length needed.\r
+        */\r
+       private int calculateExtendedLengthByteCount (long ddmSize)\r
+       {\r
+               if (ddmSize <= 0x7fff)\r
+                       return 0;\r
+               // JCC does not support 2 at this time, so we always send\r
+               // at least 4\r
+               //              else if (ddmSize <= 0xffff)\r
+               //      return 2;\r
+               else if (ddmSize <= 0xffffffffL)\r
+                       return 4;\r
+               else if (ddmSize <= 0xffffffffffffL)\r
+                       return 6;\r
+               else if (ddmSize <= 0x7fffffffffffffffL)\r
+                       return 8;\r
+               else\r
+                       // shouldn't happen\r
+                       // XXX - add sanity debug stuff here\r
+                       return 0;\r
+       }\r
+\r
+       /**\r
+        * Ensure that there is space in the buffer\r
+        *\r
+        * @param length space required\r
+        */\r
+       private void ensureLength (int length)\r
+       {\r
+               length += offset;\r
+               if (length > bytes.length) {\r
+                       if (SanityManager.DEBUG)\r
+                       {\r
+                               agent.trace("DANGER - Expensive expansion of  buffer");\r
+                       }\r
+                       byte newBytes[] = new byte[Math.max (bytes.length << 1, length)];\r
+                       System.arraycopy (bytes, 0, newBytes, 0, offset);\r
+                       bytes = newBytes;\r
+               }\r
+       }\r
+\r
+\r
+       /**\r
+        * Write a Java <code>java.math.BigDecimal</code> to packed decimal bytes.\r
+        *\r
+        * @param b BigDecimal to write\r
+        * @param precision Precision of decimal or numeric type\r
+        * @return length written.\r
+        *\r
+        * @exception SQLException Thrown if # digits > 31\r
+        */\r
+       private int bigDecimalToPackedDecimalBytes (java.math.BigDecimal b,\r
+                                                                                               int precision, int scale)\r
+       throws SQLException\r
+       {\r
+               int declaredPrecision = precision;\r
+               int declaredScale = scale;\r
+\r
+               // packed decimal may only be up to 31 digits.\r
+               if (declaredPrecision > 31) // this is a bugcheck only !!!\r
+               {\r
+                       clearDdm ();\r
+                       throw new java.sql.SQLException ("Packed decimal may only be up to 31 digits!");\r
+               }\r
+\r
+               // get absolute unscaled value of the BigDecimal as a String.\r
+               String unscaledStr = b.unscaledValue().abs().toString();\r
+\r
+               // get precision of the BigDecimal.\r
+           int bigPrecision = unscaledStr.length();\r
+\r
+               if (bigPrecision > 31)\r
+               {\r
+                       clearDdm ();\r
+                   throw new SQLException ("The numeric literal \"" +\r
+                             b.toString() +\r
+                             "\" is not valid because its value is out of range.",\r
+                             "42820",\r
+                             -405);\r
+               }\r
+       int bigScale = b.scale();\r
+           int bigWholeIntegerLength = bigPrecision - bigScale;\r
+           if ( (bigWholeIntegerLength > 0) && (!unscaledStr.equals ("0")) ) {\r
+            // if whole integer part exists, check if overflow.\r
+            int declaredWholeIntegerLength = declaredPrecision - declaredScale;\r
+            if (bigWholeIntegerLength > declaredWholeIntegerLength)\r
+                       {\r
+                               clearDdm ();\r
+                throw new SQLException ("Overflow occurred during numeric data type conversion of \"" +\r
+                                       b.toString() +\r
+                                       "\".",\r
+                                       "22003",\r
+                                       -413);\r
+                       }\r
+        }\r
+\r
+        // convert the unscaled value to a packed decimal bytes.\r
+\r
+        // get unicode '0' value.\r
+        int zeroBase = '0';\r
+\r
+        // start index in target packed decimal.\r
+        int packedIndex = declaredPrecision-1;\r
+\r
+        // start index in source big decimal.\r
+        int bigIndex;\r
+\r
+        if (bigScale >= declaredScale) {\r
+          // If target scale is less than source scale,\r
+          // discard excessive fraction.\r
+\r
+          // set start index in source big decimal to ignore excessive fraction.\r
+          bigIndex = bigPrecision-1-(bigScale-declaredScale);\r
+\r
+          if (bigIndex < 0) {\r
+            // all digits are discarded, so only process the sign nybble.\r
+            bytes[offset+(packedIndex+1)/2] =\r
+              (byte) ( (b.signum()>=0)?12:13 ); // sign nybble\r
+          }\r
+          else {\r
+            // process the last nybble together with the sign nybble.\r
+            bytes[offset+(packedIndex+1)/2] =\r
+              (byte) ( ( (unscaledStr.charAt(bigIndex)-zeroBase) << 4 ) + // last nybble\r
+                     ( (b.signum()>=0)?12:13 ) ); // sign nybble\r
+          }\r
+          packedIndex-=2;\r
+          bigIndex-=2;\r
+        }\r
+        else {\r
+          // If target scale is greater than source scale,\r
+          // pad the fraction with zero.\r
+\r
+          // set start index in source big decimal to pad fraction with zero.\r
+          bigIndex = declaredScale-bigScale-1;\r
+\r
+          // process the sign nybble.\r
+          bytes[offset+(packedIndex+1)/2] =\r
+            (byte) ( (b.signum()>=0)?12:13 ); // sign nybble\r
+\r
+          for (packedIndex-=2, bigIndex-=2; bigIndex>=0; packedIndex-=2, bigIndex-=2)\r
+            bytes[offset+(packedIndex+1)/2] = (byte) 0;\r
+\r
+          if (bigIndex == -1) {\r
+            bytes[offset+(packedIndex+1)/2] =\r
+              (byte) ( (unscaledStr.charAt(bigPrecision-1)-zeroBase) << 4 ); // high nybble\r
+\r
+            packedIndex-=2;\r
+            bigIndex = bigPrecision-3;\r
+          }\r
+          else {\r
+            bigIndex = bigPrecision-2;\r
+          }\r
+        }\r
+\r
+        // process the rest.\r
+        for (; bigIndex>=0; packedIndex-=2, bigIndex-=2) {\r
+          bytes[offset+(packedIndex+1)/2] =\r
+            (byte) ( ( (unscaledStr.charAt(bigIndex)-zeroBase) << 4 ) + // high nybble\r
+                   ( unscaledStr.charAt(bigIndex+1)-zeroBase ) ); // low nybble\r
+        }\r
+\r
+        // process the first nybble when there is one left.\r
+        if (bigIndex == -1) {\r
+          bytes[offset+(packedIndex+1)/2] =\r
+            (byte) (unscaledStr.charAt(0) - zeroBase);\r
+\r
+          packedIndex-=2;\r
+        }\r
+\r
+        // pad zero in front of the big decimal if necessary.\r
+        for (; packedIndex>=-1; packedIndex-=2)\r
+          bytes[offset+(packedIndex+1)/2] = (byte) 0;\r
+\r
+        return declaredPrecision/2 + 1;\r
+       }\r
+\r
+\r
+       /***\r
+        * Prepend zeros to numeric string\r
+        *\r
+        * @param s string\r
+        * @param precision - length of padded string\r
+        *\r
+        * @return zero padded string\r
+        */\r
+       public static String zeroPadString(String s, int precision)\r
+       {\r
+\r
+               if (s == null)\r
+                       return s;\r
+\r
+               int slen = s.length();\r
+               if (precision == slen)\r
+                       return s;\r
+               else if (precision > slen)\r
+               {\r
+                       char[] ca  = new char[precision - slen];\r
+                       Arrays.fill(ca,0,precision - slen,'0');\r
+                       return new String(ca) + s;\r
+               }\r
+               else\r
+               {\r
+                       // Shouldn't happen but just in case \r
+                       // truncate\r
+                       return s.substring(0,precision);\r
+               }\r
+\r
+       }\r
+\r
+    \r
+    private void sendBytes (java.io.OutputStream socketOutputStream) \r
+       throws java.io.IOException{\r
+       \r
+       sendBytes(socketOutputStream,\r
+                 true);\r
+       \r
+    }\r
+    \r
+\r
+  private void sendBytes (java.io.OutputStream socketOutputStream,\r
+                         boolean flashStream ) \r
+      throws java.io.IOException\r
+  {\r
+       resetChainState();\r
+    try {\r
+      socketOutputStream.write (bytes, 0, offset);\r
+      if(flashStream)\r
+         socketOutputStream.flush();\r
+    }\r
+    finally {\r
+               if ((dssTrace != null) && dssTrace.isComBufferTraceOn()) {\r
+                       dssTrace.writeComBufferData (bytes,\r
+                                                      0,\r
+                                                      offset,\r
+                                                      DssTrace.TYPE_TRACE_SEND,\r
+                                                      "Reply",\r
+                                                      "flush",\r
+                                                      5);\r
+      }\r
+      clearBuffer();\r
+    }\r
+  }\r
+\r
+       protected String toDebugString(String indent)\r
+       {\r
+               String s = indent + "***** DDMWriter toDebugString ******\n";\r
+               int byteslen = 0;\r
+               if ( bytes != null)\r
+                       byteslen = bytes.length;\r
+               s += indent + "byte array length  = " + bytes.length + "\n";\r
+               return s;\r
+       }\r
+\r
+       /**\r
+        * Reset any chaining state that needs to be reset\r
+        * at time of the send\r
+        */\r
+       protected void resetChainState()\r
+       {\r
+               prevHdrLocation = -1;\r
+       }\r
+\r
+       /**\r
+        * Looks at chaining info for previous DSS written, and use\r
+        * that to figure out what the correlation id for the current\r
+        * DSS should be.  Return that correlation id.\r
+        */\r
+       private int getCorrelationID() {\r
+\r
+               int cId;\r
+               if (previousCorrId != DssConstants.CORRELATION_ID_UNKNOWN) {\r
+                       if (previousChainByte == DssConstants.DSSCHAIN_SAME_ID)\r
+                       // then we have to use the last correlation id we sent.\r
+                               cId = previousCorrId;\r
+                       else\r
+                       // get correlation id as normal.\r
+                               cId = nextCorrelationID++;\r
+               }\r
+               else {\r
+               // must be the case that this is the first DSS we're\r
+               // writing for this connection (because we haven't\r
+               // called "endDss" yet).  So, get the corr id as\r
+               // normal.\r
+                       cId = nextCorrelationID++;\r
+               }\r
+\r
+               return cId;\r
+\r
+       }\r
+\r
+       /**\r
+        * Finalize the current DSS chain and send it if\r
+        * needed.\r
+        *\r
+        * Updates the chaining state of the most recently-written-\r
+        * to-buffer DSS to correspond to the most recently-read-\r
+        * from-client request.  If that chaining state indicates\r
+        * we've reached the end of a chain, then we go ahead\r
+        * and send the buffer across the wire.\r
+        * @param socketOutputStream Output stream to which we're flushing.\r
+        */\r
+       protected void finalizeChain(byte currChainByte,\r
+               OutputStream socketOutputStream) throws DRDAProtocolException\r
+       {\r
+\r
+               // Go back to previous DSS and override the default\r
+               // chain state (WITH_SAME_ID) with whatever the last\r
+               // request dictates.\r
+\r
+               if (prevHdrLocation != -1) {\r
+               // Note: == -1 => the previous DSS was already sent; this\r
+               // should only happen in cases where the buffer filled up\r
+               // and we had to send it (which means we were probably\r
+               // writing EXTDTA).  In such cases, proper chaining\r
+               // should already have been handled @ time of send.\r
+                       bytes[prevHdrLocation + 3] &= 0x0F;     // Zero out old chain value.\r
+                       bytes[prevHdrLocation + 3] |= currChainByte;\r
+               }\r
+\r
+               // previousChainByte needs to match what we just did.\r
+               previousChainByte = currChainByte;\r
+\r
+               if (currChainByte != DssConstants.DSS_NOCHAIN)\r
+               // then we're still inside a chain, so don't send.\r
+                       return;\r
+\r
+               // Else, we just ended the chain, so send it across.\r
+\r
+               if ((SanityManager.DEBUG) && (agent != null))\r
+                       agent.trace("Sending data");\r
+\r
+               resetChainState();\r
+               if (doesRequestContainData()) {\r
+                       try {\r
+                               flush(socketOutputStream);\r
+                       } catch (java.io.IOException e) {\r
+                               agent.markCommunicationsFailure(\r
+                                       "DDMWriter.finalizeChain()",\r
+                                       "OutputStream.flush()",\r
+                                       e.getMessage(),"*");\r
+                       }\r
+               }\r
+\r
+       }\r
+\r
+       /**\r
+        * Takes note of the location of the most recently completed\r
+        * DSS in the buffer, and then returns the current offset.\r
+        * This method is used in conjunction with "clearDSSesBackToMark"\r
+        * to allow for DRDAConnThread to "back-out" DSSes in the\r
+        * event of errors.\r
+        */\r
+       protected int markDSSClearPoint()\r
+       {\r
+\r
+               lastDSSBeforeMark = prevHdrLocation;\r
+               return offset;\r
+\r
+       }\r
+\r
+       /**\r
+        * Does a logical "clear" of everything written to the buffer after\r
+        * the received mark.  It's assumed that this method will be used\r
+        * in error cases when we've started writing one or more DSSes,\r
+        * but then hit an error and need to back out.  After backing out,\r
+        * we'll always need to write _something_ back to the client to\r
+        * indicate an error (typically, we just write an SQLCARD) but what\r
+        * exactly gets written is handled in DRDAConnThread.  Here, we\r
+        * just do the necessary prep so that whatever comes next will\r
+        * succeed.\r
+        */\r
+       protected void clearDSSesBackToMark(int mark)\r
+       {\r
+\r
+               // Logical clear.\r
+               offset = mark;\r
+\r
+               // Because we've just cleared out the most recently-\r
+               // written DSSes, we have to make sure the next thing\r
+               // we write will have the correct correlation id.  We\r
+               // do this by setting the value of 'nextCorrelationID'\r
+               // based on the chaining byte from the last remaining\r
+               // DSS (where "remaining" means that it still exists\r
+               // in the buffer after the clear).\r
+               if (lastDSSBeforeMark == -1)\r
+               // we cleared out the entire buffer; reset corr id.\r
+                       nextCorrelationID = 1;\r
+               else {\r
+               // last remaining DSS had chaining, so we set "nextCorrelationID"\r
+               // to be 1 greater than whatever the last remaining DSS had as\r
+               // its correlation id.\r
+                       nextCorrelationID = 1 + (int)\r
+                               (((bytes[lastDSSBeforeMark + 4] & 0xff) << 8) +\r
+                               (bytes[lastDSSBeforeMark + 5] & 0xff));\r
+               }\r
+\r
+       }\r
+\r
+       \r
+    private static int peekStream(InputStream in) throws IOException{\r
+           \r
+       in.mark(1);\r
+\r
+       try{\r
+           return in.read();\r
+           \r
+       }finally{\r
+           in.reset();\r
+           \r
+       }\r
+    }\r
+\r
+    \r
+    private static int getLayerBStreamingBufferSize(){\r
+       return PropertyUtil.getSystemInt( Property.DRDA_PROP_STREAMOUTBUFFERSIZE , 0 );\r
+    }\r
+    \r
+    \r
+    private static OutputStream placeLayerBStreamingBuffer(OutputStream original){\r
+       \r
+       int size = getLayerBStreamingBufferSize();\r
+       \r
+       if(size < 1)\r
+           return original;\r
+       else\r
+           return new BufferedOutputStream( original, size );\r
+\r
+    }\r
+    \r
+}\r
+\r