db-derby-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From kmars...@apache.org
Subject svn commit: r1370674 [5/12] - in /db/derby/code/trunk/java/drda/org/apache/derby: drda/ impl/drda/
Date Wed, 08 Aug 2012 06:54:47 GMT
Modified: db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DDMWriter.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DDMWriter.java?rev=1370674&r1=1370673&r2=1370674&view=diff
==============================================================================
--- db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DDMWriter.java (original)
+++ db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DDMWriter.java Wed Aug  8 06:54:46 2012
@@ -42,21 +42,21 @@ import org.apache.derby.iapi.services.pr
 import org.apache.derby.iapi.services.sanity.SanityManager;
 
 /**
-	The DDMWriter is used to write DRDA protocol.   The DRDA Protocol is
-	described in the DDMReader class.
-	For more details, see DRDA Volume 3 (Distributed Data Management(DDM)
-		Architecture (DDS definition)
+    The DDMWriter is used to write DRDA protocol.   The DRDA Protocol is
+    described in the DDMReader class.
+    For more details, see DRDA Volume 3 (Distributed Data Management(DDM)
+        Architecture (DDS definition)
 */
 class DDMWriter
 {
 
-	// number of nesting levels for collections.  We need to mark the length
-	// location of the collection so that we can update it as we add more stuff
-	// to the collection
-	private final static int MAX_MARKS_NESTING = 10;
+    // number of nesting levels for collections.  We need to mark the length
+    // location of the collection so that we can update it as we add more stuff
+    // to the collection
+    private final static int MAX_MARKS_NESTING = 10;
 
-	// Default buffer size
-	private final static int DEFAULT_BUFFER_SIZE = 32767;
+    // Default buffer size
+    private final static int DEFAULT_BUFFER_SIZE = 32767;
 
     /**
      * The maximum length in bytes for strings sent by {@code writeLDString()},
@@ -64,65 +64,65 @@ class DDMWriter
      */
     private final static int MAX_VARCHAR_BYTE_LENGTH = 0xFFFF;
 
-	/**
-	 * Output buffer.
-	 */
-	private ByteBuffer buffer;
-
-	// A saved mark in the stream is saved temporarily to revisit the location.
-	private int[] markStack = new int[MAX_MARKS_NESTING];
-
-	// top of the stack
-	private int top;
-
-	// CCSID manager for translation of strings in the protocol to UTF-8 and EBCDIC
-	private EbcdicCcsidManager ebcdicCcsidManager;
-	private Utf8CcsidManager utf8CcsidManager;
-	
-	// Current CCSID manager
-	private CcsidManager ccsidManager;
-
-	// DRDA connection thread for this writer
-	private DRDAConnThread agent;
-
-	//	This Object tracks the location of the current
-	//	Dss header length bytes.	This is done so
-	//	the length bytes can be automatically
-	//	updated as information is added to this stream.
-	private int dssLengthLocation;
-
-	// Current correlation ID
-	private	int correlationID;
-
-	// Next correlation ID
-	private int nextCorrelationID;
-
-	// is this DRDA protocol or CMD protocol
-	private boolean isDRDAProtocol;
-	// trace object of the associated session
-	private DssTrace dssTrace;
-
-	// Location of the start of the header
-	// of the DSS most recently written to the buffer.
-	private int prevHdrLocation;
-
-	// Correlation id of the last DSS that was written to buffer.
-	private int previousCorrId;
-
-	// Chaining bit of the last DSS that was written to buffer.
-	private byte previousChainByte;
-
-	// Whether or not the current DSS is a continuation DSS.
-	private boolean isContinuationDss;
-
-	// In situations where we want to "mark" a buffer location so that
-	// we can "back-out" of a write to handle errors, this holds the
-	// location within the buffer of the start of the header
-	// that immediately precedes the mark.
-	private int lastDSSBeforeMark;
+    /**
+     * Output buffer.
+     */
+    private ByteBuffer buffer;
+
+    // A saved mark in the stream is saved temporarily to revisit the location.
+    private int[] markStack = new int[MAX_MARKS_NESTING];
+
+    // top of the stack
+    private int top;
+
+    // CCSID manager for translation of strings in the protocol to UTF-8 and EBCDIC
+    private EbcdicCcsidManager ebcdicCcsidManager;
+    private Utf8CcsidManager utf8CcsidManager;
+    
+    // Current CCSID manager
+    private CcsidManager ccsidManager;
+
+    // DRDA connection thread for this writer
+    private DRDAConnThread agent;
+
+    //    This Object tracks the location of the current
+    //    Dss header length bytes.    This is done so
+    //    the length bytes can be automatically
+    //    updated as information is added to this stream.
+    private int dssLengthLocation;
+
+    // Current correlation ID
+    private    int correlationID;
+
+    // Next correlation ID
+    private int nextCorrelationID;
+
+    // is this DRDA protocol or CMD protocol
+    private boolean isDRDAProtocol;
+    // trace object of the associated session
+    private DssTrace dssTrace;
+
+    // Location of the start of the header
+    // of the DSS most recently written to the buffer.
+    private int prevHdrLocation;
+
+    // Correlation id of the last DSS that was written to buffer.
+    private int previousCorrId;
+
+    // Chaining bit of the last DSS that was written to buffer.
+    private byte previousChainByte;
+
+    // Whether or not the current DSS is a continuation DSS.
+    private boolean isContinuationDss;
+
+    // In situations where we want to "mark" a buffer location so that
+    // we can "back-out" of a write to handle errors, this holds the
+    // location within the buffer of the start of the header
+    // that immediately precedes the mark.
+    private int lastDSSBeforeMark;
 
-	/** Encoder which encodes strings with the server's default encoding. */
-	private final CharsetEncoder encoder;
+    /** Encoder which encodes strings with the server's default encoding. */
+    private final CharsetEncoder encoder;
 
     // For JMX statistics. Volatile to ensure we 
     // get one complete long, but we don't bother to synchronize, 
@@ -130,57 +130,57 @@ class DDMWriter
     
     volatile long totalByteCount = 0;
     
-	DDMWriter (DRDAConnThread agent, DssTrace dssTrace)
-	{
-	    // Create instances of the two ccsid managers and default to EBCDIC
-	    this.ebcdicCcsidManager = new EbcdicCcsidManager();
-	    this.utf8CcsidManager = new Utf8CcsidManager();
-	    this.ccsidManager = this.ebcdicCcsidManager;
-	    
-		this.buffer = ByteBuffer.allocate(DEFAULT_BUFFER_SIZE);
-		this.agent = agent;
-		this.prevHdrLocation = -1;
-		this.previousCorrId = DssConstants.CORRELATION_ID_UNKNOWN;
-		this.previousChainByte = DssConstants.DSS_NOCHAIN;
-		this.isContinuationDss = false;
-		this.lastDSSBeforeMark = -1;
-		reset(dssTrace);
-		// create an encoder which inserts the charset's default replacement
-		// character for characters it can't encode
-		encoder = NetworkServerControlImpl.DEFAULT_CHARSET.newEncoder()
-			.onMalformedInput(CodingErrorAction.REPLACE)
-			.onUnmappableCharacter(CodingErrorAction.REPLACE);
-	}
-
-	// Switch the ccsidManager to the UTF-8 instance
-	protected void setUtf8Ccsid() {
-	    ccsidManager = utf8CcsidManager;
-	}
-	
-	// Switch the ccsidManager to the EBCDIC instance
-	protected void setEbcdicCcsid() {
-	    ccsidManager = ebcdicCcsidManager;
-	}
-	
-	// Get the current ccsidManager
-	protected CcsidManager getCurrentCcsidManager() {
-	    return ccsidManager;
-	}
-	
-	/**
-	 * reset values for sending next message
-	 *
-	 */
-	protected void reset(DssTrace dssTrace)
-	{
-		buffer.clear();
-		top = 0;
-		dssLengthLocation = 0;
-		nextCorrelationID = 1;
-		correlationID = DssConstants.CORRELATION_ID_UNKNOWN;
-		isDRDAProtocol = true;
-		this.dssTrace = dssTrace;
-	}
+    DDMWriter (DRDAConnThread agent, DssTrace dssTrace)
+    {
+        // Create instances of the two ccsid managers and default to EBCDIC
+        this.ebcdicCcsidManager = new EbcdicCcsidManager();
+        this.utf8CcsidManager = new Utf8CcsidManager();
+        this.ccsidManager = this.ebcdicCcsidManager;
+        
+        this.buffer = ByteBuffer.allocate(DEFAULT_BUFFER_SIZE);
+        this.agent = agent;
+        this.prevHdrLocation = -1;
+        this.previousCorrId = DssConstants.CORRELATION_ID_UNKNOWN;
+        this.previousChainByte = DssConstants.DSS_NOCHAIN;
+        this.isContinuationDss = false;
+        this.lastDSSBeforeMark = -1;
+        reset(dssTrace);
+        // create an encoder which inserts the charset's default replacement
+        // character for characters it can't encode
+        encoder = NetworkServerControlImpl.DEFAULT_CHARSET.newEncoder()
+            .onMalformedInput(CodingErrorAction.REPLACE)
+            .onUnmappableCharacter(CodingErrorAction.REPLACE);
+    }
+
+    // Switch the ccsidManager to the UTF-8 instance
+    protected void setUtf8Ccsid() {
+        ccsidManager = utf8CcsidManager;
+    }
+    
+    // Switch the ccsidManager to the EBCDIC instance
+    protected void setEbcdicCcsid() {
+        ccsidManager = ebcdicCcsidManager;
+    }
+    
+    // Get the current ccsidManager
+    protected CcsidManager getCurrentCcsidManager() {
+        return ccsidManager;
+    }
+    
+    /**
+     * reset values for sending next message
+     *
+     */
+    protected void reset(DssTrace dssTrace)
+    {
+        buffer.clear();
+        top = 0;
+        dssLengthLocation = 0;
+        nextCorrelationID = 1;
+        correlationID = DssConstants.CORRELATION_ID_UNKNOWN;
+        isDRDAProtocol = true;
+        this.dssTrace = dssTrace;
+    }
 
     /**
      * Get the current position in the output buffer.
@@ -211,107 +211,107 @@ class DDMWriter
         return bytes;
     }
 
-	/**
-	 * set protocol to CMD protocol
-	 */
-	protected void setCMDProtocol()
-	{
-		isDRDAProtocol = false;
-	}
-
-	/**
-	 * Create DSS reply object
-	 */
-	protected void createDssReply()
-	{
-		beginDss(DssConstants.DSSFMT_RPYDSS, true);
-	}
-
-	/**
-	 * Create DSS request object
-	 * NOTE: This is _ONLY_ used for testing the protocol
+    /**
+     * set protocol to CMD protocol
+     */
+    protected void setCMDProtocol()
+    {
+        isDRDAProtocol = false;
+    }
+
+    /**
+     * Create DSS reply object
+     */
+    protected void createDssReply()
+    {
+        beginDss(DssConstants.DSSFMT_RPYDSS, true);
+    }
+
+    /**
+     * Create DSS request object
+     * NOTE: This is _ONLY_ used for testing the protocol
     * (via the ProtocolTestAdapter.java file in this package)!
-	 * We should never create a DSS request in normal
-	 * DRDA processing (we should only create DSS replies
-	 * and DSS objects).
-	 */
-	protected void createDssRequest()
-	{
-		beginDss(DssConstants.DSSFMT_RQSDSS, true);
-	}
-
-	/**
-	 * Create DSS data object
-	 */
-	protected void createDssObject()
-	{
-		beginDss(DssConstants.DSSFMT_OBJDSS, true);
-	}
-
-	/**
-	 * Mark the DSS that we're currently writing as
-	 * a continued DSS, which is done by setting
-	 * the high-order bit to "1", per DDM spec.
-	 * This means:
-	 *
-	 *	1. One or more continuation DSSes will immediately
-	 * 		follow the current (continued) DSS.
-	 *	2. All continuation DSSes will have a 2-byte
-	 * 		continuation header, followed by data; in
-	 * 		other words, chaining state, correlation
-	 *		id, dss format info, and code point will
-	 * 		NOT be included.  All of that info is 
-	 * 		present ONLY in the FIRST DSS in the
-	 *		list of continued DSSes.
-	 *
-	 *	NOTE: A DSS can be a "continuation" DSS _and_
-	 * 	a "continued" DSS at the same time.  However,
-	 * 	the FIRST DSS to be continued canNOT be
-	 *	a continuation DSS.
-	 */
-	private void markDssAsContinued(boolean forLob)
-	{
-
-		if (!forLob) {
-		// continuation bit defaults to '1' for lobs, so
-		// we only have to switch it if we're not writing
-		// lobs.
-			byte b = (byte) (buffer.get(dssLengthLocation) | 0x80);
-			buffer.put(dssLengthLocation, b);
-		}
-
-		// We need to set the chaining state, but ONLY
-		// IF this is the FIRST DSS in the continuation
-		// list (only the first one has chaining state
-		// in it's header; the others do not).
-		if (!isContinuationDss)
-			endDss(!forLob);
-
-	}
-
-	/**
-	 * End DSS header by writing the length in the length location
-	 * and setting the chain bit.  Unlike the other two endDss
-	 * methods, this one overrides the default chaining byte
-	 * (which is set in beginDss) with the chaining byte that
-	 * is passed in.  NOTE: This method is only used in
-	 * association with createDssRequest, and thus is for
+     * We should never create a DSS request in normal
+     * DRDA processing (we should only create DSS replies
+     * and DSS objects).
+     */
+    protected void createDssRequest()
+    {
+        beginDss(DssConstants.DSSFMT_RQSDSS, true);
+    }
+
+    /**
+     * Create DSS data object
+     */
+    protected void createDssObject()
+    {
+        beginDss(DssConstants.DSSFMT_OBJDSS, true);
+    }
+
+    /**
+     * Mark the DSS that we're currently writing as
+     * a continued DSS, which is done by setting
+     * the high-order bit to "1", per DDM spec.
+     * This means:
+     *
+     *    1. One or more continuation DSSes will immediately
+     *         follow the current (continued) DSS.
+     *    2. All continuation DSSes will have a 2-byte
+     *         continuation header, followed by data; in
+     *         other words, chaining state, correlation
+     *        id, dss format info, and code point will
+     *         NOT be included.  All of that info is 
+     *         present ONLY in the FIRST DSS in the
+     *        list of continued DSSes.
+     *
+     *    NOTE: A DSS can be a "continuation" DSS _and_
+     *     a "continued" DSS at the same time.  However,
+     *     the FIRST DSS to be continued canNOT be
+     *    a continuation DSS.
+     */
+    private void markDssAsContinued(boolean forLob)
+    {
+
+        if (!forLob) {
+        // continuation bit defaults to '1' for lobs, so
+        // we only have to switch it if we're not writing
+        // lobs.
+            byte b = (byte) (buffer.get(dssLengthLocation) | 0x80);
+            buffer.put(dssLengthLocation, b);
+        }
+
+        // We need to set the chaining state, but ONLY
+        // IF this is the FIRST DSS in the continuation
+        // list (only the first one has chaining state
+        // in it's header; the others do not).
+        if (!isContinuationDss)
+            endDss(!forLob);
+
+    }
+
+    /**
+     * End DSS header by writing the length in the length location
+     * and setting the chain bit.  Unlike the other two endDss
+     * methods, this one overrides the default chaining byte
+     * (which is set in beginDss) with the chaining byte that
+     * is passed in.  NOTE: This method is only used in
+     * association with createDssRequest, and thus is for
     * TESTING purposes only (via ProtocolTestAdpater.java).  No calls
-	 * should be made to this method in normal DRDA processing
-	 * (because for normal processing, chaining must be
-	 * determined automatically based on DSS requests).
-	 */
-	protected void endDss(byte chainByte)
-	{
-
-		// Do regular endDss processing.
-		endDss(true);
-
-		// Now override default chain state.
-		overrideChainByte(dssLengthLocation + 3, chainByte);
-		previousChainByte = chainByte;
+     * should be made to this method in normal DRDA processing
+     * (because for normal processing, chaining must be
+     * determined automatically based on DSS requests).
+     */
+    protected void endDss(byte chainByte)
+    {
 
-	}
+        // Do regular endDss processing.
+        endDss(true);
+
+        // Now override default chain state.
+        overrideChainByte(dssLengthLocation + 3, chainByte);
+        previousChainByte = chainByte;
+
+    }
 
     /**
      * Override the default chaining byte with the chaining byte that is passed
@@ -327,173 +327,173 @@ class DDMWriter
         buffer.put(pos, b);
     }
 
-	/**
-	 * End DSS header by writing the length in the length location
-	 * and setting the chain bit.
-	 */
-	protected void endDss() {
-		endDss(true);
-	}
-
-	/**
-	 * End DSS header by writing the length in the length location
-	 * and setting the chain bit.
-	 */
-	private void endDss (boolean finalizeLength)
-	{
-
-		if (finalizeLength)
-			finalizeDssLength();
-
-		if (isContinuationDss) {
-		// no chaining information for this DSS; so we're done.
-			isContinuationDss = false;
-			return;
-		}
-
-		previousCorrId = correlationID;
-		prevHdrLocation = dssLengthLocation;
-		previousChainByte = DssConstants.DSSCHAIN_SAME_ID;
-
-	}
-
-	/**
-	 * End final DDM and DSS header by writing the length in the length location
-	 *
-	 */
-	protected void endDdmAndDss ()
-	{
-		endDdm();	// updates last DDM object
-		endDss();
-	}
-	/**
-	 * Copy Data to End
-	 * Create a buffer and copy from the position given to the end of data
-	 *
-	 * Note that the position given is treated as relative to the
-	 * current DSS, for there may be other DSS blocks (chained, presumably)
-	 * which are sitting unwritten in the buffer. The caller doesn't
-	 * know this, though, and works only with the current DSS.
-	 *
-	 * getDSSLength, copyDSSDataToEnd, and truncateDSS work together to
-	 * provide a sub-protocol for DRDAConnThread to use in its
-	 * implementation of the LMTBLKPRC protocol. They enable the caller
-	 * to determine when it has written too much data into the current
-	 * DSS, to reclaim the extra data that won't fit, and to truncate
-	 * that extra data once it has been reclaimed and stored elsewhere.
-	 * Note that this support only works for the current DSS. Earlier,
-	 * chained DSS blocks cannot be accessed using these methods. For
-	 * additional background information, the interested reader should
-	 * investigate bugs DERBY-491 and 492 at:
-	 * http://issues.apache.org/jira/browse/DERBY-491 and
-	 * http://issues.apache.org/jira/browse/DERBY-492
-	 *
-	 * @param start
-	 */
-	protected byte [] copyDSSDataToEnd(int start)
-	{
-		start = start + dssLengthLocation;
-		int length = buffer.position() - start;
-		byte [] temp = new byte[length];
-		buffer.position(start);
-		buffer.get(temp);
-		return temp;
-	}
-
-	// Collection methods
-
-	/**
-	 * Mark the location of the length bytes for the collection so they
-	 * can be updated later
-	 *
-	 */
-	protected void startDdm (int codePoint)
-	{
-		// save the location of the beginning of the collection so
-		// that we can come back and fill in the length bytes
-		final int offset = buffer.position();
-		markStack[top++] = offset;
-		ensureLength (4); // verify space for length bytes and code point
-		// move past the length bytes before writing the code point
-		buffer.position(offset + 2);
-		buffer.putShort((short) codePoint);
-	}
-
-	/**
-	 * Erase all writes for the current ddm and reset the
-	 * top
-	 */
-	protected void clearDdm ()
-	{
-		buffer.position(markStack[top--]);
-	}
-
-	/**
-	 * Clear the entire send buffer
-	 *
-	 */
-	protected void clearBuffer()
-	{
-		buffer.clear();
-		top = 0;
-		dssLengthLocation = 0;
-		correlationID = DssConstants.CORRELATION_ID_UNKNOWN;
-		nextCorrelationID = 1;
-		isDRDAProtocol = true;
-	}
-
-	/**
-	 * End the current DDM
-	 *
-	 */
-	protected void endDdm ()
-	{
-		// remove the top length location offset from the mark stack
-		// calculate the length based on the marked location and end of data.
-		int lengthLocation = markStack[--top];
-		int length = buffer.position() - lengthLocation;
-
-		// determine if any extended length bytes are needed.	the value returned
-		// from calculateExtendedLengthByteCount is the number of extended length
-		// bytes required. 0 indicates no exteneded length.
-		int extendedLengthByteCount = calculateExtendedLengthByteCount (length);
-		if (extendedLengthByteCount != 0)
-		{
-			// ensure there is enough room in the buffer for the extended length bytes.
-			ensureLength (extendedLengthByteCount);
-
-			// calculate the length to be placed in the extended length bytes.
-			// this length does not include the 4 byte llcp.
-			int extendedLength = length - 4;
-
-			// the extended length should be written right after the length and
-			// the codepoint (2+2 bytes)
-			final int extendedLengthLocation = lengthLocation + 4;
-
-			// shift the data to the right by the number of extended
-			// length bytes needed.
-			buffer.position(extendedLengthLocation + extendedLengthByteCount);
-			buffer.put(buffer.array(), extendedLengthLocation, extendedLength);
-
-			// write the extended length (a variable number of bytes in
-			// big-endian order)
-			for (int pos = extendedLengthLocation + extendedLengthByteCount - 1;
-				 pos >= extendedLengthLocation; pos--) {
-				buffer.put(pos, (byte) extendedLength);
-				extendedLength >>= 8;
-			}
-
-			// the two byte length field before the codepoint contains the length
-			// of itself, the length of the codepoint, and the number of bytes used
-			// to hold the extended length.	the 2 byte length field also has the first
-			// bit on to indicate extended length bytes were used.
-			length = extendedLengthByteCount + 4;
-			length |= DssConstants.CONTINUATION_BIT;
-		}
-
-		// write the 2 byte length field (2 bytes before codepoint).
-		buffer.putShort(lengthLocation, (short) length);
-	}
+    /**
+     * End DSS header by writing the length in the length location
+     * and setting the chain bit.
+     */
+    protected void endDss() {
+        endDss(true);
+    }
+
+    /**
+     * End DSS header by writing the length in the length location
+     * and setting the chain bit.
+     */
+    private void endDss (boolean finalizeLength)
+    {
+
+        if (finalizeLength)
+            finalizeDssLength();
+
+        if (isContinuationDss) {
+        // no chaining information for this DSS; so we're done.
+            isContinuationDss = false;
+            return;
+        }
+
+        previousCorrId = correlationID;
+        prevHdrLocation = dssLengthLocation;
+        previousChainByte = DssConstants.DSSCHAIN_SAME_ID;
+
+    }
+
+    /**
+     * End final DDM and DSS header by writing the length in the length location
+     *
+     */
+    protected void endDdmAndDss ()
+    {
+        endDdm();    // updates last DDM object
+        endDss();
+    }
+    /**
+     * Copy Data to End
+     * Create a buffer and copy from the position given to the end of data
+     *
+     * Note that the position given is treated as relative to the
+     * current DSS, for there may be other DSS blocks (chained, presumably)
+     * which are sitting unwritten in the buffer. The caller doesn't
+     * know this, though, and works only with the current DSS.
+     *
+     * getDSSLength, copyDSSDataToEnd, and truncateDSS work together to
+     * provide a sub-protocol for DRDAConnThread to use in its
+     * implementation of the LMTBLKPRC protocol. They enable the caller
+     * to determine when it has written too much data into the current
+     * DSS, to reclaim the extra data that won't fit, and to truncate
+     * that extra data once it has been reclaimed and stored elsewhere.
+     * Note that this support only works for the current DSS. Earlier,
+     * chained DSS blocks cannot be accessed using these methods. For
+     * additional background information, the interested reader should
+     * investigate bugs DERBY-491 and 492 at:
+     * http://issues.apache.org/jira/browse/DERBY-491 and
+     * http://issues.apache.org/jira/browse/DERBY-492
+     *
+     * @param start
+     */
+    protected byte [] copyDSSDataToEnd(int start)
+    {
+        start = start + dssLengthLocation;
+        int length = buffer.position() - start;
+        byte [] temp = new byte[length];
+        buffer.position(start);
+        buffer.get(temp);
+        return temp;
+    }
+
+    // Collection methods
+
+    /**
+     * Mark the location of the length bytes for the collection so they
+     * can be updated later
+     *
+     */
+    protected void startDdm (int codePoint)
+    {
+        // save the location of the beginning of the collection so
+        // that we can come back and fill in the length bytes
+        final int offset = buffer.position();
+        markStack[top++] = offset;
+        ensureLength (4); // verify space for length bytes and code point
+        // move past the length bytes before writing the code point
+        buffer.position(offset + 2);
+        buffer.putShort((short) codePoint);
+    }
+
+    /**
+     * Erase all writes for the current ddm and reset the
+     * top
+     */
+    protected void clearDdm ()
+    {
+        buffer.position(markStack[top--]);
+    }
+
+    /**
+     * Clear the entire send buffer
+     *
+     */
+    protected void clearBuffer()
+    {
+        buffer.clear();
+        top = 0;
+        dssLengthLocation = 0;
+        correlationID = DssConstants.CORRELATION_ID_UNKNOWN;
+        nextCorrelationID = 1;
+        isDRDAProtocol = true;
+    }
+
+    /**
+     * End the current DDM
+     *
+     */
+    protected void endDdm ()
+    {
+        // remove the top length location offset from the mark stack
+        // calculate the length based on the marked location and end of data.
+        int lengthLocation = markStack[--top];
+        int length = buffer.position() - lengthLocation;
+
+        // determine if any extended length bytes are needed.    the value returned
+        // from calculateExtendedLengthByteCount is the number of extended length
+        // bytes required. 0 indicates no exteneded length.
+        int extendedLengthByteCount = calculateExtendedLengthByteCount (length);
+        if (extendedLengthByteCount != 0)
+        {
+            // ensure there is enough room in the buffer for the extended length bytes.
+            ensureLength (extendedLengthByteCount);
+
+            // calculate the length to be placed in the extended length bytes.
+            // this length does not include the 4 byte llcp.
+            int extendedLength = length - 4;
+
+            // the extended length should be written right after the length and
+            // the codepoint (2+2 bytes)
+            final int extendedLengthLocation = lengthLocation + 4;
+
+            // shift the data to the right by the number of extended
+            // length bytes needed.
+            buffer.position(extendedLengthLocation + extendedLengthByteCount);
+            buffer.put(buffer.array(), extendedLengthLocation, extendedLength);
+
+            // write the extended length (a variable number of bytes in
+            // big-endian order)
+            for (int pos = extendedLengthLocation + extendedLengthByteCount - 1;
+                 pos >= extendedLengthLocation; pos--) {
+                buffer.put(pos, (byte) extendedLength);
+                extendedLength >>= 8;
+            }
+
+            // the two byte length field before the codepoint contains the length
+            // of itself, the length of the codepoint, and the number of bytes used
+            // to hold the extended length.    the 2 byte length field also has the first
+            // bit on to indicate extended length bytes were used.
+            length = extendedLengthByteCount + 4;
+            length |= DssConstants.CONTINUATION_BIT;
+        }
+
+        // write the 2 byte length field (2 bytes before codepoint).
+        buffer.putShort(lengthLocation, (short) length);
+    }
 
     /**
      * Get the length of the current DSS block we're working on. This is
@@ -522,247 +522,247 @@ class DDMWriter
     }
 
 
-	// Write routines
+    // Write routines
+
+    /**
+     * Write byte
+     *
+     * @param     value    byte to be written
+     */
+    protected void writeByte (int value)
+    {
+        if (SanityManager.DEBUG)
+        {
+            if (value > 255)
+                SanityManager.THROWASSERT(
+                                       "writeByte value: " + value +
+                                       " may not be > 255");
+        }
+
+        ensureLength (1);
+        buffer.put((byte) value);
+    }
+
+
+    /**
+     * Write network short
+     *
+     * @param     value    value to be written
+     */
+    protected void writeNetworkShort (int value)
+    {
+        ensureLength (2);
+        buffer.putShort((short) value);
+    }
+
+    /**
+     * Write network int
+     *
+     * @param     value    value to be written
+     */
+    protected void writeNetworkInt (int value)
+    {
+        ensureLength (4);
+        buffer.putInt(value);
+    }
+
+
+    /**
+     * Write byte array
+     *
+     * @param     buf    byte array to be written
+     * @param    length  - length to write
+     */
+    protected void writeBytes (byte[] buf, int length)
+    {
+        writeBytes(buf, 0,length);
+    }
+
+
+
+    /**
+     * Write byte array
+     *
+     * @param     buf    byte array to be written
+     * @param    start  - starting position
+     * @param    length  - length to write
+     */
+    protected void writeBytes (byte[] buf, int start, int length)
+    {
 
-	/**
-	 * Write byte
-	 *
-	 * @param 	value	byte to be written
-	 */
-	protected void writeByte (int value)
-	{
-		if (SanityManager.DEBUG)
-		{
-			if (value > 255)
-				SanityManager.THROWASSERT(
-									   "writeByte value: " + value +
-									   " may not be > 255");
-		}
-
-		ensureLength (1);
-		buffer.put((byte) value);
-	}
-
-
-	/**
-	 * Write network short
-	 *
-	 * @param 	value	value to be written
-	 */
-	protected void writeNetworkShort (int value)
-	{
-		ensureLength (2);
-		buffer.putShort((short) value);
-	}
-
-	/**
-	 * Write network int
-	 *
-	 * @param 	value	value to be written
-	 */
-	protected void writeNetworkInt (int value)
-	{
-		ensureLength (4);
-		buffer.putInt(value);
-	}
-
-
-	/**
-	 * Write byte array
-	 *
-	 * @param 	buf	byte array to be written
-	 * @param	length  - length to write
-	 */
-	protected void writeBytes (byte[] buf, int length)
-	{
-		writeBytes(buf, 0,length);
-	}
-
-
-
-	/**
-	 * Write byte array
-	 *
-	 * @param 	buf	byte array to be written
-	 * @param	start  - starting position
-	 * @param	length  - length to write
-	 */
-	protected void writeBytes (byte[] buf, int start, int length)
-	{
-
-		if (SanityManager.DEBUG)
-		{
-			if (buf == null && length > 0)
-		    	SanityManager.THROWASSERT("Buf is null");
-			if (length + start - 1 > buf.length)
-		    	SanityManager.THROWASSERT("Not enough bytes in buffer");
-
-		}
-		ensureLength (length);
-		buffer.put(buf, start, length);
-	}
-	/**
-	 * Write byte array
-	 *
-	 * @param 	buf	byte array to be written
-	 **/
-	protected void writeBytes (byte[] buf)
-	{
-		writeBytes(buf,buf.length);
-	}
-
-
-
-	protected void writeLDBytes(byte[] buf)
-	{
-		writeLDBytes(buf, 0);
-	}
-
-	protected void writeLDBytes(byte[] buf, int index)
-	{
-		int writeLen =  buf.length;
-
-		writeShort(writeLen);
-
-		writeBytes(buf,0,writeLen);
-	}
-
-
-	/**
-	 * Write code point and 4 bytes
-	 *
-	 * @param 	codePoint - code point to write
-	 * @param	value  - value to write after code point
-	 */
-	void writeCodePoint4Bytes (int codePoint, int value)
-	{
-		ensureLength (4);
-		buffer.putShort((short) codePoint);
-		buffer.putShort((short) value);
-	}
-
-	/**
-	 * Write scalar 1 byte object includes length, codepoint and value
-	 *
-	 * @param 	codePoint - code point to write
-	 * @param	value  - value to write after code point
-	 */
-	void writeScalar1Byte (int codePoint, int value)
-	{
-		ensureLength (5);
-		buffer.putShort((short) 0x0005);
-		buffer.putShort((short) codePoint);
-		buffer.put((byte) value);
-	}
-
-	/**
-	 * Write scalar 2 byte object includes length, codepoint and value
-	 *
-	 * @param 	codePoint - code point to write
-	 * @param	value  - value to write after code point
-	 */
-	protected void writeScalar2Bytes (int codePoint, int value)
-	{
-		ensureLength (6);
-		buffer.putShort((short) 0x0006);
-		buffer.putShort((short) codePoint);
-		buffer.putShort((short) value);
-	}
-
-	protected void writeScalar2Bytes ( int value)
-	{
-		ensureLength (2);
-		buffer.putShort((short) value);
-	}
+        if (SanityManager.DEBUG)
+        {
+            if (buf == null && length > 0)
+                SanityManager.THROWASSERT("Buf is null");
+            if (length + start - 1 > buf.length)
+                SanityManager.THROWASSERT("Not enough bytes in buffer");
+
+        }
+        ensureLength (length);
+        buffer.put(buf, start, length);
+    }
+    /**
+     * Write byte array
+     *
+     * @param     buf    byte array to be written
+     **/
+    protected void writeBytes (byte[] buf)
+    {
+        writeBytes(buf,buf.length);
+    }
+
+
+
+    protected void writeLDBytes(byte[] buf)
+    {
+        writeLDBytes(buf, 0);
+    }
+
+    protected void writeLDBytes(byte[] buf, int index)
+    {
+        int writeLen =  buf.length;
+
+        writeShort(writeLen);
+
+        writeBytes(buf,0,writeLen);
+    }
+
+
+    /**
+     * Write code point and 4 bytes
+     *
+     * @param     codePoint - code point to write
+     * @param    value  - value to write after code point
+     */
+    void writeCodePoint4Bytes (int codePoint, int value)
+    {
+        ensureLength (4);
+        buffer.putShort((short) codePoint);
+        buffer.putShort((short) value);
+    }
+
+    /**
+     * Write scalar 1 byte object includes length, codepoint and value
+     *
+     * @param     codePoint - code point to write
+     * @param    value  - value to write after code point
+     */
+    void writeScalar1Byte (int codePoint, int value)
+    {
+        ensureLength (5);
+        buffer.putShort((short) 0x0005);
+        buffer.putShort((short) codePoint);
+        buffer.put((byte) value);
+    }
+
+    /**
+     * Write scalar 2 byte object includes length, codepoint and value
+     *
+     * @param     codePoint - code point to write
+     * @param    value  - value to write after code point
+     */
+    protected void writeScalar2Bytes (int codePoint, int value)
+    {
+        ensureLength (6);
+        buffer.putShort((short) 0x0006);
+        buffer.putShort((short) codePoint);
+        buffer.putShort((short) value);
+    }
+
+    protected void writeScalar2Bytes ( int value)
+    {
+        ensureLength (2);
+        buffer.putShort((short) value);
+    }
     
     protected void writeScalarStream (boolean chainedWithSameCorrelator,
-									  int codePoint,
-				      EXTDTAInputStream in,
-									  boolean writeNullByte) 
-		throws DRDAProtocolException
-	{
-
-	    
-
-		// Stream equivalent of "beginDss"...
-	    int spareDssLength = prepScalarStream( chainedWithSameCorrelator,
-											codePoint,
-											writeNullByte);
-	    
-		// write the data
-				try {
-				    
-		OutputStream out = 
-		    placeLayerBStreamingBuffer( agent.getOutputStream() );
-		
-		boolean isLastSegment = false;
-		
-		while( !isLastSegment ){
-		    
-		    if( SanityManager.DEBUG ){
-		
-			if( PropertyUtil.getSystemBoolean("derby.debug.suicideOfLayerBStreaming") )
-			    throw new IOException();
-				}
-
-			// read as many bytes as possible directly into the backing array
-			final int offset = buffer.position();
-			final int bytesRead =
-				in.read(buffer.array(), offset,
-						Math.min(spareDssLength, buffer.remaining()));
-
-			// update the buffer position
-			buffer.position(offset + bytesRead);
-
-		    spareDssLength -= bytesRead;
-
-		    isLastSegment = peekStream(in) < 0;
-		    
-		    if(isLastSegment || 
-		       spareDssLength == 0){
-			
-			flushScalarStreamSegment (isLastSegment, 
-						  out);
-			
-			if( ! isLastSegment )
-			    spareDssLength = DssConstants.MAX_DSS_LENGTH - 2;
-
-			}
-		    
-		}
-		
-		out.flush();
-		
-	    }catch(IOException e){
-		agent.markCommunicationsFailure (e,"DDMWriter.writeScalarStream()",
-						 "",
-						 e.getMessage(),
-						 "*");
-		}
-				
-	}
-	
-	/**
-	 * Begins a DSS stream (for writing LOB data).
-	 */
-	private void beginDss (boolean chainedToNextStructure,
-						   int dssType)
-	{
-		beginDss(dssType, false);	// false => don't ensure length.
-
-		// always turn on continuation flags... this is helpful for lobs...
-		// these bytes will get rest if dss lengths are finalized.
-		buffer.putShort(dssLengthLocation, (short) 0xFFFF);
-
-		// Set whether or not this DSS should be chained to
-		// the next one.  If it's chained, it has to be chained
-		// with same id (that's the nature of EXTDTA chaining).
-		if (chainedToNextStructure) {
-			dssType |= DssConstants.GDSCHAIN_SAME_ID;
-		}
+                                      int codePoint,
+                      EXTDTAInputStream in,
+                                      boolean writeNullByte) 
+        throws DRDAProtocolException
+    {
+
+        
+
+        // Stream equivalent of "beginDss"...
+        int spareDssLength = prepScalarStream( chainedWithSameCorrelator,
+                                            codePoint,
+                                            writeNullByte);
+        
+        // write the data
+                try {
+                    
+        OutputStream out = 
+            placeLayerBStreamingBuffer( agent.getOutputStream() );
+        
+        boolean isLastSegment = false;
+        
+        while( !isLastSegment ){
+            
+            if( SanityManager.DEBUG ){
+        
+            if( PropertyUtil.getSystemBoolean("derby.debug.suicideOfLayerBStreaming") )
+                throw new IOException();
+                }
+
+            // read as many bytes as possible directly into the backing array
+            final int offset = buffer.position();
+            final int bytesRead =
+                in.read(buffer.array(), offset,
+                        Math.min(spareDssLength, buffer.remaining()));
+
+            // update the buffer position
+            buffer.position(offset + bytesRead);
+
+            spareDssLength -= bytesRead;
+
+            isLastSegment = peekStream(in) < 0;
+            
+            if(isLastSegment || 
+               spareDssLength == 0){
+            
+            flushScalarStreamSegment (isLastSegment, 
+                          out);
+            
+            if( ! isLastSegment )
+                spareDssLength = DssConstants.MAX_DSS_LENGTH - 2;
+
+            }
+            
+        }
+        
+        out.flush();
+        
+        }catch(IOException e){
+        agent.markCommunicationsFailure (e,"DDMWriter.writeScalarStream()",
+                         "",
+                         e.getMessage(),
+                         "*");
+        }
+                
+    }
+    
+    /**
+     * Begins a DSS stream (for writing LOB data).
+     */
+    private void beginDss (boolean chainedToNextStructure,
+                           int dssType)
+    {
+        beginDss(dssType, false);    // false => don't ensure length.
+
+        // always turn on continuation flags... this is helpful for lobs...
+        // these bytes will get rest if dss lengths are finalized.
+        buffer.putShort(dssLengthLocation, (short) 0xFFFF);
+
+        // Set whether or not this DSS should be chained to
+        // the next one.  If it's chained, it has to be chained
+        // with same id (that's the nature of EXTDTA chaining).
+        if (chainedToNextStructure) {
+            dssType |= DssConstants.GDSCHAIN_SAME_ID;
+        }
 
-		buffer.put(dssLengthLocation + 3, (byte) dssType);
-	}
+        buffer.put(dssLengthLocation + 3, (byte) dssType);
+    }
 
 
     /**
@@ -791,8 +791,8 @@ class DDMWriter
       // Here, 10 stands for sum of headers of layer A and B.
 
       try {
-	    // The existing DSS segment was finalized by endDss; all
-	    // we have to do is send it across the wire.
+        // The existing DSS segment was finalized by endDss; all
+        // we have to do is send it across the wire.
         sendBytes(agent.getOutputStream());
       }
       catch (java.io.IOException e) {
@@ -802,7 +802,7 @@ class DDMWriter
       }
 
     // buildStreamDss should not call ensure length.
-	beginDss(chainedWithSameCorrelator, DssConstants.GDSFMT_OBJDSS);
+    beginDss(chainedWithSameCorrelator, DssConstants.GDSFMT_OBJDSS);
 
       writeLengthCodePoint(0x8004,codePoint);
 
@@ -821,47 +821,47 @@ class DDMWriter
 
   // method to determine if any data is in the request.
   // this indicates there is a dss object already in the buffer.
-	protected boolean doesRequestContainData()
-	{
-		return buffer.position() != 0;
-	}
-
-
-	// Writes out a scalar stream DSS segment, along with DSS continuation
-	// headers if necessary.
-	private void flushScalarStreamSegment ( boolean lastSegment,
-					        OutputStream out)
-		throws DRDAProtocolException
-	{
-
-		// either at end of data, end of dss segment, or both.
-	    if (! lastSegment) {
-
-		// 32k segment filled and not at end of data.
-				try {
-				// Mark current DSS as continued, set its chaining state,
-				// then send the data across.
-					markDssAsContinued(true); 	// true => for lobs
-					sendBytes (out,
-						   false);
-			    
-			}catch (java.io.IOException ioe) {
-					agent.markCommunicationsFailure ("DDMWriter.flushScalarStreamSegment()",
+    protected boolean doesRequestContainData()
+    {
+        return buffer.position() != 0;
+    }
+
+
+    // Writes out a scalar stream DSS segment, along with DSS continuation
+    // headers if necessary.
+    private void flushScalarStreamSegment ( boolean lastSegment,
+                            OutputStream out)
+        throws DRDAProtocolException
+    {
+
+        // either at end of data, end of dss segment, or both.
+        if (! lastSegment) {
+
+        // 32k segment filled and not at end of data.
+                try {
+                // Mark current DSS as continued, set its chaining state,
+                // then send the data across.
+                    markDssAsContinued(true);     // true => for lobs
+                    sendBytes (out,
+                           false);
+                
+            }catch (java.io.IOException ioe) {
+                    agent.markCommunicationsFailure ("DDMWriter.flushScalarStreamSegment()",
                                                "",
                                                ioe.getMessage(),
                                                "*");
-				}
+                }
 
 
-			// Prepare a DSS continuation header for next DSS.
-			dssLengthLocation = buffer.position();
-			buffer.putShort((short) 0xFFFF);
-			isContinuationDss = true;
-	    }else{
-		// we're done writing the data, so end the DSS.
-			endDss();
+            // Prepare a DSS continuation header for next DSS.
+            dssLengthLocation = buffer.position();
+            buffer.putShort((short) 0xFFFF);
+            isContinuationDss = true;
+        }else{
+        // we're done writing the data, so end the DSS.
+            endDss();
 
-	}
+    }
 
   }
 
@@ -874,219 +874,219 @@ class DDMWriter
   void writeLengthCodePoint (int length, int codePoint)
   {
     ensureLength (4);
-	buffer.putShort((short) length);
-	buffer.putShort((short) codePoint);
+    buffer.putShort((short) length);
+    buffer.putShort((short) codePoint);
   }
 
-	/**
-	 * Write scalar object header includes length and codepoint
-	 *
-	 * @param 	codePoint - code point to write
-	 * @param	dataLength - length of object data
-	 */
-	protected void writeScalarHeader (int codePoint, int dataLength)
-	{
-		ensureLength (dataLength + 4);
-		buffer.putShort((short) (dataLength + 4));
-		buffer.putShort((short) codePoint);
-	}
-
-	/**
-	 * Write scalar string object includes length, codepoint and value
-	 * the string is converted into the appropriate codeset (EBCDIC)
-	 *
-	 * @param 	codePoint - code point to write
-	 * @param	string - string to be written
-	 */
-	void writeScalarString (int codePoint, String string)
-	{
-		int stringLength = ccsidManager.getByteLength(string);
-		ensureLength ((stringLength * 2)  + 4);
-		buffer.putShort((short) (stringLength + 4));
-		buffer.putShort((short) codePoint);
-		ccsidManager.convertFromJavaString(string, buffer);
-	}
-
-	/**
-	 * Write padded scalar string object includes length, codepoint and value
-	 * the string is converted into the appropriate codeset (EBCDIC)
-	 *
-	 * @param 	codePoint - code point to write
-	 * @param	string - string to be written
-	 * @param 	paddedLength - length to pad string to
-	 */
-	void writeScalarPaddedString (int codePoint, String string, int paddedLength)
-	{
-		int stringLength = ccsidManager.getByteLength(string);
-		int fillLength = paddedLength - stringLength;
-		ensureLength (paddedLength + 4);
-		buffer.putShort((short) (paddedLength + 4));
-		buffer.putShort((short) codePoint);
-		ccsidManager.convertFromJavaString(string, buffer);
-		padBytes(ccsidManager.space, fillLength);
-	}
-
-	/**
-	 * Write padded scalar <code>DRDAString</code> object value. The
-	 * string is converted into the appropriate codeset.
-	 *
-	 * @param drdaString string to be written
-	 * @param paddedLength length to pad string to
-	 */
-	protected void writeScalarPaddedString (DRDAString drdaString, int paddedLength)
-	{
-	    /* This .length() call is valid as this is a DRDAString */
-		int stringLength = drdaString.length();
-		int fillLength = paddedLength - stringLength;
-		ensureLength(paddedLength);
-		buffer.put(drdaString.getBytes(), 0, stringLength);
-		padBytes(ccsidManager.space, fillLength);
-	}
-
-	/**
-	 * Write padded scalar byte array object includes length, codepoint and value
-	 *
-	 * @param 	codePoint - code point to write
-	 * @param	buf - byte array to be written
-	 * @param 	paddedLength - length to pad string to
-	 * @param	padByte - byte to be used for padding
-	 */
-	protected void writeScalarPaddedBytes (int codePoint, byte[] buf, int paddedLength, byte padByte)
-	{
-		ensureLength (paddedLength + 4);
-		buffer.putShort((short) (paddedLength + 4));
-		buffer.putShort((short) codePoint);
-		buffer.put(buf);
-		padBytes(padByte, paddedLength - buf.length);
-	}
-
-	/**
-	 * Write padded scalar byte array object  value
-	 *
-	 * @param	buf - byte array to be written
-	 * @param 	paddedLength - length to pad string to
-	 * @param	padByte - byte to be used for padding
-	 */
-	protected void writeScalarPaddedBytes (byte[] buf, int paddedLength, byte padByte)
-	{
-		ensureLength (paddedLength);
-		buffer.put(buf);
-		padBytes(padByte, paddedLength - buf.length);
-	}
-
-	/**
-	 * Write scalar byte array object includes length, codepoint and value
-	 *
-	 * @param 	codePoint - code point to write
-	 * @param	buf - byte array to be written
-	 */
-	protected void writeScalarBytes (int codePoint, byte[] buf)
-	{
-		ensureLength(buf.length + 4);
-		buffer.putShort((short) (buf.length + 4));
-		buffer.putShort((short) codePoint);
-		buffer.put(buf);
-	}
-
-	// The following methods write data in the platform format
-	// The platform format was indicated during connection time as ASC since
-	// JCC doesn't read JVM platform (yet)
-
-	/**
-	 * Write platform short
-	 *
-	 * @param 	v	value to be written
-	 */
-	protected void writeShort (int v)
-	{
-		writeNetworkShort(v);
-	}
-
-	/**
-	 * Write boolean as short
-	 * @param b boolean value true = 1 false = 0
-	 *
-	 */
-	protected void writeShort(boolean b)
-	{
-		writeNetworkShort(b ? 1 : 0);
-	}
-
-	/**
-	 * Write platform int
-	 *
-	 * @param 	v	value to be written
-	 */
-	protected void writeInt (int v)
-	{
-		writeNetworkInt(v);
-	}
-
-	/**
-	 * Write platform long
-	 *
-	 * @param 	v	value to be written
-	 */
-	protected void writeLong (long v)
-	{
-		ensureLength (8);
-		buffer.putLong(v);
-	}
-
-	/**
-	 * Write platform float
-	 *
-	 * @param 	v	value to be written
-	 */
-	protected void writeFloat (float v)
-	{
-		writeInt (Float.floatToIntBits (v));
-	}
-
-	/**
-	 * Write platform double
-	 *
-	 * @param 	v	value to be written
-	 */
-	protected void writeDouble (double v)
-	{
-		writeLong (Double.doubleToLongBits (v));
-	}
-
-	/**
-	 * Write platform boolean
-	 *
-	 * @param 	v	value to be written
-	 */
-	protected void writeBoolean (boolean v)
-	{
-		writeByte(v ? 1 : 0);
-	}
-
-	/**
-	 * Write length delimited string
-	 *
-	 * @param s value to be written with integer
-	 *
-	 * @exception DRDAProtocolException
-	 */
-	protected void writeLDString(String s) throws DRDAProtocolException
-	{
-		writeLDString(s, 0, null, false);
-	}
-
-	/**
-	 * Write a value of a user defined type.
-	 *
-	 * @param val object to be written
-	 *
-	 * @exception DRDAProtocolException
-	 */
-	protected void writeUDT( Object val, int index ) throws DRDAProtocolException
-	{
+    /**
+     * Write scalar object header includes length and codepoint
+     *
+     * @param     codePoint - code point to write
+     * @param    dataLength - length of object data
+     */
+    protected void writeScalarHeader (int codePoint, int dataLength)
+    {
+        ensureLength (dataLength + 4);
+        buffer.putShort((short) (dataLength + 4));
+        buffer.putShort((short) codePoint);
+    }
+
+    /**
+     * Write scalar string object includes length, codepoint and value
+     * the string is converted into the appropriate codeset (EBCDIC)
+     *
+     * @param     codePoint - code point to write
+     * @param    string - string to be written
+     */
+    void writeScalarString (int codePoint, String string)
+    {
+        int stringLength = ccsidManager.getByteLength(string);
+        ensureLength ((stringLength * 2)  + 4);
+        buffer.putShort((short) (stringLength + 4));
+        buffer.putShort((short) codePoint);
+        ccsidManager.convertFromJavaString(string, buffer);
+    }
+
+    /**
+     * Write padded scalar string object includes length, codepoint and value
+     * the string is converted into the appropriate codeset (EBCDIC)
+     *
+     * @param     codePoint - code point to write
+     * @param    string - string to be written
+     * @param     paddedLength - length to pad string to
+     */
+    void writeScalarPaddedString (int codePoint, String string, int paddedLength)
+    {
+        int stringLength = ccsidManager.getByteLength(string);
+        int fillLength = paddedLength - stringLength;
+        ensureLength (paddedLength + 4);
+        buffer.putShort((short) (paddedLength + 4));
+        buffer.putShort((short) codePoint);
+        ccsidManager.convertFromJavaString(string, buffer);
+        padBytes(ccsidManager.space, fillLength);
+    }
+
+    /**
+     * Write padded scalar <code>DRDAString</code> object value. The
+     * string is converted into the appropriate codeset.
+     *
+     * @param drdaString string to be written
+     * @param paddedLength length to pad string to
+     */
+    protected void writeScalarPaddedString (DRDAString drdaString, int paddedLength)
+    {
+        /* This .length() call is valid as this is a DRDAString */
+        int stringLength = drdaString.length();
+        int fillLength = paddedLength - stringLength;
+        ensureLength(paddedLength);
+        buffer.put(drdaString.getBytes(), 0, stringLength);
+        padBytes(ccsidManager.space, fillLength);
+    }
+
+    /**
+     * Write padded scalar byte array object includes length, codepoint and value
+     *
+     * @param     codePoint - code point to write
+     * @param    buf - byte array to be written
+     * @param     paddedLength - length to pad string to
+     * @param    padByte - byte to be used for padding
+     */
+    protected void writeScalarPaddedBytes (int codePoint, byte[] buf, int paddedLength, byte padByte)
+    {
+        ensureLength (paddedLength + 4);
+        buffer.putShort((short) (paddedLength + 4));
+        buffer.putShort((short) codePoint);
+        buffer.put(buf);
+        padBytes(padByte, paddedLength - buf.length);
+    }
+
+    /**
+     * Write padded scalar byte array object  value
+     *
+     * @param    buf - byte array to be written
+     * @param     paddedLength - length to pad string to
+     * @param    padByte - byte to be used for padding
+     */
+    protected void writeScalarPaddedBytes (byte[] buf, int paddedLength, byte padByte)
+    {
+        ensureLength (paddedLength);
+        buffer.put(buf);
+        padBytes(padByte, paddedLength - buf.length);
+    }
+
+    /**
+     * Write scalar byte array object includes length, codepoint and value
+     *
+     * @param     codePoint - code point to write
+     * @param    buf - byte array to be written
+     */
+    protected void writeScalarBytes (int codePoint, byte[] buf)
+    {
+        ensureLength(buf.length + 4);
+        buffer.putShort((short) (buf.length + 4));
+        buffer.putShort((short) codePoint);
+        buffer.put(buf);
+    }
+
+    // The following methods write data in the platform format
+    // The platform format was indicated during connection time as ASC since
+    // JCC doesn't read JVM platform (yet)
+
+    /**
+     * Write platform short
+     *
+     * @param     v    value to be written
+     */
+    protected void writeShort (int v)
+    {
+        writeNetworkShort(v);
+    }
+
+    /**
+     * Write boolean as short
+     * @param b boolean value true = 1 false = 0
+     *
+     */
+    protected void writeShort(boolean b)
+    {
+        writeNetworkShort(b ? 1 : 0);
+    }
+
+    /**
+     * Write platform int
+     *
+     * @param     v    value to be written
+     */
+    protected void writeInt (int v)
+    {
+        writeNetworkInt(v);
+    }
+
+    /**
+     * Write platform long
+     *
+     * @param     v    value to be written
+     */
+    protected void writeLong (long v)
+    {
+        ensureLength (8);
+        buffer.putLong(v);
+    }
+
+    /**
+     * Write platform float
+     *
+     * @param     v    value to be written
+     */
+    protected void writeFloat (float v)
+    {
+        writeInt (Float.floatToIntBits (v));
+    }
+
+    /**
+     * Write platform double
+     *
+     * @param     v    value to be written
+     */
+    protected void writeDouble (double v)
+    {
+        writeLong (Double.doubleToLongBits (v));
+    }
+
+    /**
+     * Write platform boolean
+     *
+     * @param     v    value to be written
+     */
+    protected void writeBoolean (boolean v)
+    {
+        writeByte(v ? 1 : 0);
+    }
+
+    /**
+     * Write length delimited string
+     *
+     * @param s value to be written with integer
+     *
+     * @exception DRDAProtocolException
+     */
+    protected void writeLDString(String s) throws DRDAProtocolException
+    {
+        writeLDString(s, 0, null, false);
+    }
+
+    /**
+     * Write a value of a user defined type.
+     *
+     * @param val object to be written
+     *
+     * @exception DRDAProtocolException
+     */
+    protected void writeUDT( Object val, int index ) throws DRDAProtocolException
+    {
         // should not be called if val is null
-		if (SanityManager.DEBUG)
-		{
+        if (SanityManager.DEBUG)
+        {
             if ( val == null )
             {
                 SanityManager.THROWASSERT( "UDT is null" );
@@ -1121,42 +1121,42 @@ class DDMWriter
             writeShort( length );
             writeBytes( buffer, 0, length );
         }
-	}
+    }
 
-	/**
-	 * Find the maximum number of bytes needed to represent the string in the
-	 * default encoding.
-	 *
-	 * @param s the string to encode
-	 * @return an upper limit for the number of bytes needed to encode the
-	 * string
-	 */
-	private int maxEncodedLength(String s) {
-		// maxBytesPerChar() returns a float, which can only hold 24 bits of an
-		// integer. Therefore, promote the float to a double so that all bits
-		// are preserved in the intermediate result.
-		return (int) (s.length() * (double) encoder.maxBytesPerChar());
-	}
-
-	/**
-	 * Write length delimited string
-	 *
-	 * @param s              value to be written with integer
-	 * @param index          column index to put in warning
+    /**
+     * Find the maximum number of bytes needed to represent the string in the
+     * default encoding.
+     *
+     * @param s the string to encode
+     * @return an upper limit for the number of bytes needed to encode the
+     * string
+     */
+    private int maxEncodedLength(String s) {
+        // maxBytesPerChar() returns a float, which can only hold 24 bits of an
+        // integer. Therefore, promote the float to a double so that all bits
+        // are preserved in the intermediate result.
+        return (int) (s.length() * (double) encoder.maxBytesPerChar());
+    }
+
+    /**
+     * Write length delimited string
+     *
+     * @param s              value to be written with integer
+     * @param index          column index to put in warning
      * @param stmt           the executing statement (null if not invoked as
      *                       part of statement execution)
      * @param isParameter    true if the value written is for an output
      *                       parameter in a procedure call
-	 * @exception DRDAProtocolException
-	 */
-	protected void writeLDString(String s, int index, DRDAStatement stmt,
+     * @exception DRDAProtocolException
+     */
+    protected void writeLDString(String s, int index, DRDAStatement stmt,
                                  boolean isParameter)
             throws DRDAProtocolException
-	{
-		// Position on which to write the length of the string (in bytes). The
-		// actual writing of the length is delayed until we have encoded the
-		// string.
-		final int lengthPos = buffer.position();
+    {
+        // Position on which to write the length of the string (in bytes). The
+        // actual writing of the length is delayed until we have encoded the
+        // string.
+        final int lengthPos = buffer.position();
 
         // Reserve two bytes for the length field and move the position to
         // where the string should be inserted.
@@ -1223,7 +1223,7 @@ class DDMWriter
 
         // Go back and write the length in bytes.
         buffer.putShort(lengthPos, (short) byteLength);
-	}
+    }
 
     /**
      * Check if a byte value represents a continuation byte in a UTF-8 byte
@@ -1240,364 +1240,364 @@ class DDMWriter
         return (b & 0xC0) == 0x80;
     }
 
-	/**
-	 * Write string with default encoding
-	 *
-	 * @param s value to be written
-	 *
-	 * @exception DRDAProtocolException
-	 */
-	protected void writeString(String s) throws DRDAProtocolException
-	{
-		ensureLength(maxEncodedLength(s));
-		CharBuffer input = CharBuffer.wrap(s);
-		encoder.reset();
-		CoderResult res = encoder.encode(input, buffer, true);
-		if (res == CoderResult.UNDERFLOW) {
-			res = encoder.flush(buffer);
-		}
-		if (SanityManager.DEBUG) {
-			SanityManager.ASSERT(res == CoderResult.UNDERFLOW,
-								 "CharBuffer was not exhausted: res = " + res);
-		}
-	}
-
-	/**
-	 * Write pad bytes using spaceChar
-	 *
-	 * @param   val	value to be written
-	 * @param	length		length to be written
-	 */
-	protected void padBytes (byte val, int length)
-	{
-		final int offset = buffer.position();
-		final int end = offset + length;
-		Arrays.fill(buffer.array(), offset, end, val);
-		buffer.position(end);
-	}
-
-	/**
-	 * Flush buffer to outputstream
-	 *
-	 *
-	 * @exception IOException
-	 */
-	protected void flush () throws java.io.IOException
-	{
-		flush(agent.getOutputStream());
-	}
-
-	/**
-	 * Flush buffer to specified stream
-	 *
-	 * @param socketOutputStream
-	 *
-	 * @exception IOException
-	 */
-	protected void flush(OutputStream socketOutputStream)
-		throws java.io.IOException
-	{
-		final byte[] bytes = buffer.array();
-		final int length = buffer.position();
-		try {
-			socketOutputStream.write (bytes, 0, length);
-			socketOutputStream.flush();
-		}
-		finally {
-			if ((dssTrace != null) && dssTrace.isComBufferTraceOn()) {
-			  dssTrace.writeComBufferData (bytes,
-			                               0,
+    /**
+     * Write string with default encoding
+     *
+     * @param s value to be written
+     *
+     * @exception DRDAProtocolException
+     */
+    protected void writeString(String s) throws DRDAProtocolException
+    {
+        ensureLength(maxEncodedLength(s));
+        CharBuffer input = CharBuffer.wrap(s);
+        encoder.reset();
+        CoderResult res = encoder.encode(input, buffer, true);
+        if (res == CoderResult.UNDERFLOW) {
+            res = encoder.flush(buffer);
+        }
+        if (SanityManager.DEBUG) {
+            SanityManager.ASSERT(res == CoderResult.UNDERFLOW,
+                                 "CharBuffer was not exhausted: res = " + res);
+        }
+    }
+
+    /**
+     * Write pad bytes using spaceChar
+     *
+     * @param   val    value to be written
+     * @param    length        length to be written
+     */
+    protected void padBytes (byte val, int length)
+    {
+        final int offset = buffer.position();
+        final int end = offset + length;
+        Arrays.fill(buffer.array(), offset, end, val);
+        buffer.position(end);
+    }
+
+    /**
+     * Flush buffer to outputstream
+     *
+     *
+     * @exception IOException
+     */
+    protected void flush () throws java.io.IOException
+    {
+        flush(agent.getOutputStream());
+    }
+
+    /**
+     * Flush buffer to specified stream
+     *
+     * @param socketOutputStream
+     *
+     * @exception IOException
+     */
+    protected void flush(OutputStream socketOutputStream)
+        throws java.io.IOException
+    {
+        final byte[] bytes = buffer.array();
+        final int length = buffer.position();
+        try {
+            socketOutputStream.write (bytes, 0, length);
+            socketOutputStream.flush();
+        }
+        finally {
+            if ((dssTrace != null) && dssTrace.isComBufferTraceOn()) {
+              dssTrace.writeComBufferData (bytes,
+                                           0,
                                            length,
-			                               DssTrace.TYPE_TRACE_SEND,
-			                               "Reply",
-			                               "flush",
-			                               5);
-			}
-			reset(dssTrace);
-		}
+                                           DssTrace.TYPE_TRACE_SEND,
+                                           "Reply",
+                                           "flush",
+                                           5);
+            }
+            reset(dssTrace);
+        }
         totalByteCount += length;
-	}
+    }
 
-	// private methods
+    // private methods
 
-	/**
-	 * Write DSS header
-	 * DSS Header format is
-	 * 	2 bytes	- length
-	 *	1 byte	- 'D0'	- indicates DDM data
-	 * 	1 byte	- DSS format
-	 *		|---|---------|----------|
-	 *		| 0	|	flags |	type     |
-	 *		|---|---------|----------|
-	 *		| 0 | 1	2	3 | 4 5 6 7	 |
-	 *		|---|---------|----------|
-	 *		bit 0 - '0'
-	 *		bit 1 - '0' - unchained, '1' - chained
-	 *		bit 2 - '0'	- do not continue on error, '1' - continue on error
-	 *		bit 3 - '0' - next DSS has different correlator, '1' - next DSS has
-	 *						same correlator
-	 *		type - 1 - Request DSS
-	 *			 - 2 - Reply DSS
-	 *			 - 3 - Object DSS
-	 *			 - 4 - Communications DSS
-	 *			 - 5 - Request DSS where no reply is expected
-	 */
-	private void beginDss (int dssType, boolean ensureLen)
-	{
-
-		// save length position, the length will be written at the end
-		dssLengthLocation = buffer.position();
-
-		// Should this really only be for non-stream DSSes?
-		if (ensureLen)
-			ensureLength(6);
-
-		// Skip past length; we'll come back and set it later.
-		buffer.position(dssLengthLocation + 2);
-
-		// write gds info
-		buffer.put((byte) 0xD0);
-
-		// Write DSS type, and default chain bit to be 
-		// DssConstants.DSSCHAIN_SAME_ID.  This default
-		// will be overridden by calls to "finalizeChain()"
-		// and/or calls to "beginDss(boolean, int)" for
-		// writing LOB data.
-		buffer.put((byte) (dssType | DssConstants.DSSCHAIN_SAME_ID));
-
-		// save correlationID for use in error messages while processing
-		// this DSS
-		correlationID = getCorrelationID();
-
-		// write the reply correlation id
-		buffer.putShort((short) correlationID);
-	}
+    /**
+     * Write DSS header
+     * DSS Header format is
+     *     2 bytes    - length
+     *    1 byte    - 'D0'    - indicates DDM data
+     *     1 byte    - DSS format
+     *        |---|---------|----------|
+     *        | 0    |    flags |    type     |
+     *        |---|---------|----------|
+     *        | 0 | 1    2    3 | 4 5 6 7     |
+     *        |---|---------|----------|
+     *        bit 0 - '0'
+     *        bit 1 - '0' - unchained, '1' - chained
+     *        bit 2 - '0'    - do not continue on error, '1' - continue on error
+     *        bit 3 - '0' - next DSS has different correlator, '1' - next DSS has
+     *                        same correlator
+     *        type - 1 - Request DSS
+     *             - 2 - Reply DSS
+     *             - 3 - Object DSS
+     *             - 4 - Communications DSS
+     *             - 5 - Request DSS where no reply is expected
+     */
+    private void beginDss (int dssType, boolean ensureLen)
+    {
 
-	/**
+        // save length position, the length will be written at the end
+        dssLengthLocation = buffer.position();
+
+        // Should this really only be for non-stream DSSes?
+        if (ensureLen)
+            ensureLength(6);
+
+        // Skip past length; we'll come back and set it later.
+        buffer.position(dssLengthLocation + 2);
+
+        // write gds info
+        buffer.put((byte) 0xD0);
+
+        // Write DSS type, and default chain bit to be 
+        // DssConstants.DSSCHAIN_SAME_ID.  This default
+        // will be overridden by calls to "finalizeChain()"
+        // and/or calls to "beginDss(boolean, int)" for
+        // writing LOB data.
+        buffer.put((byte) (dssType | DssConstants.DSSCHAIN_SAME_ID));
+
+        // save correlationID for use in error messages while processing
+        // this DSS
+        correlationID = getCorrelationID();
+
+        // write the reply correlation id
+        buffer.putShort((short) correlationID);
+    }
+
+    /**
      * Finish a DSS Layer A object.
-	 * The length of dss object will be calculated based on the difference between the
-	 * start of the dss, saved on the beginDss call, and the current
-	 * offset into the buffer which marks the end of the data.	In the event
-	 * the length requires the use of continuation Dss headers, one for each 32k
-	 * chunk of data, the data will be shifted and the continuation headers
-	 * will be inserted with the correct values as needed.
-	 */
-	private void finalizeDssLength ()
-	{
-		// initial position in the byte buffer
-		final int offset = buffer.position();
-
-		// calculate the total size of the dss and the number of bytes which would
-		// require continuation dss headers.	The total length already includes the
-		// the 6 byte dss header located at the beginning of the dss.	It does not
-		// include the length of any continuation headers.
-		int totalSize = offset - dssLengthLocation;
-		int bytesRequiringContDssHeader = totalSize - DssConstants.MAX_DSS_LENGTH;
-
-		// determine if continuation headers are needed
-		if (bytesRequiringContDssHeader > 0)
-		{
-			// the continuation headers are needed, so calculate how many.
-			// after the first 32767 worth of data, a continuation header is
-			// needed for every 32765 bytes (32765 bytes of data + 2 bytes of
-			// continuation header = 32767 Dss Max Size).
-			int contDssHeaderCount = bytesRequiringContDssHeader / 32765;
-			if (bytesRequiringContDssHeader % 32765 != 0)
-				contDssHeaderCount++;
-
-			// right now the code will shift to the right.	In the future we may want
-			// to try something fancier to help reduce the copying (maybe keep
-			// space in the beginning of the buffer??).
-			// the offset points to the next available offset in the buffer to place
-			// a piece of data, so the last dataByte is at offset -1.
-			// various bytes will need to be shifted by different amounts
-			// depending on how many dss headers to insert so the amount to shift
-			// will be calculated and adjusted as needed.	ensure there is enough room
-			// for all the conutinuation headers and adjust the offset to point to the
-			// new end of the data.
-			int dataByte = offset - 1;
-			int shiftSize = contDssHeaderCount * 2;
-			ensureLength (shiftSize);
-
-			// We're going to access the buffer with absolute positions, so
-			// just move the current position pointer right away to where it's
-			// supposed to be after we have finished the shifting.
-			buffer.position(offset + shiftSize);
-
-			// Notes on the behavior of the Layer B segmenting loop below:
-			//
-			// We start with the right most chunk. For a 3-segment object we'd
-			// shift 2 segments: shift the first (rightmost) one 4 bytes and 
-			// the second one 2. Note that by 'first' we mean 'first time
-			// through the loop', but that is actually the last segment
-			// of data since we are moving right-to-left. For an object
-			// of K segments we will pass through this loop K-1 times.
-			// The 0th (leftmost) segment is not shifted, as it is
-			// already in the right place. When we are done, we will
-			// have made room in each segment for an additional
-			// 2 bytes for the continuation header. Thus, each
-			// segment K is shifted K*2 bytes to the right.
-			//
-			// Each time through the loop, "dataByte" points to the
-			// last byte in the segment; "dataToShift" is the amount of
-			// data that we need to shift, and "shiftSize" is the
-			// distance that we need to shift it. Since dataByte points
-			// at the last byte, not one byte beyond it (as with the
-			// "offset" variable used elsewhere in DDMWriter), the start
-			// of the segement is actually at (dataByte-dataToShift+1).
-			//
-			// After we have shifted the segment, we move back to the
-			// start of the segment and set the value of the 2-byte DSS
-			// continuation header, which needs to hold the length of
-			// this segment's data, together with the continuation flag
-			// if this is not the rightmost (passOne) segment.
-			//
-			// In general, each segment except the rightmost will contain
-			// 32765 bytes of data, plus the 2-byte header, and its
-			// continuation flag will be set, so the header value will
-			// be 0xFFFF. The rightmost segment will not have the
-			// continuation flag set, so its value may be anything from
-			// 0x0001 to 0x7FFF, depending on the amount of data in that
-			// segment.
-			//
-			// Note that the 0th (leftmost) segment also has a 2-byte
-			// DSS header, which needs to have its continuation flag set.
-			// This is done by resetting the "totalSize" variable below,
-			// at which point that variable no longer holds the total size
-			// of the object, but rather just the length of segment 0. The
-			// total size of the object was written using extended length
-			// bytes by the endDdm() method earlier.
-			//
-			// Additional information about this routine is available in the
-			// bug notes for DERBY-125:
-			// http://issues.apache.org/jira/browse/DERBY-125
-			
-			// mark passOne to help with calculating the length of the final (first or
-			// rightmost) continuation header.
-			boolean passOne = true;
-			do {
-				// calculate chunk of data to shift
-				int dataToShift = bytesRequiringContDssHeader % 32765;
-				if (dataToShift == 0)
-					dataToShift = 32765;
-				int startOfCopyData = dataByte - dataToShift + 1;
-				// perform the shift directly on the backing array
-				final byte[] bytes = buffer.array();
-				System.arraycopy(bytes,startOfCopyData, bytes, 
-								 startOfCopyData + shiftSize, dataToShift);
-				dataByte -= dataToShift;
-
-
-				// calculate the value the value of the 2 byte continuation dss
-				// header which includes the length of itself.  On the first pass,
-				// if the length is 32767
-				// we do not want to set the continuation dss header flag.
-				int twoByteContDssHeader = dataToShift + 2;
-				if (passOne)
-					passOne = false;
-				else
-				{
-					if (twoByteContDssHeader == DssConstants.MAX_DSS_LENGTH)
-					twoByteContDssHeader = (twoByteContDssHeader |
-						DssConstants.CONTINUATION_BIT);
-
-				}
-
-				// insert the header's length bytes
-				buffer.putShort(dataByte + shiftSize - 1,
-								(short) twoByteContDssHeader);
-
-				// adjust the bytesRequiringContDssHeader and the amount to shift for
-				// data in upstream headers.
-				bytesRequiringContDssHeader -= dataToShift;
-				shiftSize -= 2;
-
-				// shift and insert another header for more data.
-			}
-			while (bytesRequiringContDssHeader > 0);
-
-			// set the continuation dss header flag on for the first header
-			totalSize = (DssConstants.MAX_DSS_LENGTH |
-					DssConstants.CONTINUATION_BIT);
-
-
-		}
-
-		// insert the length bytes in the 6 byte dss header.
-		buffer.putShort(dssLengthLocation, (short) totalSize);
-	}
-
-	protected void writeExtendedLength(long size)
-	{
-		int numbytes = calculateExtendedLengthByteCount(size);
-		if (size > 0)
-			writeInt(0x8000 | numbytes);
-		else
-			writeInt(numbytes);
-	}
-
-
-	/**
-	 * Calculate extended length byte count which follows the DSS header
-	 * for extended DDM.
-	 *
-	 * @param ddmSize - size of DDM command
-	 * @return minimum number of extended length bytes needed. 0 indicates no
-	 * 	extended length needed.
-	 */
-	private int calculateExtendedLengthByteCount (long ddmSize)
-	{
-		if (ddmSize <= 0x7fff)
-			return 0;
-		// JCC does not support 2 at this time, so we always send
-		// at least 4
-		//		else if (ddmSize <= 0xffff)
-		//	return 2;
-		else if (ddmSize <= 0xffffffffL)
-			return 4;
-		else if (ddmSize <= 0xffffffffffffL)
-			return 6;
-		else if (ddmSize <= 0x7fffffffffffffffL)
-			return 8;
-		else
-			// shouldn't happen
-			// XXX - add sanity debug stuff here
-			return 0;
-	}
-
-	/**
-	 * Ensure that there is space in the buffer
-	 *
-	 * @param length space required
-	 */
-	private void ensureLength (int length)
-	{
-		if (buffer.remaining() < length) {
-			if (SanityManager.DEBUG)
-			{
-				agent.trace("DANGER - Expensive expansion of  buffer");
-			}
-			int newLength =
-				Math.max(buffer.capacity() * 2, buffer.position() + length);
-			// copy the old buffer into a new one
-			buffer.flip();
-			buffer = ByteBuffer.allocate(newLength).put(buffer);
-		}
-	}
-
-
-	/**
-	 * Write a Java <code>java.math.BigDecimal</code> to packed decimal bytes.
-	 *
-	 * @param b BigDecimal to write
-	 * @param precision Precision of decimal or numeric type
-	 * @param scale declared scale
-	 *
-	 * @exception SQLException Thrown if # digits > 31
-	 */
-	void writeBigDecimal(BigDecimal b, int precision, int scale)
-	throws SQLException
-	{
+     * The length of dss object will be calculated based on the difference between the
+     * start of the dss, saved on the beginDss call, and the current
+     * offset into the buffer which marks the end of the data.    In the event
+     * the length requires the use of continuation Dss headers, one for each 32k
+     * chunk of data, the data will be shifted and the continuation headers
+     * will be inserted with the correct values as needed.
+     */
+    private void finalizeDssLength ()
+    {
+        // initial position in the byte buffer
+        final int offset = buffer.position();
+
+        // calculate the total size of the dss and the number of bytes which would
+        // require continuation dss headers.    The total length already includes the
+        // the 6 byte dss header located at the beginning of the dss.    It does not
+        // include the length of any continuation headers.
+        int totalSize = offset - dssLengthLocation;
+        int bytesRequiringContDssHeader = totalSize - DssConstants.MAX_DSS_LENGTH;
+
+        // determine if continuation headers are needed
+        if (bytesRequiringContDssHeader > 0)
+        {
+            // the continuation headers are needed, so calculate how many.
+            // after the first 32767 worth of data, a continuation header is
+            // needed for every 32765 bytes (32765 bytes of data + 2 bytes of
+            // continuation header = 32767 Dss Max Size).
+            int contDssHeaderCount = bytesRequiringContDssHeader / 32765;
+            if (bytesRequiringContDssHeader % 32765 != 0)
+                contDssHeaderCount++;
+
+            // right now the code will shift to the right.    In the future we may want
+            // to try something fancier to help reduce the copying (maybe keep
+            // space in the beginning of the buffer??).
+            // the offset points to the next available offset in the buffer to place
+            // a piece of data, so the last dataByte is at offset -1.
+            // various bytes will need to be shifted by different amounts
+            // depending on how many dss headers to insert so the amount to shift
+            // will be calculated and adjusted as needed.    ensure there is enough room
+            // for all the conutinuation headers and adjust the offset to point to the
+            // new end of the data.
+            int dataByte = offset - 1;
+            int shiftSize = contDssHeaderCount * 2;
+            ensureLength (shiftSize);
+
+            // We're going to access the buffer with absolute positions, so
+            // just move the current position pointer right away to where it's
+            // supposed to be after we have finished the shifting.
+            buffer.position(offset + shiftSize);
+
+            // Notes on the behavior of the Layer B segmenting loop below:
+            //
+            // We start with the right most chunk. For a 3-segment object we'd
+            // shift 2 segments: shift the first (rightmost) one 4 bytes and 
+            // the second one 2. Note that by 'first' we mean 'first time
+            // through the loop', but that is actually the last segment
+            // of data since we are moving right-to-left. For an object
+            // of K segments we will pass through this loop K-1 times.
+            // The 0th (leftmost) segment is not shifted, as it is
+            // already in the right place. When we are done, we will
+            // have made room in each segment for an additional
+            // 2 bytes for the continuation header. Thus, each
+            // segment K is shifted K*2 bytes to the right.
+            //
+            // Each time through the loop, "dataByte" points to the
+            // last byte in the segment; "dataToShift" is the amount of
+            // data that we need to shift, and "shiftSize" is the
+            // distance that we need to shift it. Since dataByte points
+            // at the last byte, not one byte beyond it (as with the
+            // "offset" variable used elsewhere in DDMWriter), the start
+            // of the segement is actually at (dataByte-dataToShift+1).
+            //
+            // After we have shifted the segment, we move back to the
+            // start of the segment and set the value of the 2-byte DSS
+            // continuation header, which needs to hold the length of
+            // this segment's data, together with the continuation flag
+            // if this is not the rightmost (passOne) segment.
+            //
+            // In general, each segment except the rightmost will contain
+            // 32765 bytes of data, plus the 2-byte header, and its
+            // continuation flag will be set, so the header value will
+            // be 0xFFFF. The rightmost segment will not have the
+            // continuation flag set, so its value may be anything from
+            // 0x0001 to 0x7FFF, depending on the amount of data in that
+            // segment.
+            //
+            // Note that the 0th (leftmost) segment also has a 2-byte
+            // DSS header, which needs to have its continuation flag set.
+            // This is done by resetting the "totalSize" variable below,
+            // at which point that variable no longer holds the total size
+            // of the object, but rather just the length of segment 0. The
+            // total size of the object was written using extended length
+            // bytes by the endDdm() method earlier.
+            //
+            // Additional information about this routine is available in the
+            // bug notes for DERBY-125:
+            // http://issues.apache.org/jira/browse/DERBY-125
+            
+            // mark passOne to help with calculating the length of the final (first or
+            // rightmost) continuation header.
+            boolean passOne = true;
+            do {
+                // calculate chunk of data to shift
+                int dataToShift = bytesRequiringContDssHeader % 32765;
+                if (dataToShift == 0)
+                    dataToShift = 32765;
+                int startOfCopyData = dataByte - dataToShift + 1;
+                // perform the shift directly on the backing array
+                final byte[] bytes = buffer.array();
+                System.arraycopy(bytes,startOfCopyData, bytes, 
+                                 startOfCopyData + shiftSize, dataToShift);
+                dataByte -= dataToShift;
+
+
+                // calculate the value the value of the 2 byte continuation dss
+                // header which includes the length of itself.  On the first pass,
+                // if the length is 32767
+                // we do not want to set the continuation dss header flag.
+                int twoByteContDssHeader = dataToShift + 2;
+                if (passOne)
+                    passOne = false;
+                else
+                {
+                    if (twoByteContDssHeader == DssConstants.MAX_DSS_LENGTH)
+                    twoByteContDssHeader = (twoByteContDssHeader |
+                        DssConstants.CONTINUATION_BIT);
+
+                }
+
+                // insert the header's length bytes
+                buffer.putShort(dataByte + shiftSize - 1,
+                                (short) twoByteContDssHeader);
+
+                // adjust the bytesRequiringContDssHeader and the amount to shift for
+                // data in upstream headers.
+                bytesRequiringContDssHeader -= dataToShift;
+                shiftSize -= 2;
+
+                // shift and insert another header for more data.
+            }
+            while (bytesRequiringContDssHeader > 0);
+
+            // set the continuation dss header flag on for the first header
+            totalSize = (DssConstants.MAX_DSS_LENGTH |
+                    DssConstants.CONTINUATION_BIT);
+
+
+        }
+
+        // insert the length bytes in the 6 byte dss header.
+        buffer.putShort(dssLengthLocation, (short) totalSize);
+    }
+
+    protected void writeExtendedLength(long size)
+    {
+        int numbytes = calculateExtendedLengthByteCount(size);
+        if (size > 0)
+            writeInt(0x8000 | numbytes);
+        else
+            writeInt(numbytes);
+    }
+
+
+    /**
+     * Calculate extended length byte count which follows the DSS header
+     * for extended DDM.
+     *
+     * @param ddmSize - size of DDM command
+     * @return minimum number of extended length bytes needed. 0 indicates no
+     *     extended length needed.
+     */
+    private int calculateExtendedLengthByteCount (long ddmSize)
+    {
+        if (ddmSize <= 0x7fff)
+            return 0;
+        // JCC does not support 2 at this time, so we always send
+        // at least 4
+        //        else if (ddmSize <= 0xffff)
+        //    return 2;
+        else if (ddmSize <= 0xffffffffL)
+            return 4;
+        else if (ddmSize <= 0xffffffffffffL)
+            return 6;
+        else if (ddmSize <= 0x7fffffffffffffffL)
+            return 8;
+        else
+            // shouldn't happen
+            // XXX - add sanity debug stuff here
+            return 0;
+    }
+
+    /**
+     * Ensure that there is space in the buffer
+     *
+     * @param length space required
+     */
+    private void ensureLength (int length)
+    {
+        if (buffer.remaining() < length) {
+            if (SanityManager.DEBUG)
+            {
+                agent.trace("DANGER - Expensive expansion of  buffer");
+            }
+            int newLength =
+                Math.max(buffer.capacity() * 2, buffer.position() + length);
+            // copy the old buffer into a new one
+            buffer.flip();
+            buffer = ByteBuffer.allocate(newLength).put(buffer);
+        }
+    }
+
+
+    /**
+     * Write a Java <code>java.math.BigDecimal</code> to packed decimal bytes.
+     *
+     * @param b BigDecimal to write
+     * @param precision Precision of decimal or numeric type
+     * @param scale declared scale
+     *
+     * @exception SQLException Thrown if # digits > 31
+     */
+    void writeBigDecimal(BigDecimal b, int precision, int scale)
+    throws SQLException
+    {
         final int encodedLength = precision / 2 + 1;
         ensureLength(encodedLength);
 
@@ -1607,45 +1607,45 @@ class DDMWriter
         // Move current position to the end of the encoded decimal.
         buffer.position(offset + encodedLength);
 
-		int declaredPrecision = precision;
-		int declaredScale = scale;
+        int declaredPrecision = precision;
+        int declaredScale = scale;
+
+        // packed decimal may only be up to 31 digits.
+        if (declaredPrecision > 31) // this is a bugcheck only !!!
+        {
+            clearDdm ();
+            throw new java.sql.SQLException ("Packed decimal may only be up to 31 digits!");
+        }
+
+        // get absolute unscaled value of the BigDecimal as a String.
+        String unscaledStr = b.unscaledValue().abs().toString();
+
+        // get precision of the BigDecimal.
+          int bigPrecision = unscaledStr.length();
 
-		// packed decimal may only be up to 31 digits.
-		if (declaredPrecision > 31) // this is a bugcheck only !!!
-		{
-			clearDdm ();
-			throw new java.sql.SQLException ("Packed decimal may only be up to 31 digits!");
-		}
-
-		// get absolute unscaled value of the BigDecimal as a String.
-		String unscaledStr = b.unscaledValue().abs().toString();
-
-		// get precision of the BigDecimal.
-  	    int bigPrecision = unscaledStr.length();
-
-		if (bigPrecision > 31)
-		{
-			clearDdm ();
-  		    throw new SQLException ("The numeric literal \"" +
+        if (bigPrecision > 31)
+        {
+            clearDdm ();
+              throw new SQLException ("The numeric literal \"" +
                              b.toString() +
                              "\" is not valid because its value is out of range.",
                              "42820",
                              -405);
-		}
-    	int bigScale = b.scale();
-  	    int bigWholeIntegerLength = bigPrecision - bigScale;
-	    if ( (bigWholeIntegerLength > 0) && (!unscaledStr.equals ("0")) ) {
+        }
+        int bigScale = b.scale();
+          int bigWholeIntegerLength = bigPrecision - bigScale;
+        if ( (bigWholeIntegerLength > 0) && (!unscaledStr.equals ("0")) ) {
             // if whole integer part exists, check if overflow.
             int declaredWholeIntegerLength = declaredPrecision - declaredScale;
             if (bigWholeIntegerLength > declaredWholeIntegerLength)
-			{
-				clearDdm ();
+            {
+                clearDdm ();
                 throw new SQLException ("Overflow occurred during numeric data type conversion of \"" +
                                        b.toString() +
                                        "\".",
                                        "22003",
                                        -413);
-			}
+            }
         }
 
         // convert the unscaled value to a packed decimal bytes.
@@ -1720,216 +1720,216 @@ class DDMWriter
         // pad zero in front of the big decimal if necessary.
         for (; packedIndex>=-1; packedIndex-=2)
             buffer.put(offset + (packedIndex+1)/2, (byte) 0);
-	}
+    }
 
 
     private void sendBytes (java.io.OutputStream socketOutputStream) 
-	throws java.io.IOException{
-	
-	sendBytes(socketOutputStream,
-		  true);
-	
+    throws java.io.IOException{
+    
+    sendBytes(socketOutputStream,
+          true);
+    
     }
     
 
   private void sendBytes (java.io.OutputStream socketOutputStream,
-			  boolean flashStream ) 
+              boolean flashStream ) 
       throws java.io.IOException
   {
-	resetChainState();
-	final byte[] bytes = buffer.array();
-	final int length = buffer.position();
+    resetChainState();
+    final byte[] bytes = buffer.array();
+    final int length = buffer.position();
     try {
       socketOutputStream.write(bytes, 0, length);
       totalByteCount += length;
       if(flashStream)
-	  socketOutputStream.flush();
+      socketOutputStream.flush();
     }
     finally {
-		if ((dssTrace != null) && dssTrace.isComBufferTraceOn()) {
-			dssTrace.writeComBufferData (bytes,
-			                               0,
-			                               length,
-			                               DssTrace.TYPE_TRACE_SEND,
-			                               "Reply",
-			                               "flush",
-			                               5);
+        if ((dssTrace != null) && dssTrace.isComBufferTraceOn()) {
+            dssTrace.writeComBufferData (bytes,
+                                           0,
+                                           length,
+                                           DssTrace.TYPE_TRACE_SEND,
+                                           "Reply",
+                                           "flush",
+                                           5);
       }
       clearBuffer();
     }
   }
 
-	/**
-	 * Reset any chaining state that needs to be reset
-	 * at time of the send
-	 */
-	protected void resetChainState()
-	{
-		prevHdrLocation = -1;

[... 327 lines stripped ...]


Mime
View raw message