📄 ddmwriter.java
字号:
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; } // TODO: Rewrite writeScalarStream to avoid passing a length. // The length is never written and not required by the DRDA spec. // Also looks like on IOException we just pad out the stream instead // of actually sending an exception. Similar code is in client, so // should be fixed in both places. protected int writeScalarStream (boolean chainedWithSameCorrelator, int codePoint, int length, java.io.InputStream in, boolean writeNullByte) throws DRDAProtocolException { // Stream equivalent of "beginDss"... int leftToRead = length; int bytesToRead = prepScalarStream (chainedWithSameCorrelator, codePoint, writeNullByte, leftToRead); if (length == 0) return 0; // write the data int bytesRead = 0; int totalBytesRead = 0; do { do { try { bytesRead = in.read (bytes, offset, bytesToRead); totalBytesRead += bytesRead; } catch (java.io.IOException e) { padScalarStreamForError (leftToRead, bytesToRead); return totalBytesRead; } if (bytesRead == -1) { padScalarStreamForError (leftToRead, bytesToRead); return totalBytesRead; } else { bytesToRead -= bytesRead; offset += bytesRead; leftToRead -= bytesRead; } } while (bytesToRead > 0); bytesToRead = flushScalarStreamSegment (leftToRead, bytesToRead); } while (leftToRead > 0); // check to make sure that the specified length wasn't too small try { if (in.read() != -1) { totalBytesRead += 1; } } catch (java.io.IOException e) { // Encountered error in stream length verification for // InputStream, parameter #" + parameterIndex + ". // Don't think we need to error for this condition } return totalBytesRead; } /** * 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); } // prepScalarStream does the following prep for writing stream data: // 1. Flushes an existing DSS segment, if necessary // 2. Determines if extended length bytes are needed // 3. Creates a new DSS/DDM header and a null byte indicator, if applicable protected int prepScalarStream (boolean chainedWithSameCorrelator, int codePoint, boolean writeNullByte, int leftToRead) throws DRDAProtocolException { int extendedLengthByteCount; int nullIndicatorSize = 0; if (writeNullByte) nullIndicatorSize = 1; extendedLengthByteCount = calculateExtendedLengthByteCount (leftToRead + 4 + nullIndicatorSize); // flush the existing DSS segment if this stream will not fit in the send buffer if (10 + extendedLengthByteCount + nullIndicatorSize + leftToRead + offset > DssConstants.MAX_DSS_LENGTH) { 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); if (extendedLengthByteCount > 0) { // method should never ensure length writeLengthCodePoint (0x8004 + extendedLengthByteCount, codePoint); if (writeNullByte) writeExtendedLengthBytes (extendedLengthByteCount, leftToRead + 1); else writeExtendedLengthBytes (extendedLengthByteCount, leftToRead); } else { if (writeNullByte) writeLengthCodePoint (leftToRead + 4 + 1, codePoint); else writeLengthCodePoint (leftToRead + 4, codePoint); } // write the null byte, if necessary if (writeNullByte) writeByte(0x0); int bytesToRead; if (writeNullByte) bytesToRead = Math.min (leftToRead, DssConstants.MAX_DSS_LENGTH - 6 - 4 - 1 - extendedLengthByteCount); else bytesToRead = Math.min (leftToRead, DssConstants.MAX_DSS_LENGTH - 6 - 4 - extendedLengthByteCount); return bytesToRead; } // 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. protected int flushScalarStreamSegment (int leftToRead, int bytesToRead) throws DRDAProtocolException { int newBytesToRead = bytesToRead; // either at end of data, end of dss segment, or both. if (leftToRead != 0) { // 32k segment filled and not at end of data. if ((Math.min (2 + leftToRead, 32767)) > (bytes.length - offset)) { try { // Mark current DSS as continued, set its chaining state, // then send the data across. markDssAsContinued(true); // true => for lobs sendBytes (agent.getOutputStream()); } catch (java.io.IOException ioe) { agent.markCommunicationsFailure ("DDMWriter.flushScalarStreamSegment()", "", ioe.getMessage(), "*"); } } else { // DSS is full, but we still have space in the buffer. So // end the DSS, then start the next DSS right after it. endDss(false); // false => don't finalize length. } // Prepare a DSS continuation header for next DSS. dssLengthLocation = offset; bytes[offset++] = (byte) (0xff); bytes[offset++] = (byte) (0xff); newBytesToRead = Math.min (leftToRead,32765); isContinuationDss = true; } else { // we're done writing the data, so end the DSS. endDss(); } return newBytesToRead; } // the offset must not be updated when an error is encountered // note valid data may be overwritten protected void padScalarStreamForError (int leftToRead, int bytesToRead) throws DRDAProtocolException { do { do { bytes[offset++] = (byte)(0x0); // use 0x0 as the padding byte bytesToRead--; leftToRead--; } while (bytesToRead > 0); bytesToRead = flushScalarStreamSegment (leftToRead, bytesToRead); } while(leftToRead > 0); } 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; } /**
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -