⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ddmwriter.java

📁 derby database source code.good for you.
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
/*   Derby - Class org.apache.derby.impl.drda.DDMWriter   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      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. */package org.apache.derby.impl.drda;import java.io.OutputStream;import org.apache.derby.iapi.services.sanity.SanityManager;import java.sql.SQLException;import java.sql.DataTruncation;import java.math.BigDecimal;import org.apache.derby.iapi.error.ExceptionSeverity;import java.util.Arrays;/**	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);	}	/**	 * 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;		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     * used by the LMTBLKPRC protocol, which does its own conversational     * blocking protocol above the layer of the DRDA blocking. The LMTBLKPRC     * implementation (in DRDAConnThread) needs to be able to truncate a     * DSS block when splitting a QRYDTA response.     *     * @return current DSS block length    */    protected int getDSSLength()    {        return offset - dssLengthLocation;    }     /**     * Truncate the current DSS. Before making this call, you should ensure     * that you have copied the data to be truncated somewhere else, by     * calling copyDSSDataToEnd     *     * @param desired DSS length    */    protected void truncateDSS(int value)    {        offset = dssLengthLocation + value;    }	// 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);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -