001: /*
002:
003: Derby - Class org.apache.derby.client.net.NetPackageRequest
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to You under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021: package org.apache.derby.client.net;
022:
023: import org.apache.derby.client.am.Configuration;
024: import org.apache.derby.client.am.Section;
025: import org.apache.derby.client.am.SqlException;
026: import org.apache.derby.client.am.ClientMessageId;
027: import org.apache.derby.shared.common.reference.SQLState;
028:
029: public class NetPackageRequest extends NetConnectionRequest {
030: static final String COLLECTIONNAME = "NULLID";
031:
032: NetPackageRequest(NetAgent netAgent, CcsidManager ccsidManager,
033: int bufferSize) {
034: super (netAgent, ccsidManager, bufferSize);
035: }
036:
037: // RDB Package Name, Consistency Token
038: // Scalar Object specifies the fully qualified name of a relational
039: // database package and its consistency token.
040: //
041: // To accomodate larger lengths, the Scalar Data Length
042: // (SCLDTALEN) Field is used to specify the length of the instance
043: // variable which follows.
044: static final String collectionName = "NULLID";
045:
046: void buildCommonPKGNAMinfo(Section section) throws SqlException {
047: String collectionToFlow = COLLECTIONNAME;
048: // the scalar data length field may or may not be required. it depends
049: // on the level of support and length of the data.
050: // check the lengths of the RDBNAM, RDBCOLID, and PKGID.
051: // Determine if the lengths require an SCLDTALEN object.
052: // Note: if an SQLDTALEN is required for ONE of them,
053: // it is needed for ALL of them. This is why this check is
054: // up front.
055: // the SQLAM level dictates the maximum size for
056: // RDB Collection Identifier (RDBCOLID)
057: // Relational Database Name (RDBNAM)
058: // RDB Package Identifier (PKGID)
059: int maxIdentifierLength = NetConfiguration.PKG_IDENTIFIER_MAX_LEN;
060:
061: boolean scldtalenRequired = false;
062: scldtalenRequired = checkPKGNAMlengths(
063: netAgent_.netConnection_.databaseName_,
064: maxIdentifierLength,
065: NetConfiguration.PKG_IDENTIFIER_FIXED_LEN);
066:
067: if (!scldtalenRequired) {
068: scldtalenRequired = checkPKGNAMlengths(collectionToFlow,
069: maxIdentifierLength,
070: NetConfiguration.PKG_IDENTIFIER_FIXED_LEN);
071: }
072:
073: if (!scldtalenRequired) {
074: scldtalenRequired = checkPKGNAMlengths(section
075: .getPackageName(), maxIdentifierLength,
076: NetConfiguration.PKG_IDENTIFIER_FIXED_LEN);
077: }
078:
079: // the format is different depending on if an SCLDTALEN is required.
080: if (!scldtalenRequired) {
081: writeScalarPaddedString(
082: netAgent_.netConnection_.databaseName_,
083: NetConfiguration.PKG_IDENTIFIER_FIXED_LEN);
084: writeScalarPaddedString(collectionToFlow,
085: NetConfiguration.PKG_IDENTIFIER_FIXED_LEN);
086: writeScalarPaddedString(section.getPackageName(),
087: NetConfiguration.PKG_IDENTIFIER_FIXED_LEN);
088: } else {
089: buildSCLDTA(netAgent_.netConnection_.databaseName_,
090: NetConfiguration.PKG_IDENTIFIER_FIXED_LEN);
091: buildSCLDTA(collectionToFlow,
092: NetConfiguration.PKG_IDENTIFIER_FIXED_LEN);
093: buildSCLDTA(section.getPackageName(),
094: NetConfiguration.PKG_IDENTIFIER_FIXED_LEN);
095: }
096: }
097:
098: private void buildSCLDTA(String identifier, int minimumLength)
099: throws SqlException {
100: if (identifier.length() <= minimumLength) {
101: write2Bytes(minimumLength);
102: writeScalarPaddedString(identifier, minimumLength);
103: } else {
104: write2Bytes(identifier.length());
105: writeScalarPaddedString(identifier, identifier.length());
106: }
107: }
108:
109: // this specifies the fully qualified package name,
110: // consistency token, and section number within the package being used
111: // to execute the SQL. If the connection supports reusing the previous
112: // package information and this information is the same except for the section
113: // number then only the section number needs to be sent to the server.
114: void buildPKGNAMCSN(Section section) throws SqlException {
115: if (!canCommandUseDefaultPKGNAMCSN()) {
116: markLengthBytes(CodePoint.PKGNAMCSN);
117: // If PKGNAMCBytes is already available, copy the bytes to the request buffer directly.
118: if (section.getPKGNAMCBytes() != null) {
119: writeStoredPKGNAMCBytes(section);
120: } else {
121: // Mark the beginning of PKGNAMCSN bytes.
122: markForCachingPKGNAMCSN();
123: buildCommonPKGNAMinfo(section);
124: writeScalarPaddedBytes(
125: Configuration.dncPackageConsistencyToken,
126: NetConfiguration.PKGCNSTKN_FIXED_LEN,
127: NetConfiguration.NON_CHAR_DDM_DATA_PAD_BYTE);
128: // store the PKGNAMCbytes
129: storePKGNAMCBytes(section);
130: }
131: write2Bytes(section.getSectionNumber());
132: updateLengthBytes();
133: } else {
134: writeScalar2Bytes(CodePoint.PKGSN, section
135: .getSectionNumber());
136: }
137: }
138:
139: private void storePKGNAMCBytes(Section section) {
140: // Get the locaton where we started writing PKGNAMCSN
141: int startPos = popMarkForCachingPKGNAMCSN();
142: int copyLength = offset_ - startPos;
143: byte[] b = new byte[copyLength];
144: System.arraycopy(bytes_, startPos, b, 0, copyLength);
145: section.setPKGNAMCBytes(b);
146: }
147:
148: private void writeStoredPKGNAMCBytes(Section section) {
149: byte[] b = section.getPKGNAMCBytes();
150:
151: // Mare sure request buffer has enough space to write this byte array.
152: ensureLength(offset_ + b.length);
153:
154: System.arraycopy(b, 0, bytes_, offset_, b.length);
155:
156: offset_ += b.length;
157: }
158:
159: private boolean canCommandUseDefaultPKGNAMCSN() {
160: return false;
161: }
162:
163: // throws an exception if lengths exceed the maximum.
164: // returns a boolean indicating if SLCDTALEN is required.
165: private boolean checkPKGNAMlengths(String identifier,
166: int maxIdentifierLength, int lengthRequiringScldta)
167: throws SqlException {
168: int length = identifier.length();
169: if (length > maxIdentifierLength) {
170: throw new SqlException(netAgent_.logWriter_,
171: new ClientMessageId(
172: SQLState.LANG_IDENTIFIER_TOO_LONG),
173: identifier, new Integer(maxIdentifierLength));
174: }
175:
176: return (length > lengthRequiringScldta);
177: }
178:
179: private byte[] getBytes(String string, String encoding)
180: throws SqlException {
181: try {
182: return string.getBytes(encoding);
183: } catch (java.lang.Exception e) {
184: throw new SqlException(netAgent_.logWriter_,
185: new ClientMessageId(SQLState.JAVA_EXCEPTION), e
186: .getClass().getName(), e.getMessage(), e);
187: }
188: }
189:
190: private void buildNOCMorNOCS(String string) throws SqlException {
191: if (string == null) {
192: write2Bytes(0xffff);
193: } else {
194: byte[] sqlBytes = null;
195:
196: if (netAgent_.typdef_.isCcsidMbcSet()) {
197: sqlBytes = getBytes(string, netAgent_.typdef_
198: .getCcsidMbcEncoding());
199: write1Byte(0x00);
200: write4Bytes(sqlBytes.length);
201: writeBytes(sqlBytes, sqlBytes.length);
202: write1Byte(0xff);
203: } else {
204: sqlBytes = getBytes(string, netAgent_.typdef_
205: .getCcsidSbcEncoding());
206: write1Byte(0xff);
207: write1Byte(0x00);
208: write4Bytes(sqlBytes.length);
209: writeBytes(sqlBytes, sqlBytes.length);
210: }
211: }
212: }
213:
214: // SQLSTTGRP : FDOCA EARLY GROUP
215: // SQL Statement Group Description
216: //
217: // FORMAT FOR SQLAM <= 6
218: // SQLSTATEMENT_m; PROTOCOL TYPE LVCM; ENVLID 0x40; Length Override 32767
219: // SQLSTATEMENT_s; PROTOCOL TYPE LVCS; ENVLID 0x34; Length Override 32767
220: //
221: // FORMAT FOR SQLAM >= 7
222: // SQLSTATEMENT_m; PROTOCOL TYPE NOCM; ENVLID 0xCF; Length Override 4
223: // SQLSTATEMENT_s; PROTOCOL TYPE NOCS; ENVLID 0xCB; Length Override 4
224: private void buildSQLSTTGRP(String string) throws SqlException {
225: buildNOCMorNOCS(string);
226: return;
227: }
228:
229: // SQLSTT : FDOCA EARLY ROW
230: // SQL Statement Row Description
231: //
232: // FORMAT FOR ALL SQLAM LEVELS
233: // SQLSTTGRP; GROUP LID 0x5C; ELEMENT TAKEN 0(all); REP FACTOR 1
234: private void buildSQLSTT(String string) throws SqlException {
235: buildSQLSTTGRP(string);
236: }
237:
238: protected void buildSQLSTTcommandData(String sql)
239: throws SqlException {
240: createEncryptedCommandData();
241: int loc = offset_;
242: markLengthBytes(CodePoint.SQLSTT);
243: buildSQLSTT(sql);
244: updateLengthBytes();
245: if (netAgent_.netConnection_.getSecurityMechanism() == NetConfiguration.SECMEC_EUSRIDDTA
246: || netAgent_.netConnection_.getSecurityMechanism() == NetConfiguration.SECMEC_EUSRPWDDTA) {
247: encryptDataStream(loc);
248: }
249:
250: }
251:
252: protected void buildSQLATTRcommandData(String sql)
253: throws SqlException {
254: createEncryptedCommandData();
255: int loc = offset_;
256: markLengthBytes(CodePoint.SQLATTR);
257: buildSQLSTT(sql);
258: updateLengthBytes();
259: if (netAgent_.netConnection_.getSecurityMechanism() == NetConfiguration.SECMEC_EUSRIDDTA
260: || netAgent_.netConnection_.getSecurityMechanism() == NetConfiguration.SECMEC_EUSRPWDDTA) {
261: encryptDataStream(loc);
262: }
263:
264: }
265:
266: public void encryptDataStream(int lengthLocation)
267: throws SqlException {
268: byte[] clearedBytes = new byte[offset_ - lengthLocation];
269: byte[] encryptedBytes;
270: for (int i = lengthLocation; i < offset_; i++) {
271: clearedBytes[i - lengthLocation] = bytes_[i];
272: }
273:
274: encryptedBytes = netAgent_.netConnection_
275: .getEncryptionManager().encryptData(clearedBytes,
276: NetConfiguration.SECMEC_EUSRIDPWD,
277: netAgent_.netConnection_.getTargetPublicKey(),
278: netAgent_.netConnection_.getTargetPublicKey());
279:
280: int length = encryptedBytes.length;
281:
282: if (bytes_.length >= lengthLocation + length) {
283: System.arraycopy(encryptedBytes, 0, bytes_, lengthLocation,
284: length);
285: } else {
286: byte[] largeByte = new byte[lengthLocation + length];
287: System.arraycopy(bytes_, 0, largeByte, 0, lengthLocation);
288: System.arraycopy(encryptedBytes, 0, largeByte,
289: lengthLocation, length);
290: bytes_ = largeByte;
291: }
292:
293: offset_ += length - clearedBytes.length;
294:
295: //we need to update the length in DSS header here.
296:
297: bytes_[lengthLocation - 6] = (byte) ((length >>> 8) & 0xff);
298: bytes_[lengthLocation - 5] = (byte) (length & 0xff);
299: }
300:
301: }
|