You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by tm...@apache.org on 2006/05/31 18:07:46 UTC
svn commit: r410570 [2/4] - in /db/derby/code/trunk/java:
drda/org/apache/derby/impl/drda/ engine/org/apache/derby/iapi/reference/
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=410570&r1=410569&r2=410570&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 May 31 09:07:45 2006
@@ -1,22 +1,22 @@
/*
-Derby - Class org.apache.derby.impl.drda.DDMWriter
+ Derby - Class org.apache.derby.impl.drda.DDMWriter
-Copyright 2001, 2004 The Apache Software Foundation or its licensors, as applicable.
+ Copyright 2001, 2004 The Apache Software Foundation or its licensors, as applicable.
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
-http://www.apache.org/licenses/LICENSE-2.0
+ http://www.apache.org/licenses/LICENSE-2.0
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-*/
+ */
package org.apache.derby.impl.drda;
@@ -36,377 +36,395 @@
import java.io.IOException;
/**
- 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;
-
- // Default buffer size
- private final static int DEFAULT_BUFFER_SIZE = 32767;
-
-
- static final BigDecimal ZERO = BigDecimal.valueOf(0L);
-
- // output buffer
- private byte[] bytes;
-
- // offset into output buffer
- private int offset;
-
- // 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 EBCDIC
- 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 within the "bytes" array 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 "bytes" array of the start of the header
- // that immediately precedes the mark.
- private int lastDSSBeforeMark;
-
- // Constructors
- DDMWriter (int minSize, CcsidManager ccsidManager, DRDAConnThread agent, DssTrace dssTrace) {
- this.bytes = new byte[minSize];
- this.ccsidManager = ccsidManager;
- 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);
- }
-
- DDMWriter (CcsidManager ccsidManager, DRDAConnThread agent, DssTrace dssTrace) {
- this.bytes = new byte[DEFAULT_BUFFER_SIZE];
- this.ccsidManager = ccsidManager;
- 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);
- }
-
- /**
- * reset values for sending next message
- *
- */
- protected void reset(DssTrace dssTrace) {
- offset = 0;
- top = 0;
- dssLengthLocation = 0;
- nextCorrelationID = 1;
- correlationID = DssConstants.CORRELATION_ID_UNKNOWN;
- isDRDAProtocol = true;
- this.dssTrace = dssTrace;
- }
-
- /**
- * 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 TestProto.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);
- }
+class DDMWriter
+{
- /**
- * Create DSS data object
- */
- protected void createDssObject() {
- beginDss(DssConstants.DSSFMT_OBJDSS, true);
- }
+ // 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;
+
+
+ static final BigDecimal ZERO = BigDecimal.valueOf(0L);
+
+ // output buffer
+ private byte[] bytes;
+
+ // offset into output buffer
+ private int offset;
+
+ // 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 EBCDIC
+ 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 within the "bytes" array 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 "bytes" array of the start of the header
+ // that immediately precedes the mark.
+ private int lastDSSBeforeMark;
+
+ // Constructors
+ DDMWriter (int minSize, CcsidManager ccsidManager, DRDAConnThread agent, DssTrace dssTrace)
+ {
+ this.bytes = new byte[minSize];
+ this.ccsidManager = ccsidManager;
+ 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);
+ }
+
+ DDMWriter (CcsidManager ccsidManager, DRDAConnThread agent, DssTrace dssTrace)
+ {
+ this.bytes = new byte[DEFAULT_BUFFER_SIZE];
+ this.ccsidManager = ccsidManager;
+ 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);
+ }
+
+ /**
+ * reset values for sending next message
+ *
+ */
+ protected void reset(DssTrace dssTrace)
+ {
+ offset = 0;
+ top = 0;
+ dssLengthLocation = 0;
+ nextCorrelationID = 1;
+ correlationID = DssConstants.CORRELATION_ID_UNKNOWN;
+ isDRDAProtocol = true;
+ this.dssTrace = dssTrace;
+ }
+
+ /**
+ * 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 TestProto.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.
+ bytes[dssLengthLocation] |= 0x80;
+ }
+
+ // 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 TestProto.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.
+ bytes[dssLengthLocation + 3] &= 0x0F; // Zero out default
+ bytes[dssLengthLocation + 3] |= chainByte;
+ previousChainByte = chainByte;
+
+ }
+
+ /**
+ * 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 = offset - start;
+ byte [] temp = new byte[length];
+ System.arraycopy(bytes,start,temp,0,length);
+ 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
+ markStack[top++] = offset;
+ ensureLength (4); // verify space for length bytes and code point
+ offset += 2; // move past the length bytes before writing the code point
+ bytes[offset] = (byte) ((codePoint >>> 8) & 0xff);
+ bytes[offset + 1] = (byte) (codePoint & 0xff);
+ offset += 2;
+ }
+
+ /**
+ * Erase all writes for the current ddm and reset the
+ * top
+ */
+ protected void clearDdm ()
+ {
+ offset = markStack[top--];
+ }
+
+ /**
+ * Clear the entire send buffer
+ *
+ */
+ protected void clearBuffer()
+ {
+ offset = 0;
+ 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 = offset - 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;
+
+ // shift the data to the right by the number of extended
+ // length bytes needed.
+ int extendedLengthLocation = lengthLocation + 4;
+ System.arraycopy (bytes,
+ extendedLengthLocation,
+ bytes,
+ extendedLengthLocation + extendedLengthByteCount,
+ extendedLength);
+
+ // write the extended length
+ int shiftSize = (extendedLengthByteCount -1) * 8;
+ for (int i = 0; i < extendedLengthByteCount; i++)
+ {
+ bytes[extendedLengthLocation++] =
+ (byte) ((extendedLength >>> shiftSize ) & 0xff);
+ shiftSize -= 8;
+ }
+
+ // adjust the offset to account for the shift and insert
+ offset += extendedLengthByteCount;
+
+ // 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).
+ bytes[lengthLocation] = (byte) ((length >>> 8) & 0xff);
+ bytes[lengthLocation+1] = (byte) (length & 0xff);
- /**
- * 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.
- bytes[dssLengthLocation] |= 0x80;
- }
-
- // 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 TestProto.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.
- bytes[dssLengthLocation + 3] &= 0x0F; // Zero out default
- bytes[dssLengthLocation + 3] |= chainByte;
- previousChainByte = chainByte;
-
- }
-
- /**
- * 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 = offset - start;
- byte [] temp = new byte[length];
- System.arraycopy(bytes,start,temp,0,length);
- 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
- markStack[top++] = offset;
- ensureLength (4); // verify space for length bytes and code point
- offset += 2; // move past the length bytes before writing the code point
- bytes[offset] = (byte) ((codePoint >>> 8) & 0xff);
- bytes[offset + 1] = (byte) (codePoint & 0xff);
- offset += 2;
- }
-
- /**
- * Erase all writes for the current ddm and reset the
- * top
- */
- protected void clearDdm () {
- offset = markStack[top--];
- }
-
- /**
- * Clear the entire send buffer
- *
- */
- protected void clearBuffer() {
- offset = 0;
- 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 = offset - 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;
-
- // shift the data to the right by the number of extended
- // length bytes needed.
- int extendedLengthLocation = lengthLocation + 4;
- System.arraycopy (bytes,
- extendedLengthLocation,
- bytes,
- extendedLengthLocation + extendedLengthByteCount,
- extendedLength);
-
- // write the extended length
- int shiftSize = (extendedLengthByteCount -1) * 8;
- for (int i = 0; i < extendedLengthByteCount; i++) {
- bytes[extendedLengthLocation++] =
- (byte) ((extendedLength >>> shiftSize ) & 0xff);
- shiftSize -= 8;
- }
-
- // adjust the offset to account for the shift and insert
- offset += extendedLengthByteCount;
-
- // 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).
- bytes[lengthLocation] = (byte) ((length >>> 8) & 0xff);
- bytes[lengthLocation+1] = (byte) (length & 0xff);
-
- }
+ }
/**
* Get the length of the current DSS block we're working on. This is
@@ -416,8 +434,9 @@
* DSS block when splitting a QRYDTA response.
*
* @return current DSS block length
- */
- protected int getDSSLength() {
+ */
+ protected int getDSSLength()
+ {
return offset - dssLengthLocation;
}
@@ -427,301 +446,323 @@
* calling copyDSSDataToEnd
*
* @param value DSS length
- */
- protected void truncateDSS(int value) {
+ */
+ protected void truncateDSS(int value)
+ {
offset = dssLengthLocation + value;
}
- // 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);
- bytes[offset++] = (byte) (value & 0xff);
- }
-
-
- /**
- * Write network short
- *
- * @param value value to be written
- */
- protected void writeNetworkShort (int value) {
- ensureLength (2);
- bytes[offset] = (byte) ((value >>> 8) & 0xff);
- bytes[offset + 1] = (byte) (value & 0xff);
- offset += 2;
- }
-
- /**
- * Write network int
- *
- * @param value value to be written
- */
- protected void writeNetworkInt (int value) {
- ensureLength (4);
- bytes[offset] = (byte) ((value >>> 24) & 0xff);
- bytes[offset + 1] = (byte) ((value >>> 16) & 0xff);
- bytes[offset + 2] = (byte) ((value >>> 8) & 0xff);
- bytes[offset + 3] = (byte) (value & 0xff);
- offset += 4;
- }
-
-
- /**
- * 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);
- System.arraycopy(buf,start,bytes,offset,length);
- offset += 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 length = buf.length;
- 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);
- bytes[offset] = (byte) ((codePoint >>> 8) & 0xff);
- bytes[offset + 1] = (byte) (codePoint & 0xff);
- bytes[offset + 2] = (byte) ((value >>> 8) & 0xff);
- bytes[offset + 3] = (byte) (value & 0xff);
- offset += 4;
- }
-
- /**
- * 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);
- bytes[offset] = 0x00;
- bytes[offset + 1] = 0x05;
- bytes[offset + 2] = (byte) ((codePoint >>> 8) & 0xff);
- bytes[offset + 3] = (byte) (codePoint & 0xff);
- bytes[offset + 4] = (byte) (value & 0xff);
- offset += 5;
- }
-
- /**
- * 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);
- bytes[offset] = 0x00;
- bytes[offset + 1] = 0x06;
- bytes[offset + 2] = (byte) ((codePoint >>> 8) & 0xff);
- bytes[offset + 3] = (byte) (codePoint & 0xff);
- bytes[offset + 4] = (byte) ((value >>> 8) & 0xff);
- bytes[offset + 5] = (byte) (value & 0xff);
- offset += 6;
- }
-
- protected void writeScalar2Bytes ( int value) {
- ensureLength (2);
- bytes[offset] = (byte) ((value >>> 8) & 0xff);
- bytes[offset + 1] = (byte) (value & 0xff);
- offset += 2;
- }
-
- /**
- * Write length and codepoint
- *
- * @param length - length of object
- * @param codePoint - code point to write
- */
- protected void startDdm (int length, int codePoint) {
- ensureLength (4);
- bytes[offset] = (byte) ((length >>> 8) & 0xff);
- bytes[offset + 1] = (byte) (length & 0xff);
- bytes[offset + 2] = (byte) ((codePoint >>> 8) & 0xff);
- bytes[offset + 3] = (byte) (codePoint & 0xff);
- offset += 4;
- }
-
- /**
- * Write scalar byte array object includes length, codepoint and value
- *
- * @param codePoint - code point to write
- * @param buf - value to write after code point
- * @param length - number of bytes to write
- */
- protected void writeScalarBytes (int codePoint, byte[] buf, int length) {
- if (SanityManager.DEBUG) {
- if (buf == null && length > 0)
- SanityManager.THROWASSERT("Buf is null");
- if (length > buf.length)
- SanityManager.THROWASSERT("Not enough bytes in buffer");
- }
- ensureLength (length + 4);
- bytes[offset] = (byte) (((length+4) >>> 8) & 0xff);
- bytes[offset + 1] = (byte) ((length+4) & 0xff);
- bytes[offset + 2] = (byte) ((codePoint >>> 8) & 0xff);
- bytes[offset + 3] = (byte) (codePoint & 0xff);
- System.arraycopy(buf,0,bytes,offset + 4, length);
- offset += length + 4;
- }
+ /**
+ * 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);
+ bytes[offset++] = (byte) (value & 0xff);
+ }
+
+
+ /**
+ * Write network short
+ *
+ * @param value value to be written
+ */
+ protected void writeNetworkShort (int value)
+ {
+ ensureLength (2);
+ bytes[offset] = (byte) ((value >>> 8) & 0xff);
+ bytes[offset + 1] = (byte) (value & 0xff);
+ offset += 2;
+ }
+
+ /**
+ * Write network int
+ *
+ * @param value value to be written
+ */
+ protected void writeNetworkInt (int value)
+ {
+ ensureLength (4);
+ bytes[offset] = (byte) ((value >>> 24) & 0xff);
+ bytes[offset + 1] = (byte) ((value >>> 16) & 0xff);
+ bytes[offset + 2] = (byte) ((value >>> 8) & 0xff);
+ bytes[offset + 3] = (byte) (value & 0xff);
+ offset += 4;
+ }
+
+
+ /**
+ * 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);
+ System.arraycopy(buf,start,bytes,offset,length);
+ offset += 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 length = buf.length;
+ 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);
+ bytes[offset] = (byte) ((codePoint >>> 8) & 0xff);
+ bytes[offset + 1] = (byte) (codePoint & 0xff);
+ bytes[offset + 2] = (byte) ((value >>> 8) & 0xff);
+ bytes[offset + 3] = (byte) (value & 0xff);
+ offset += 4;
+ }
+
+ /**
+ * 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);
+ bytes[offset] = 0x00;
+ bytes[offset + 1] = 0x05;
+ bytes[offset + 2] = (byte) ((codePoint >>> 8) & 0xff);
+ bytes[offset + 3] = (byte) (codePoint & 0xff);
+ bytes[offset + 4] = (byte) (value & 0xff);
+ offset += 5;
+ }
+
+ /**
+ * 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);
+ bytes[offset] = 0x00;
+ bytes[offset + 1] = 0x06;
+ bytes[offset + 2] = (byte) ((codePoint >>> 8) & 0xff);
+ bytes[offset + 3] = (byte) (codePoint & 0xff);
+ bytes[offset + 4] = (byte) ((value >>> 8) & 0xff);
+ bytes[offset + 5] = (byte) (value & 0xff);
+ offset += 6;
+ }
+
+ protected void writeScalar2Bytes ( int value)
+ {
+ ensureLength (2);
+ bytes[offset] = (byte) ((value >>> 8) & 0xff);
+ bytes[offset + 1] = (byte) (value & 0xff);
+ offset += 2;
+ }
+
+ /**
+ * Write length and codepoint
+ *
+ * @param length - length of object
+ * @param codePoint - code point to write
+ */
+ protected void startDdm (int length, int codePoint)
+ {
+ ensureLength (4);
+ bytes[offset] = (byte) ((length >>> 8) & 0xff);
+ bytes[offset + 1] = (byte) (length & 0xff);
+ bytes[offset + 2] = (byte) ((codePoint >>> 8) & 0xff);
+ bytes[offset + 3] = (byte) (codePoint & 0xff);
+ offset += 4;
+ }
+
+ /**
+ * Write scalar byte array object includes length, codepoint and value
+ *
+ * @param codePoint - code point to write
+ * @param buf - value to write after code point
+ * @param length - number of bytes to write
+ */
+ protected void writeScalarBytes (int codePoint, byte[] buf, int length)
+ {
+ if (SanityManager.DEBUG)
+ {
+ if (buf == null && length > 0)
+ SanityManager.THROWASSERT("Buf is null");
+ if (length > buf.length)
+ SanityManager.THROWASSERT("Not enough bytes in buffer");
+ }
+ ensureLength (length + 4);
+ bytes[offset] = (byte) (((length+4) >>> 8) & 0xff);
+ bytes[offset + 1] = (byte) ((length+4) & 0xff);
+ bytes[offset + 2] = (byte) ((codePoint >>> 8) & 0xff);
+ bytes[offset + 3] = (byte) (codePoint & 0xff);
+ System.arraycopy(buf,0,bytes,offset + 4, length);
+ offset += length + 4;
+ }
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
- int bytesRead = 0;
- int totalBytesRead = 0;
-
- try {
-
- OutputStream out =
- placeLayerBStreamingBuffer( agent.getOutputStream() );
-
- boolean isLastSegment = false;
-
- while( !isLastSegment ){
-
- int spareBufferLength = bytes.length - offset;
-
- if( SanityManager.DEBUG ){
-
- if( PropertyUtil.getSystemProperty("derby.debug.suicideOfLayerBStreaming") != null )
- throw new IOException();
- }
-
- bytesRead = in.read(bytes,
- offset,
- Math.min(spareDssLength,
- spareBufferLength));
-
- totalBytesRead += bytesRead;
- offset += bytesRead;
- spareDssLength -= bytesRead;
- spareBufferLength -= 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 ("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.
- bytes[dssLengthLocation] = (byte) 0xFF;
- bytes[dssLengthLocation + 1] = (byte) 0xFF;
-
- // 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
+ int bytesRead = 0;
+ int totalBytesRead = 0;
+
+ try {
+
+ OutputStream out =
+ placeLayerBStreamingBuffer( agent.getOutputStream() );
+
+ boolean isLastSegment = false;
+
+ while( !isLastSegment ){
+
+ int spareBufferLength = bytes.length - offset;
+
+ if( SanityManager.DEBUG ){
+
+ if( PropertyUtil.getSystemProperty("derby.debug.suicideOfLayerBStreaming") != null )
+ throw new IOException();
+ }
+
+ bytesRead = in.read(bytes,
+ offset,
+ Math.min(spareDssLength,
+ spareBufferLength));
+
+ totalBytesRead += bytesRead;
+ offset += bytesRead;
+ spareDssLength -= bytesRead;
+ spareBufferLength -= 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 ("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.
+ bytes[dssLengthLocation] = (byte) 0xFF;
+ bytes[dssLengthLocation + 1] = (byte) 0xFF;
+
+ // 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;
+ }
- bytes[dssLengthLocation + 3] = (byte) (dssType & 0xff);
- }
+ bytes[dssLengthLocation + 3] = (byte) (dssType & 0xff);
+ }
/**
@@ -734,837 +775,884 @@
* cf. page 315 of specification of DRDA, Version 3, Volume 3
*
*/
- private int prepScalarStream( boolean chainedWithSameCorrelator,
- int codePoint,
- boolean writeNullByte)
- throws DRDAProtocolException {
+ private int prepScalarStream( boolean chainedWithSameCorrelator,
+ int codePoint,
+ boolean writeNullByte) throws DRDAProtocolException
+ {
- ensureLength( DEFAULT_BUFFER_SIZE - offset );
+ ensureLength( DEFAULT_BUFFER_SIZE - offset );
- final int nullIndicatorSize = writeNullByte ? 1:0;
+ final int nullIndicatorSize = writeNullByte ? 1:0;
- // flush the existing DSS segment ,
- // if this stream will not fit in the send buffer or
- // length of this stream is unknown.
- // 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.
- sendBytes(agent.getOutputStream());
- } catch (java.io.IOException e) {
- agent.markCommunicationsFailure ("DDMWriter.writeScalarStream()",
- "OutputStream.flush()",
- e.getMessage(),"*");
- }
-
- // buildStreamDss should not call ensure length.
- beginDss(chainedWithSameCorrelator, DssConstants.GDSFMT_OBJDSS);
-
- writeLengthCodePoint(0x8004,codePoint);
-
-
- // write the null byte, if necessary
- if (writeNullByte)
- writeByte(0x0);
-
- //Here, 6 stands for header of layer A and
- //4 stands for header of layer B.
- return DssConstants.MAX_DSS_LENGTH - 6 - 4 - nullIndicatorSize;
-
-
- }
-
-
- // 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 offset != 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 = offset;
- bytes[offset++] = (byte) (0xff);
- bytes[offset++] = (byte) (0xff);
- isContinuationDss = true;
- }else{
- // we're done writing the data, so end the DSS.
- endDss();
-
- }
-
- }
-
-
- private void writeExtendedLengthBytes (int extendedLengthByteCount, long length) {
- int shiftSize = (extendedLengthByteCount -1) * 8;
- for (int i = 0; i < extendedLengthByteCount; i++) {
- bytes[offset + i] = (byte) ((length >>> shiftSize) & 0xff);
- shiftSize -= 8;
- }
- offset += extendedLengthByteCount;
- }
-
-
- // insert a 4 byte length/codepoint pair into the buffer.
- // total of 4 bytes inserted in buffer.
- // Note: the length value inserted in the buffer is the same as the value
- // passed in as an argument (this value is NOT incremented by 4 before being
- // inserted).
- void writeLengthCodePoint (int length, int codePoint) {
- ensureLength (4);
- bytes[offset] = (byte) ((length >>> 8) & 0xff);
- bytes[offset + 1] = (byte) (length & 0xff);
- bytes[offset + 2] = (byte) ((codePoint >>> 8) & 0xff);
- bytes[offset + 3] = (byte) (codePoint & 0xff);
- offset +=4;
- }
-
- /**
- * 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);
- bytes[offset] = (byte) (((dataLength+4) >>> 8) & 0xff);
- bytes[offset + 1] = (byte) ((dataLength+4) & 0xff);
- bytes[offset + 2] = (byte) ((codePoint >>> 8) & 0xff);
- bytes[offset + 3] = (byte) (codePoint & 0xff);
- offset += 4;
- }
-
- /**
- * 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 = string.length();
- ensureLength ((stringLength * 2) + 4);
- bytes[offset] = (byte) (((stringLength+4) >>> 8) & 0xff);
- bytes[offset + 1] = (byte) ((stringLength+4) & 0xff);
- bytes[offset + 2] = (byte) ((codePoint >>> 8) & 0xff);
- bytes[offset + 3] = (byte) (codePoint & 0xff);
- offset = ccsidManager.convertFromUCS2 (string, bytes, offset + 4);
- }
-
- /**
- * 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 = string.length();
- int fillLength = paddedLength - stringLength;
- ensureLength (paddedLength + 4);
- bytes[offset] = (byte) (((paddedLength+4) >>> 8) & 0xff);
- bytes[offset + 1] = (byte) ((paddedLength+4) & 0xff);
- bytes[offset + 2] = (byte) ((codePoint >>> 8) & 0xff);
- bytes[offset + 3] = (byte) (codePoint & 0xff);
- offset = ccsidManager.convertFromUCS2 (string, bytes, offset + 4);
- Arrays.fill(bytes,offset, offset + fillLength,ccsidManager.space);
- offset += fillLength;
- }
-
- /**
- * Write padded scalar string object value
- * the string is converted into the appropriate codeset (EBCDIC)
- *
- * @param string - string to be written
- * @param paddedLength - length to pad string to
- */
- protected void writeScalarPaddedString (String string, int paddedLength) {
- int stringLength = string.length();
-
- int fillLength = paddedLength -stringLength;
- ensureLength (paddedLength);
- offset = ccsidManager.convertFromUCS2 (string, bytes, offset);
- Arrays.fill(bytes,offset, offset + fillLength,ccsidManager.space);
- offset += fillLength;
- }
+ // flush the existing DSS segment ,
+ // if this stream will not fit in the send buffer or
+ // length of this stream is unknown.
+ // 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.
+ sendBytes(agent.getOutputStream());
+ }
+ catch (java.io.IOException e) {
+ agent.markCommunicationsFailure ("DDMWriter.writeScalarStream()",
+ "OutputStream.flush()",
+ e.getMessage(),"*");
+ }
+
+ // buildStreamDss should not call ensure length.
+ beginDss(chainedWithSameCorrelator, DssConstants.GDSFMT_OBJDSS);
+
+ writeLengthCodePoint(0x8004,codePoint);
+
+
+ // write the null byte, if necessary
+ if (writeNullByte)
+ writeByte(0x0);
+
+ //Here, 6 stands for header of layer A and
+ //4 stands for header of layer B.
+ return DssConstants.MAX_DSS_LENGTH - 6 - 4 - nullIndicatorSize;
+
+
+ }
+
+
+ // 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 offset != 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 = offset;
+ bytes[offset++] = (byte) (0xff);
+ bytes[offset++] = (byte) (0xff);
+ isContinuationDss = true;
+ }else{
+ // we're done writing the data, so end the DSS.
+ endDss();
+
+ }
+
+ }
+
+
+ private void writeExtendedLengthBytes (int extendedLengthByteCount, long length)
+ {
+ int shiftSize = (extendedLengthByteCount -1) * 8;
+ for (int i = 0; i < extendedLengthByteCount; i++) {
+ bytes[offset + i] = (byte) ((length >>> shiftSize) & 0xff);
+ shiftSize -= 8;
+ }
+ offset += extendedLengthByteCount;
+ }
+
+
+ // insert a 4 byte length/codepoint pair into the buffer.
+ // total of 4 bytes inserted in buffer.
+ // Note: the length value inserted in the buffer is the same as the value
+ // passed in as an argument (this value is NOT incremented by 4 before being
+ // inserted).
+ void writeLengthCodePoint (int length, int codePoint)
+ {
+ ensureLength (4);
+ bytes[offset] = (byte) ((length >>> 8) & 0xff);
+ bytes[offset + 1] = (byte) (length & 0xff);
+ bytes[offset + 2] = (byte) ((codePoint >>> 8) & 0xff);
+ bytes[offset + 3] = (byte) (codePoint & 0xff);
+ offset +=4;
+ }
+
+ /**
+ * 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);
+ bytes[offset] = (byte) (((dataLength+4) >>> 8) & 0xff);
+ bytes[offset + 1] = (byte) ((dataLength+4) & 0xff);
+ bytes[offset + 2] = (byte) ((codePoint >>> 8) & 0xff);
+ bytes[offset + 3] = (byte) (codePoint & 0xff);
+ offset += 4;
+ }
+
+ /**
+ * 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 = string.length();
+ ensureLength ((stringLength * 2) + 4);
+ bytes[offset] = (byte) (((stringLength+4) >>> 8) & 0xff);
+ bytes[offset + 1] = (byte) ((stringLength+4) & 0xff);
+ bytes[offset + 2] = (byte) ((codePoint >>> 8) & 0xff);
+ bytes[offset + 3] = (byte) (codePoint & 0xff);
+ offset = ccsidManager.convertFromUCS2 (string, bytes, offset + 4);
+ }
+
+ /**
+ * 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 = string.length();
+ int fillLength = paddedLength - stringLength;
+ ensureLength (paddedLength + 4);
+ bytes[offset] = (byte) (((paddedLength+4) >>> 8) & 0xff);
+ bytes[offset + 1] = (byte) ((paddedLength+4) & 0xff);
+ bytes[offset + 2] = (byte) ((codePoint >>> 8) & 0xff);
+ bytes[offset + 3] = (byte) (codePoint & 0xff);
+ offset = ccsidManager.convertFromUCS2 (string, bytes, offset + 4);
+ Arrays.fill(bytes,offset, offset + fillLength,ccsidManager.space);
+ offset += fillLength;
+ }
+
+ /**
+ * Write padded scalar string object value
+ * the string is converted into the appropriate codeset (EBCDIC)
+ *
+ * @param string - string to be written
+ * @param paddedLength - length to pad string to
+ */
+ protected void writeScalarPaddedString (String string, int paddedLength)
+ {
+ int stringLength = string.length();
+
+ int fillLength = paddedLength -stringLength;
+ ensureLength (paddedLength);
+ offset = ccsidManager.convertFromUCS2 (string, bytes, offset);
+ Arrays.fill(bytes,offset, offset + fillLength,ccsidManager.space);
+ offset += 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)
+ {
+ int stringLength = drdaString.length();
+ int fillLength = paddedLength - stringLength;
+ ensureLength(paddedLength);
+ System.arraycopy(drdaString.getBytes(), 0, bytes, offset, stringLength);
+ offset += stringLength;
+ Arrays.fill(bytes, offset, offset + fillLength, ccsidManager.space);
+ offset += 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)
+ {
+ int bufLength = buf.length;
+ ensureLength (paddedLength + 4);
+ bytes[offset] = (byte) (((paddedLength+4) >>> 8) & 0xff);
+ bytes[offset + 1] = (byte) ((paddedLength+4) & 0xff);
+ bytes[offset + 2] = (byte) ((codePoint >>> 8) & 0xff);
+ bytes[offset + 3] = (byte) (codePoint & 0xff);
+ offset += 4;
+ System.arraycopy(buf,0,bytes,offset,bufLength);
+ offset += bufLength;
+ int fillLength = paddedLength - bufLength;
+ Arrays.fill(bytes,offset,offset + fillLength,padByte);
+ offset += fillLength;
+ }
+
+ /**
+ * 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)
+ {
+ int bufLength = buf.length;
+ int fillLength = paddedLength - bufLength;
+ ensureLength (paddedLength);
+ System.arraycopy(buf,0,bytes,offset,bufLength);
+ offset +=bufLength;
+ Arrays.fill(bytes,offset,offset + fillLength,padByte);
+ offset += fillLength;
+ }
+
+ /**
+ * 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)
+ {
+ int bufLength = buf.length;
+ ensureLength (bufLength + 4);
+ bytes[offset] = (byte) (((bufLength+4) >>> 8) & 0xff);
+ bytes[offset + 1] = (byte) ((bufLength+4) & 0xff);
+ bytes[offset + 2] = (byte) ((codePoint >>> 8) & 0xff);
+ bytes[offset + 3] = (byte) (codePoint & 0xff);
+ System.arraycopy(buf,0,bytes,offset + 4,bufLength);
+ offset += bufLength + 4;
+ }
+
+ /**
+ * Write scalar byte array object includes length, codepoint and value
+ *
+ * @param codePoint - code point to write
+ * @param buf - byte array to be written
+ * @param start - starting point
+ * @param length - length to write
+ */
+ protected void writeScalarBytes (int codePoint, byte[] buf, int start, int length)
+ {
+ if (SanityManager.DEBUG)
+ {
+ if (buf == null && length > start)
+ SanityManager.THROWASSERT("Buf is null");
+ if (length - start > buf.length)
+ SanityManager.THROWASSERT("Not enough bytes in buffer");
+ }
+ int numBytes = length - start;
+ ensureLength (numBytes + 4);
+ bytes[offset] = (byte) (((numBytes+4) >>> 8) & 0xff);
+ bytes[offset + 1] = (byte) ((numBytes+4) & 0xff);
+ bytes[offset + 2] = (byte) ((codePoint >>> 8) & 0xff);
+ bytes[offset + 3] = (byte) (codePoint & 0xff);
+ offset += 4;
+ System.arraycopy(buf,start,bytes,offset,numBytes);
+ offset += numBytes;
+ }
+ // 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);
+ bytes[offset] = (byte) ((v >>> 56) & 0xff);
+ bytes[offset + 1] = (byte) ((v >>> 48) & 0xff);
+ bytes[offset + 2] = (byte) ((v >>> 40) & 0xff);
+ bytes[offset + 3] = (byte) ((v >>> 32) & 0xff);
+ bytes[offset + 4] = (byte) ((v >>> 24) & 0xff);
+ bytes[offset + 5] = (byte) ((v >>> 16) & 0xff);
+ bytes[offset + 6] = (byte) ((v >>> 8) & 0xff);
+ bytes[offset + 7] = (byte) ((v >>> 0) & 0xff);
+ offset += 8;
+ }
+
+ /**
+ * 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 big decimal to buffer
+ *
+ * @param v value to write
+ * @param precision Precison of decimal or numeric type
+ * @param scale declared scale
+ * @exception SQLException thrown if number of digits > 31
+ */
+ protected void writeBigDecimal (java.math.BigDecimal v, int precision, int scale)
+ throws SQLException
+ {
+ int length = precision / 2 + 1;
+ ensureLength (offset + length);
+ bigDecimalToPackedDecimalBytes (v,precision, scale);
+ offset += length;
+ }
+
+ /**
+ * Write platform boolean
+ *
+ * @param v value to be written
+ */
+ protected void writeBoolean (boolean v)
+ {
+ ensureLength (1);
+ bytes[offset++] = (byte) ((v ? 1 : 0) & 0xff);
+ }
+
+ /**
+ * Write length delimited string
+ *
+ * @param s value to be written with integer
+ *
+ * @exception DRDAProtocolException
+ */
+ protected void writeLDString(String s) throws DRDAProtocolException
+ {
+ writeLDString(s,0);
+ }
+
+
+ /**
+ * Write length delimited string
+ *
+ * @param s value to be written with integer
+ * @param index column index to put in warning
+ * @exception DRDAProtocolException
+ */
+ protected void writeLDString(String s, int index) throws DRDAProtocolException
+ {
+ try {
+ byte [] byteval = s.getBytes(NetworkServerControlImpl.DEFAULT_ENCODING);
+ int origLen = byteval.length;
+ boolean multiByteTrunc = false;
+ int writeLen =
+ java.lang.Math.min(FdocaConstants.LONGVARCHAR_MAX_LEN,
+ origLen);
+ /*
+ Need to make sure we truncate on character boundaries.
+ We are assuming
+ http://www.sun.com/developers/gadc/technicalpublications/articles/utf8.html
+ To find the beginning of a multibyte character:
+ 1) Does the current byte start with the bit pattern 10xxxxxx?
+ 2) If yes, move left and go to step #1.
+ 3) Finished
+ We assume that NetworkServerControlImpl.DEFAULT_ENCODING remains UTF-8
+ */
+
+ if (SanityManager.DEBUG)
+ {
+ if (!(NetworkServerControlImpl.DEFAULT_ENCODING.equals("UTF8")))
+ SanityManager.THROWASSERT("Encoding assumed to be UTF8, but is actually" + NetworkServerControlImpl.DEFAULT_ENCODING);
+ }
+
+ if (writeLen != origLen)
+ // first position on the first byte of the multibyte char
+ while ((byteval[writeLen -1] & 0xC0) == 0x80)
+ {
+ multiByteTrunc = true;
+ writeLen--;
+ // Then subtract one more to get to the end of the
+ // previous character
+ if (multiByteTrunc == true)
+ {
+ writeLen = writeLen -1;
+ }
+ }
+
+ writeShort(writeLen);
+ writeBytes(byteval,writeLen);
+ }
+ catch (Exception e) {
+ //this should never happen
+ agent.agentError("Encoding " + NetworkServerControlImpl.DEFAULT_ENCODING + " not supported");
+ }
+ }
+
+ /**
+ * Write string with default encoding
+ *
+ * @param s value to be written
+ *
+ * @exception DRDAProtocolException
+ */
+ protected void writeString(String s) throws DRDAProtocolException
+ {
+ try {
+ writeBytes(s.getBytes(NetworkServerControlImpl.DEFAULT_ENCODING));
+ } catch (Exception e) {
+ //this should never happen
+ agent.agentError("Encoding " + NetworkServerControlImpl.DEFAULT_ENCODING + " not supported");
+ }
+ }
+
+ /**
+ * Write string with default encoding and specified length
+ *
+ * @param s value to be written
+ * @param length number of bytes to be written
+ *
+ * @exception DRDAProtocolException
+ */
+ protected void writeString(String s, int length) throws DRDAProtocolException
+ {
+ byte[] bs = null;
+ try {
+ bs = s.getBytes(NetworkServerControlImpl.DEFAULT_ENCODING);
+ } catch (Exception e) {
+ //this should never happen
+ agent.agentError("Encoding " + NetworkServerControlImpl.DEFAULT_ENCODING + " not supported");
+ }
+ int len = bs.length;
+ if (len >= length)
+ writeBytes(bs, length);
+ else
+ {
+ writeBytes(bs);
+ padBytes(NetworkServerControlImpl.SPACE_CHAR, length-len);
+ }
+ }
+
+ /**
+ * Write pad bytes using spaceChar
+ *
+ * @param val value to be written
+ * @param length length to be written
+ */
+ protected void padBytes (byte val, int length)
+ {
+ Arrays.fill(bytes,offset, offset + length,val);
+ offset += length;
+ }
+
+ /**
+ * 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
+ {
+ try {
+ socketOutputStream.write (bytes, 0, offset);
+ socketOutputStream.flush();
+ }
+ finally {
+ if ((dssTrace != null) && dssTrace.isComBufferTraceOn()) {
+ dssTrace.writeComBufferData (bytes,
+ 0,
+ offset,
+ DssTrace.TYPE_TRACE_SEND,
+ "Reply",
+ "flush",
+ 5);
+ }
+ reset(dssTrace);
+ }
+ }
+
+ // 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 = offset;
+
+ // Should this really only be for non-stream DSSes?
+ if (ensureLen)
+ ensureLength(6);
+
+ // Skip past length; we'll come back and set it later.
+ offset += 2;
+
+ // write gds info
+ bytes[offset] = (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.
+ bytes[offset + 1] = (byte) dssType;
+ bytes[offset + 1] |= DssConstants.DSSCHAIN_SAME_ID;
+
+ // save correlationID for use in error messages while processing
+ // this DSS
+ correlationID = getCorrelationID();
+
+ // write the reply correlation id
+ bytes[offset + 2] = (byte) ((correlationID >>> 8) & 0xff);
+ bytes[offset + 3] = (byte) (correlationID & 0xff);
+ offset += 4;
+ }
- /**
- * 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) {
- int stringLength = drdaString.length();
- int fillLength = paddedLength - stringLength;
- ensureLength(paddedLength);
- System.arraycopy(drdaString.getBytes(), 0, bytes, offset, stringLength);
- offset += stringLength;
- Arrays.fill(bytes, offset, offset + fillLength, ccsidManager.space);
- offset += 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) {
- int bufLength = buf.length;
- ensureLength (paddedLength + 4);
- bytes[offset] = (byte) (((paddedLength+4) >>> 8) & 0xff);
- bytes[offset + 1] = (byte) ((paddedLength+4) & 0xff);
- bytes[offset + 2] = (byte) ((codePoint >>> 8) & 0xff);
- bytes[offset + 3] = (byte) (codePoint & 0xff);
- offset += 4;
- System.arraycopy(buf,0,bytes,offset,bufLength);
- offset += bufLength;
- int fillLength = paddedLength - bufLength;
- Arrays.fill(bytes,offset,offset + fillLength,padByte);
- offset += fillLength;
- }
-
- /**
- * 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) {
- int bufLength = buf.length;
- int fillLength = paddedLength - bufLength;
- ensureLength (paddedLength);
- System.arraycopy(buf,0,bytes,offset,bufLength);
- offset +=bufLength;
- Arrays.fill(bytes,offset,offset + fillLength,padByte);
- offset += fillLength;
- }
-
- /**
- * 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) {
- int bufLength = buf.length;
- ensureLength (bufLength + 4);
- bytes[offset] = (byte) (((bufLength+4) >>> 8) & 0xff);
- bytes[offset + 1] = (byte) ((bufLength+4) & 0xff);
- bytes[offset + 2] = (byte) ((codePoint >>> 8) & 0xff);
- bytes[offset + 3] = (byte) (codePoint & 0xff);
- System.arraycopy(buf,0,bytes,offset + 4,bufLength);
- offset += bufLength + 4;
- }
-
- /**
- * Write scalar byte array object includes length, codepoint and value
- *
- * @param codePoint - code point to write
- * @param buf - byte array to be written
- * @param start - starting point
- * @param length - length to write
- */
- protected void writeScalarBytes (int codePoint, byte[] buf, int start, int length) {
- if (SanityManager.DEBUG) {
- if (buf == null && length > start)
- SanityManager.THROWASSERT("Buf is null");
- if (length - start > buf.length)
- SanityManager.THROWASSERT("Not enough bytes in buffer");
- }
- int numBytes = length - start;
- ensureLength (numBytes + 4);
- bytes[offset] = (byte) (((numBytes+4) >>> 8) & 0xff);
- bytes[offset + 1] = (byte) ((numBytes+4) & 0xff);
- bytes[offset + 2] = (byte) ((codePoint >>> 8) & 0xff);
- bytes[offset + 3] = (byte) (codePoint & 0xff);
- offset += 4;
- System.arraycopy(buf,start,bytes,offset,numBytes);
- offset += numBytes;
- }
- // 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);
- bytes[offset] = (byte) ((v >>> 56) & 0xff);
- bytes[offset + 1] = (byte) ((v >>> 48) & 0xff);
- bytes[offset + 2] = (byte) ((v >>> 40) & 0xff);
- bytes[offset + 3] = (byte) ((v >>> 32) & 0xff);
- bytes[offset + 4] = (byte) ((v >>> 24) & 0xff);
- bytes[offset + 5] = (byte) ((v >>> 16) & 0xff);
- bytes[offset + 6] = (byte) ((v >>> 8) & 0xff);
- bytes[offset + 7] = (byte) ((v >>> 0) & 0xff);
- offset += 8;
- }
-
- /**
- * 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 big decimal to buffer
- *
- * @param v value to write
- * @param precision Precison of decimal or numeric type
- * @param scale declared scale
- * @exception SQLException thrown if number of digits > 31
- */
- protected void writeBigDecimal (java.math.BigDecimal v, int precision, int scale)
- throws SQLException {
- int length = precision / 2 + 1;
- ensureLength (offset + length);
- bigDecimalToPackedDecimalBytes (v,precision, scale);
- offset += length;
- }
-
- /**
- * Write platform boolean
- *
- * @param v value to be written
- */
- protected void writeBoolean (boolean v) {
- ensureLength (1);
- bytes[offset++] = (byte) ((v ? 1 : 0) & 0xff);
- }
-
- /**
- * Write length delimited string
- *
- * @param s value to be written with integer
- *
- * @exception DRDAProtocolException
- */
- protected void writeLDString(String s) throws DRDAProtocolException {
- writeLDString(s,0);
- }
-
-
- /**
- * Write length delimited string
- *
- * @param s value to be written with integer
- * @param index column index to put in warning
- * @exception DRDAProtocolException
- */
- protected void writeLDString(String s, int index)
- throws DRDAProtocolException {
- try {
- byte [] byteval = s.getBytes(NetworkServerControlImpl.DEFAULT_ENCODING);
- int origLen = byteval.length;
- boolean multiByteTrunc = false;
- int writeLen =
- java.lang.Math.min(FdocaConstants.LONGVARCHAR_MAX_LEN,
- origLen);
- /*
- Need to make sure we truncate on character boundaries.
- We are assuming
- http://www.sun.com/developers/gadc/technicalpublications/articles/utf8.html
- To find the beginning of a multibyte character:
- 1) Does the current byte start with the bit pattern 10xxxxxx?
- 2) If yes, move left and go to step #1.
- 3) Finished
- We assume that NetworkServerControlImpl.DEFAULT_ENCODING remains UTF-8
- */
-
- if (SanityManager.DEBUG) {
- if (!(NetworkServerControlImpl.DEFAULT_ENCODING.equals("UTF8")))
- SanityManager.THROWASSERT("Encoding assumed to be UTF8, but is actually" + NetworkServerControlImpl.DEFAULT_ENCODING);
- }
-
- if (writeLen != origLen)
- // first position on the first byte of the multibyte char
- while ((byteval[writeLen -1] & 0xC0) == 0x80) {
- multiByteTrunc = true;
- writeLen--;
- // Then subtract one more to get to the end of the
- // previous character
- if (multiByteTrunc == true) {
- writeLen = writeLen -1;
- }
- }
-
- writeShort(writeLen);
- writeBytes(byteval,writeLen);
- } catch (Exception e) {
- //this should never happen
- agent.agentError("Encoding " + NetworkServerControlImpl.DEFAULT_ENCODING + " not supported");
- }
- }
-
- /**
- * Write string with default encoding
- *
- * @param s value to be written
- *
- * @exception DRDAProtocolException
- */
- protected void writeString(String s) throws DRDAProtocolException {
- try {
- writeBytes(s.getBytes(NetworkServerControlImpl.DEFAULT_ENCODING));
- } catch (Exception e) {
- //this should never happen
- agent.agentError("Encoding " + NetworkServerControlImpl.DEFAULT_ENCODING + " not supported");
- }
- }
-
- /**
- * Write string with default encoding and specified length
- *
- * @param s value to be written
- * @param length number of bytes to be written
- *
- * @exception DRDAProtocolException
- */
- protected void writeString(String s, int length) throws DRDAProtocolException {
- byte[] bs = null;
- try {
- bs = s.getBytes(NetworkServerControlImpl.DEFAULT_ENCODING);
- } catch (Exception e) {
- //this should never happen
- agent.agentError("Encoding " + NetworkServerControlImpl.DEFAULT_ENCODING + " not supported");
- }
- int len = bs.length;
- if (len >= length)
- writeBytes(bs, length);
- else {
- writeBytes(bs);
- padBytes(NetworkServerControlImpl.SPACE_CHAR, length-len);
- }
- }
-
- /**
- * Write pad bytes using spaceChar
- *
- * @param val value to be written
- * @param length length to be written
- */
- protected void padBytes (byte val, int length) {
- Arrays.fill(bytes,offset, offset + length,val);
- offset += length;
- }
-
- /**
- * 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 {
- try {
- socketOutputStream.write (bytes, 0, offset);
- socketOutputStream.flush();
- } finally {
- if ((dssTrace != null) && dssTrace.isComBufferTraceOn()) {
- dssTrace.writeComBufferData (bytes,
- 0,
- offset,
- DssTrace.TYPE_TRACE_SEND,
- "Reply",
- "flush",
- 5);
- }
- reset(dssTrace);
- }
- }
-
- // 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 = offset;
-
- // Should this really only be for non-stream DSSes?
- if (ensureLen)
- ensureLength(6);
-
- // Skip past length; we'll come back and set it later.
- offset += 2;
-
- // write gds info
- bytes[offset] = (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.
- bytes[offset + 1] = (byte) dssType;
- bytes[offset + 1] |= DssConstants.DSSCHAIN_SAME_ID;
-
- // save correlationID for use in error messages while processing
- // this DSS
- correlationID = getCorrelationID();
-
- // write the reply correlation id
- bytes[offset + 2] = (byte) ((correlationID >>> 8) & 0xff);
- bytes[offset + 3] = (byte) (correlationID & 0xff);
- offset += 4;
- }
-
- /**
+ /**
* 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 () {
- // 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);
- 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
[... 1013 lines stripped ...]