📄 reply.java
字号:
/* Derby - Class org.apache.derby.client.net.Reply Copyright (c) 2001, 2005 The Apache Software Foundation or its licensors, where 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.client.net;import java.io.ByteArrayOutputStream;import org.apache.derby.client.am.SignedBinary;import org.apache.derby.client.am.SqlException;import org.apache.derby.client.am.SqlState;public class Reply { protected org.apache.derby.client.am.Agent agent_; protected NetAgent netAgent_; //cheat-link to (NetAgent) agent_ private CcsidManager ccsidManager_; protected final static int DEFAULT_BUFFER_SIZE = 32767; protected byte[] buffer_; protected int pos_; protected int count_; private int topDdmCollectionStack_; private final static int MAX_MARKS_NESTING = 10; private int[] ddmCollectionLenStack_; private int ddmScalarLen_; // a value of -1 -> streamed ddm -> length unknown private final static int EMPTY_STACK = -1; protected boolean ensuredLengthForDecryption_ = false; // A layer lengths have already been ensured in decrypt method. protected byte[] longBufferForDecryption_ = null; protected int longPosForDecryption_ = 0; protected byte[] longValueForDecryption_ = null; protected int longCountForDecryption_ = 0; protected int dssLength_; protected boolean dssIsContinued_; private boolean dssIsChainedWithSameID_; private boolean dssIsChainedWithDiffID_; protected int dssCorrelationID_; protected int peekedLength_ = 0; protected int peekedCodePoint_ = END_OF_COLLECTION; // saves the peeked codept private int peekedNumOfExtendedLenBytes_ = 0; private int currentPos_ = 0; public final static int END_OF_COLLECTION = -1; public final static int END_OF_SAME_ID_CHAIN = -2; Reply(NetAgent netAgent, int bufferSize) { buffer_ = new byte[bufferSize]; agent_ = netAgent_ = netAgent; ccsidManager_ = netAgent.targetCcsidManager_; ddmCollectionLenStack_ = new int[Reply.MAX_MARKS_NESTING]; initialize(); } final void initialize() { pos_ = 0; count_ = 0; topDdmCollectionStack_ = Reply.EMPTY_STACK; for (int i = 0; i < Reply.MAX_MARKS_NESTING; i++) { ddmCollectionLenStack_[i] = 0; } ddmScalarLen_ = 0; dssLength_ = 0; dssIsContinued_ = false; dssIsChainedWithSameID_ = false; dssIsChainedWithDiffID_ = false; dssCorrelationID_ = 1; } final int getDdmLength() { return ddmScalarLen_; } // This is a helper method which shifts the buffered bytes from // wherever they are in the current buffer to the beginning of // different buffer (note these buffers could be the same). // State information is updated as needed after the shift. private final void shiftBuffer(byte[] destinationBuffer) { // calculate the size of the data in the current buffer. int sz = count_ - pos_; // copy this data to the new buffer starting at position 0. System.arraycopy(buffer_, pos_, destinationBuffer, 0, sz); // update the state information for data in the new buffer. pos_ = 0; count_ = sz; // replace the old buffer with the new buffer. buffer_ = destinationBuffer; } // This method makes sure there is enough room in the buffer // for a certain number of bytes. This method will allocate // a new buffer if needed and shift the bytes in the current buffer // to make ensure space is available for a fill. Right now // this method will shift bytes as needed to make sure there is // as much room as possible in the buffer before trying to // do the read. The idea is to try to have space to get as much data as possible // if we need to do a read on the socket's stream. protected final void ensureSpaceInBufferForFill(int desiredSpace) { // calculate the total unused space in the buffer. // this includes any space at the end of the buffer and any free // space at the beginning resulting from bytes already read. int currentAvailableSpace = (buffer_.length - count_) + pos_; // check to see if there is enough free space. if (currentAvailableSpace < desiredSpace) { // there is not enough free space so we need more storage. // we are going to double the buffer unless that happens to still be too small. // if more than double the buffer is needed, use the smallest amount over this as possible. int doubleBufferSize = (2 * buffer_.length); int minumNewBufferSize = (desiredSpace - currentAvailableSpace) + buffer_.length; int newsz = minumNewBufferSize <= doubleBufferSize ? doubleBufferSize : minumNewBufferSize; byte[] newBuffer = new byte[newsz]; // shift everything from the old buffer to the new buffer shiftBuffer(newBuffer); } else { // there is enough free space in the buffer but let's make sure it is all at the end. // this is also important because if we are going to do a read, it would be nice // to get as much data as possible and making room at the end if the buffer helps to // ensure this. if (pos_ != 0) { shiftBuffer(buffer_); } } } // This method will attempt to read a minimum number of bytes // from the underlying stream. This method will keep trying to // read bytes until it has obtained at least the minimum number. // Now returns the total bytes read for decryption, use to return void. protected int fill(int minimumBytesNeeded) throws org.apache.derby.client.am.DisconnectException { // make sure that there is enough space in the buffer to hold // the minimum number of bytes needed. ensureSpaceInBufferForFill(minimumBytesNeeded); // read until the minimum number of bytes needed is now in the buffer. // hopefully the read method will return as many bytes as it can. int totalBytesRead = 0; int actualBytesRead = 0; do { try { // oops, we shouldn't expose the agent's input stream here, collapse this into a read method on the agent actualBytesRead = netAgent_.getInputStream().read(buffer_, count_, buffer_.length - count_); } catch (java.io.IOException ioe) { netAgent_.throwCommunicationsFailure("Reply.fill()", "InputStream.read()", ioe.getMessage(), "*"); } finally { if (agent_.loggingEnabled()) { ((NetLogWriter) netAgent_.logWriter_).traceProtocolFlow(buffer_, count_, actualBytesRead, NetLogWriter.TYPE_TRACE_RECEIVE, "Reply", "fill", 2); // tracepoint } } count_ += actualBytesRead; totalBytesRead += actualBytesRead; } while ((totalBytesRead < minimumBytesNeeded) && (actualBytesRead != -1)); if (actualBytesRead == -1) { if (totalBytesRead < minimumBytesNeeded) { netAgent_.throwCommunicationsFailure("Reply.fill()", "InputStream.read()", "insufficient data", "*"); } } return totalBytesRead; } // Make sure a certain amount of Layer A data is in the buffer. // The data will be in the buffer after this method is called. // Now returns the total bytes read for decryption, use to return void. protected final int ensureALayerDataInBuffer(int desiredDataSize) throws org.apache.derby.client.am.DisconnectException { int totalBytesRead = 0; // calulate the the number of bytes in the buffer. int avail = count_ - pos_; // read more bytes off the network if the data is not in the buffer already. if (avail < desiredDataSize) { totalBytesRead = fill(desiredDataSize - avail); } return totalBytesRead; } protected final void ensureBLayerDataInBuffer(int desiredDataSize) throws org.apache.derby.client.am.DisconnectException { if (dssIsContinued_ && (desiredDataSize > dssLength_)) { int continueDssHeaderCount = (((desiredDataSize - dssLength_) / 32767) + 1); ensureALayerDataInBuffer(desiredDataSize + (continueDssHeaderCount * 2)); compressBLayerData(continueDssHeaderCount); return; } ensureALayerDataInBuffer(desiredDataSize); } // this will probably never be called. // it is included here in the highly unlikely event that a reply object // exceeds 32K. for opimization purposes, we should consider // removing this. removing this should be ok since we handle most // big stuff returned from the server (qrydta's for example) by // copying out the data into some other storage. any extended dss header // info will be removed in the copying process. private final void compressBLayerData(int continueDssHeaderCount) throws org.apache.derby.client.am.DisconnectException { int tempPos = 0; // jump to the last continuation header. for (int i = 0; i < continueDssHeaderCount; i++) { // the first may be less than the size of a full dss if (i == 0) { // only jump by the number of bytes remaining in the current dss tempPos = pos_ + dssLength_; } else { // all other jumps are for a full continued dss tempPos += 32767; } } // for each of the dss headers to remove, // read out the continuation header and increment the dss length by the // size of the conitnation bytes, then shift the continuation data as needed. int shiftSize = 0; int bytesToShift = 0; int continueHeaderLength = 0; int newDssLength = 0; for (int i = 0; i < continueDssHeaderCount; i++) { continueHeaderLength = ((buffer_[tempPos] & 0xFF) << 8) + ((buffer_[tempPos + 1] & 0xFF) << 0); if (i == 0) { // if this is the last one (farthest down stream and first to strip out) if ((continueHeaderLength & 0x8000) == 0x8000) { // the last dss header is again continued continueHeaderLength = 32767; dssIsContinued_ = true; } else { // the last dss header was not contiued so update continue state flag dssIsContinued_ = false; } // the very first shift size is 2 shiftSize = 2; } else { // already removed the last header so make sure the chaining flag is on if ((continueHeaderLength & 0x8000) == 0x8000) { continueHeaderLength = 32767; } else { // this is a syntax error but not really certain which one. // for now pick 0x02 which is Dss header Length does not match the number // of bytes of data found. doSyntaxrmSemantics(CodePoint.SYNERRCD_DSS_LENGTH_BYTE_NUMBER_MISMATCH); } // increase the shift size by 2
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -