📄 request.java
字号:
/* Derby - Class org.apache.derby.client.net.Request 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 org.apache.derby.client.am.DisconnectException;import org.apache.derby.client.am.EncryptionManager;import org.apache.derby.client.am.SqlException;import org.apache.derby.client.am.Utils;import java.io.UnsupportedEncodingException;public class Request { // byte array buffer used for constructing requests. // currently requests are built starting at the beginning of the buffer. protected byte[] bytes_; // keeps track of the next position to place a byte in the buffer. // so the last valid byte in the message is at bytes_[offset - 1] protected int offset_; // a stack is used to keep track of offsets into the buffer where 2 byte // ddm length values are located. these length bytes will be automatically updated // by this object when construction of a particular object has completed. // right now the max size of the stack is 10. this is an arbitrary number which // should be sufficiently large enough to handle all situations. private final static int MAX_MARKS_NESTING = 10; private int[] markStack_ = new int[MAX_MARKS_NESTING]; private int top_ = 0; // the ccsid manager for the connection is stored in this object. it will // be used when constructing character ddm data. it will NOT be used for // building any FDOCA data. protected CcsidManager ccsidManager_; // 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_ = 0; // tracks the request correlation ID to use for commands and command objects. // this is automatically updated as commands are built and sent to the server. private int correlationID_ = 0; private boolean simpleDssFinalize = false; // Used to mask out password when trace is on. protected boolean passwordIncluded_ = false; protected int passwordStart_ = 0; protected int passwordLength_ = 0; protected NetAgent netAgent_; // construct a request object specifying the minimum buffer size // to be used to buffer up the built requests. also specify the ccsid manager // instance to be used when building ddm character data. Request(NetAgent netAgent, int minSize, CcsidManager ccsidManager) { netAgent_ = netAgent; bytes_ = new byte[minSize]; ccsidManager_ = ccsidManager; clearBuffer(); } // construct a request object specifying the ccsid manager instance // to be used when building ddm character data. This will also create // a buffer using the default size (see final static DEFAULT_BUFFER_SIZE value). Request(NetAgent netAgent, CcsidManager ccsidManager, int bufferSize) { //this (netAgent, Request.DEFAULT_BUFFER_SIZE, ccsidManager); this(netAgent, bufferSize, ccsidManager); } protected final void clearBuffer() { offset_ = 0; top_ = 0; for (int i = 0; i < markStack_.length; i++) { if (markStack_[i] != 0) { markStack_[i] = 0; } else { break; } } dssLengthLocation_ = 0; } final void initialize() { clearBuffer(); correlationID_ = 0; } // set the ccsid manager value. this method allows the ccsid manager to be // changed so a request object can be reused by different connections with // different ccsid managers. final void setCcsidMgr(CcsidManager ccsidManager) { ccsidManager_ = ccsidManager; } // ensure length at the end of the buffer for a certain amount of data. // if the buffer does not contain sufficient room for the data, the buffer // will be expanded by the larger of (2 * current size) or (current size + length). // the data from the previous buffer is copied into the larger buffer. protected final void ensureLength(int length) { if (length > bytes_.length) { byte newBytes[] = new byte[Math.max(bytes_.length << 1, length)]; System.arraycopy(bytes_, 0, newBytes, 0, offset_); bytes_ = newBytes; } } // creates an request dss in the buffer to contain a ddm command // object. calling this method means any previous dss objects in // the buffer are complete and their length and chaining bytes can // be updated appropriately. protected final void createCommand() { buildDss(false, false, false, DssConstants.GDSFMT_RQSDSS, ++correlationID_, false); } // creates an request dss in the buffer to contain a ddm command // object. calling this method means any previous dss objects in // the buffer are complete and their length and chaining bytes can // be updated appropriately. protected void createXACommand() { buildDss(false, false, false, DssConstants.GDSFMT_RQSDSS_NOREPLY, ++correlationID_, false); } // creates an object dss in the buffer to contain a ddm command // data object. calling this method means any previous dss objects in // the buffer are complete and their length and chaining bytes can // be updated appropriately. final void createCommandData() { buildDss(true, false, false, DssConstants.GDSFMT_OBJDSS, correlationID_, false); } final void createEncryptedCommandData() { if (netAgent_.netConnection_.getSecurityMechanism() == NetConfiguration.SECMEC_EUSRIDDTA || netAgent_.netConnection_.getSecurityMechanism() == NetConfiguration.SECMEC_EUSRPWDDTA) { buildDss(true, false, false, DssConstants.GDSFMT_ENCOBJDSS, correlationID_, false); } else { buildDss(true, false, false, DssConstants.GDSFMT_OBJDSS, correlationID_, false); } } // experimental lob section private final void buildDss(boolean dssHasSameCorrelator, boolean chainedToNextStructure, boolean nextHasSameCorrelator, int dssType, int corrId, boolean simpleFinalizeBuildingNextDss) { if (doesRequestContainData()) { if (simpleDssFinalize) { finalizeDssLength(); } else { finalizePreviousChainedDss(dssHasSameCorrelator); } } ensureLength(offset_ + 6); // save the length position and skip // note: the length position is saved so it can be updated // with a different value later. dssLengthLocation_ = offset_; // always turn on chaining flags... this is helpful for lobs... // these bytes will get rest if dss lengths are finalized. bytes_[offset_++] = (byte) 0xFF; bytes_[offset_++] = (byte) 0xFF; // insert the manditory 0xD0 and the dssType bytes_[offset_++] = (byte) 0xD0; if (chainedToNextStructure) { dssType |= DssConstants.GDSCHAIN; if (nextHasSameCorrelator) { dssType |= DssConstants.GDSCHAIN_SAME_ID; } } bytes_[offset_++] = (byte) (dssType & 0xff); // write the request correlation id // use method that writes a short bytes_[offset_++] = (byte) ((corrId >>> 8) & 0xff); bytes_[offset_++] = (byte) (corrId & 0xff); simpleDssFinalize = simpleFinalizeBuildingNextDss; } // We need to reuse the agent's sql exception accumulation mechanism // for this write exception, pad if the length is too big, and truncation if the length is too small final void writeScalarStream(boolean chained, boolean chainedWithSameCorrelator, int codePoint, int length, java.io.InputStream in, boolean writeNullByte, int parameterIndex) throws DisconnectException, SqlException { int leftToRead = length; int extendedLengthByteCount = prepScalarStream(chained, chainedWithSameCorrelator, writeNullByte, leftToRead); int bytesToRead; if (writeNullByte) { bytesToRead = Utils.min(leftToRead, DssConstants.MAX_DSS_LEN - 6 - 4 - 1 - extendedLengthByteCount); } else { bytesToRead = Utils.min(leftToRead, DssConstants.MAX_DSS_LEN - 6 - 4 - extendedLengthByteCount); } if (netAgent_.netConnection_.getSecurityMechanism() == NetConfiguration.SECMEC_EUSRIDDTA || netAgent_.netConnection_.getSecurityMechanism() == NetConfiguration.SECMEC_EUSRPWDDTA) { byte[] lengthAndCodepoint; lengthAndCodepoint = buildLengthAndCodePointForEncryptedLob(codePoint, leftToRead, writeNullByte, extendedLengthByteCount); // we need to stream the input, rather than fully materialize it // write the data byte[] clearedBytes = new byte[leftToRead]; int bytesRead = 0; int totalBytesRead = 0; int pos = 0; do { try { bytesRead = in.read(clearedBytes, pos, leftToRead); totalBytesRead += bytesRead; } catch (java.io.IOException e) { padScalarStreamForError(leftToRead, bytesToRead); // set with SQLSTATE 01004: The value of a string was truncated when assigned to a host variable. netAgent_.accumulateReadException(new SqlException(netAgent_.logWriter_, "Encountered an IOException reading InputStream, parameter #" + parameterIndex + ". Remaining data has been padded with 0x0. Message: " + e.getMessage())); return; } if (bytesRead == -1) { //padScalarStreamForError(leftToRead, bytesToRead); // set with SQLSTATE 01004: The value of a string was truncated when assigned to a host variable. /*throw new SqlException(netAgent_.logWriter_, "End of Stream prematurely reached while reading InputStream, parameter #" + parameterIndex + ". Remaining data has been padded with 0x0.");*/ //is it OK to do a chain break Exception here. It's not good to
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -