KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > client > net > Reply


1 /*
2
3    Derby - Class org.apache.derby.client.net.Reply
4
5    Licensed to the Apache Software Foundation (ASF) under one or more
6    contributor license agreements. See the NOTICE file distributed with
7    this work for additional information regarding copyright ownership.
8    The ASF licenses this file to You under the Apache License, Version 2.0
9    (the "License"); you may not use this file except in compliance with
10    the License. You may obtain a copy of the License at
11
12       http://www.apache.org/licenses/LICENSE-2.0
13
14    Unless required by applicable law or agreed to in writing, software
15    distributed under the License is distributed on an "AS IS" BASIS,
16    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17    See the License for the specific language governing permissions and
18    limitations under the License.
19
20 */

21
22 package org.apache.derby.client.net;
23
24
25 import java.io.ByteArrayOutputStream JavaDoc;
26 import java.util.Arrays JavaDoc;
27
28 import org.apache.derby.client.am.SignedBinary;
29 import org.apache.derby.client.am.SqlException;
30 import org.apache.derby.client.am.DisconnectException;
31 import org.apache.derby.client.am.SqlState;
32 import org.apache.derby.client.am.ClientMessageId;
33
34 import org.apache.derby.shared.common.reference.SQLState;
35 import org.apache.derby.shared.common.reference.MessageId;
36
37 public class Reply {
38     protected org.apache.derby.client.am.Agent agent_;
39     protected NetAgent netAgent_; //cheat-link to (NetAgent) agent_
40

41     private CcsidManager ccsidManager_;
42     protected final static int DEFAULT_BUFFER_SIZE = 32767;
43     protected byte[] buffer_;
44     protected int pos_;
45     protected int count_;
46
47     private int topDdmCollectionStack_;
48     private final static int MAX_MARKS_NESTING = 10;
49     private int[] ddmCollectionLenStack_;
50     private int ddmScalarLen_; // a value of -1 -> streamed ddm -> length unknown
51
private final static int EMPTY_STACK = -1;
52
53     protected boolean ensuredLengthForDecryption_ = false; // A layer lengths have already been ensured in decrypt method.
54
protected byte[] longBufferForDecryption_ = null;
55     protected int longPosForDecryption_ = 0;
56     protected byte[] longValueForDecryption_ = null;
57     protected int longCountForDecryption_ = 0;
58
59     protected int dssLength_;
60     protected boolean dssIsContinued_;
61     private boolean dssIsChainedWithSameID_;
62     private boolean dssIsChainedWithDiffID_;
63     protected int dssCorrelationID_;
64
65     protected int peekedLength_ = 0;
66     protected int peekedCodePoint_ = END_OF_COLLECTION; // saves the peeked codept
67
private int peekedNumOfExtendedLenBytes_ = 0;
68     private int currentPos_ = 0;
69
70     public final static int END_OF_COLLECTION = -1;
71     public final static int END_OF_SAME_ID_CHAIN = -2;
72
73     Reply(NetAgent netAgent, int bufferSize) {
74         buffer_ = new byte[bufferSize];
75         agent_ = netAgent_ = netAgent;
76         ccsidManager_ = netAgent.targetCcsidManager_;
77         ddmCollectionLenStack_ = new int[Reply.MAX_MARKS_NESTING];
78         initialize();
79     }
80
81     final void initialize() {
82         pos_ = 0;
83         count_ = 0;
84         topDdmCollectionStack_ = Reply.EMPTY_STACK;
85         Arrays.fill(ddmCollectionLenStack_, 0);
86         ddmScalarLen_ = 0;
87         dssLength_ = 0;
88         dssIsContinued_ = false;
89         dssIsChainedWithSameID_ = false;
90         dssIsChainedWithDiffID_ = false;
91         dssCorrelationID_ = 1;
92     }
93
94     final int getDdmLength() {
95         return ddmScalarLen_;
96     }
97
98     // This is a helper method which shifts the buffered bytes from
99
// wherever they are in the current buffer to the beginning of
100
// different buffer (note these buffers could be the same).
101
// State information is updated as needed after the shift.
102
private final void shiftBuffer(byte[] destinationBuffer) {
103         // calculate the size of the data in the current buffer.
104
int sz = count_ - pos_;
105
106         // copy this data to the new buffer starting at position 0.
107
System.arraycopy(buffer_, pos_, destinationBuffer, 0, sz);
108
109         // update the state information for data in the new buffer.
110
pos_ = 0;
111         count_ = sz;
112
113         // replace the old buffer with the new buffer.
114
buffer_ = destinationBuffer;
115     }
116
117     // This method makes sure there is enough room in the buffer
118
// for a certain number of bytes. This method will allocate
119
// a new buffer if needed and shift the bytes in the current buffer
120
// to make ensure space is available for a fill. Right now
121
// this method will shift bytes as needed to make sure there is
122
// as much room as possible in the buffer before trying to
123
// do the read. The idea is to try to have space to get as much data as possible
124
// if we need to do a read on the socket's stream.
125
protected final void ensureSpaceInBufferForFill(int desiredSpace) {
126         // calculate the total unused space in the buffer.
127
// this includes any space at the end of the buffer and any free
128
// space at the beginning resulting from bytes already read.
129
int currentAvailableSpace = (buffer_.length - count_) + pos_;
130
131         // check to see if there is enough free space.
132
if (currentAvailableSpace < desiredSpace) {
133
134             // there is not enough free space so we need more storage.
135
// we are going to double the buffer unless that happens to still be too small.
136
// if more than double the buffer is needed, use the smallest amount over this as possible.
137
int doubleBufferSize = (2 * buffer_.length);
138
139             int minumNewBufferSize = (desiredSpace - currentAvailableSpace) + buffer_.length;
140             int newsz = minumNewBufferSize <= doubleBufferSize ? doubleBufferSize : minumNewBufferSize;
141
142             byte[] newBuffer = new byte[newsz];
143
144             // shift everything from the old buffer to the new buffer
145
shiftBuffer(newBuffer);
146         } else {
147
148             // there is enough free space in the buffer but let's make sure it is all at the end.
149
// this is also important because if we are going to do a read, it would be nice
150
// to get as much data as possible and making room at the end if the buffer helps to
151
// ensure this.
152
if (pos_ != 0) {
153                 shiftBuffer(buffer_);
154             }
155         }
156     }
157
158     // This method will attempt to read a minimum number of bytes
159
// from the underlying stream. This method will keep trying to
160
// read bytes until it has obtained at least the minimum number.
161
// Now returns the total bytes read for decryption, use to return void.
162
protected int fill(int minimumBytesNeeded) throws DisconnectException {
163         // make sure that there is enough space in the buffer to hold
164
// the minimum number of bytes needed.
165
ensureSpaceInBufferForFill(minimumBytesNeeded);
166
167         // read until the minimum number of bytes needed is now in the buffer.
168
// hopefully the read method will return as many bytes as it can.
169
int totalBytesRead = 0;
170         int actualBytesRead = 0;
171         do {
172             try {
173                 // oops, we shouldn't expose the agent's input stream here, collapse this into a read method on the agent
174
actualBytesRead = netAgent_.getInputStream().read(buffer_, count_, buffer_.length - count_);
175             } catch (java.io.IOException JavaDoc ioe) {
176                 netAgent_.throwCommunicationsFailure(ioe);
177             } finally {
178                 if (agent_.loggingEnabled()) {
179                     ((NetLogWriter) netAgent_.logWriter_).traceProtocolFlow(buffer_,
180                             count_,
181                             actualBytesRead,
182                             NetLogWriter.TYPE_TRACE_RECEIVE,
183                             "Reply",
184                             "fill",
185                             2); // tracepoint
186
}
187             }
188             count_ += actualBytesRead;
189             totalBytesRead += actualBytesRead;
190
191         } while ((totalBytesRead < minimumBytesNeeded) && (actualBytesRead != -1));
192
193         if (actualBytesRead == -1) {
194             if (totalBytesRead < minimumBytesNeeded) {
195                 netAgent_.accumulateChainBreakingReadExceptionAndThrow(
196                     new DisconnectException(netAgent_,
197                         new ClientMessageId(SQLState.NET_INSUFFICIENT_DATA),
198                         new Integer JavaDoc(minimumBytesNeeded),
199                         new Integer JavaDoc(totalBytesRead)));
200             }
201         }
202         return totalBytesRead;
203     }
204
205     // Make sure a certain amount of Layer A data is in the buffer.
206
// The data will be in the buffer after this method is called.
207
// Now returns the total bytes read for decryption, use to return void.
208
protected final int ensureALayerDataInBuffer(int desiredDataSize) throws DisconnectException {
209         int totalBytesRead = 0;
210         // calulate the the number of bytes in the buffer.
211
int avail = count_ - pos_;
212
213         // read more bytes off the network if the data is not in the buffer already.
214
if (avail < desiredDataSize) {
215             totalBytesRead = fill(desiredDataSize - avail);
216         }
217         return totalBytesRead;
218     }
219
220     protected final void ensureBLayerDataInBuffer(int desiredDataSize) throws DisconnectException {
221         if (dssIsContinued_ && (desiredDataSize > dssLength_)) {
222             int continueDssHeaderCount =
223                     (((desiredDataSize - dssLength_) / 32767) + 1);
224             ensureALayerDataInBuffer(desiredDataSize + (continueDssHeaderCount * 2));
225             compressBLayerData(continueDssHeaderCount);
226             return;
227         }
228         ensureALayerDataInBuffer(desiredDataSize);
229     }
230
231     // this will probably never be called.
232
// it is included here in the highly unlikely event that a reply object
233
// exceeds 32K. for opimization purposes, we should consider
234
// removing this. removing this should be ok since we handle most
235
// big stuff returned from the server (qrydta's for example) by
236
// copying out the data into some other storage. any extended dss header
237
// info will be removed in the copying process.
238
private final void compressBLayerData(int continueDssHeaderCount) throws DisconnectException {
239         int tempPos = 0;
240
241         // jump to the last continuation header.
242
for (int i = 0; i < continueDssHeaderCount; i++) {
243             // the first may be less than the size of a full dss
244
if (i == 0) {
245                 // only jump by the number of bytes remaining in the current dss
246
tempPos = pos_ + dssLength_;
247             } else {
248                 // all other jumps are for a full continued dss
249
tempPos += 32767;
250             }
251         }
252
253         // for each of the dss headers to remove,
254
// read out the continuation header and increment the dss length by the
255
// size of the conitnation bytes, then shift the continuation data as needed.
256
int shiftSize = 0;
257         int bytesToShift = 0;
258         int continueHeaderLength = 0;
259         int newDssLength = 0;
260         for (int i = 0; i < continueDssHeaderCount; i++) {
261
262             continueHeaderLength = ((buffer_[tempPos] & 0xFF) << 8) +
263                     ((buffer_[tempPos + 1] & 0xFF) << 0);
264
265             if (i == 0) {
266                 // if this is the last one (farthest down stream and first to strip out)
267

268                 if ((continueHeaderLength & 0x8000) == 0x8000) {
269                     // the last dss header is again continued
270
continueHeaderLength = 32767;
271                     dssIsContinued_ = true;
272                 } else {
273                     // the last dss header was not contiued so update continue state flag
274
dssIsContinued_ = false;
275                 }
276                 // the very first shift size is 2
277
shiftSize = 2;
278             } else {
279                 // already removed the last header so make sure the chaining flag is on
280
if ((continueHeaderLength & 0x8000) == 0x8000) {
281                     continueHeaderLength = 32767;
282                 } else {
283                     // this is a syntax error but not really certain which one.
284
// for now pick 0x02 which is Dss header Length does not match the number
285
// of bytes of data found.
286
doSyntaxrmSemantics(CodePoint.SYNERRCD_DSS_LENGTH_BYTE_NUMBER_MISMATCH);
287                 }
288                 // increase the shift size by 2
289
shiftSize += 2;
290             }
291
292             // it is a syntax error if the dss continuation is less than or equal to two
293
if (continueHeaderLength <= 2) {
294                 doSyntaxrmSemantics(CodePoint.SYNERRCD_DSS_CONT_LESS_OR_EQUAL_2);
295             }
296
297             newDssLength += (continueHeaderLength - 2);
298
299             // calculate the number of bytes to shift
300
if (i != (continueDssHeaderCount - 1)) {
301                 bytesToShift = 32767;
302             } else {
303                 bytesToShift = dssLength_;
304             }
305
306             tempPos -= (bytesToShift - 2);
307             System.arraycopy(buffer_, tempPos - shiftSize, buffer_, tempPos , bytesToShift);
308         }
309         // reposition the start of the data after the final dss shift.
310
pos_ = tempPos;
311         dssLength_ = dssLength_ + newDssLength;
312     }
313
314     protected final void readDssHeader() throws DisconnectException {
315         int correlationID = 0;
316         int nextCorrelationID = 0;
317         ensureALayerDataInBuffer(6);
318
319         // read out the dss length
320
dssLength_ =
321                 ((buffer_[pos_++] & 0xFF) << 8) +
322                 ((buffer_[pos_++] & 0xFF) << 0);
323
324         // Remember the old dss length for decryption only.
325
int oldDssLength = dssLength_;
326
327         // check for the continuation bit and update length as needed.
328
if ((dssLength_ & 0x8000) == 0x8000) {
329             dssLength_ = 32767;
330             dssIsContinued_ = true;
331         } else {
332             dssIsContinued_ = false;
333         }
334
335         if (dssLength_ < 6) {
336             doSyntaxrmSemantics(CodePoint.SYNERRCD_DSS_LESS_THAN_6);
337         }
338
339         // If the GDS id is not valid, or
340
// if the reply is not an RPYDSS nor
341
// a OBJDSS, then throw an exception.
342
if ((buffer_[pos_++] & 0xFF) != 0xd0) {
343             doSyntaxrmSemantics(CodePoint.SYNERRCD_CBYTE_NOT_D0);
344         }
345
346         int gdsFormatter = buffer_[pos_++] & 0xFF;
347         if (((gdsFormatter & 0x02) != 0x02)
348                 && ((gdsFormatter & 0x03) != 0x03)
349                 && ((gdsFormatter & 0x04) != 0x04)) {
350             doSyntaxrmSemantics(CodePoint.SYNERRCD_FBYTE_NOT_SUPPORTED);
351         }
352
353         // Determine if the current DSS is chained with the
354
// next DSS, with the same or different request ID.
355
if ((gdsFormatter & 0x40) == 0x40) { // on indicates structure chained to next structure
356
if ((gdsFormatter & 0x10) == 0x10) {
357                 dssIsChainedWithSameID_ = true;
358                 dssIsChainedWithDiffID_ = false;
359                 nextCorrelationID = dssCorrelationID_;
360             } else {
361                 dssIsChainedWithSameID_ = false;
362                 dssIsChainedWithDiffID_ = true;
363                 nextCorrelationID = dssCorrelationID_ + 1;
364             }
365         } else {
366             // chaining bit not b'1', make sure DSSFMT bit3 not b'1'
367
if ((gdsFormatter & 0x10) == 0x10) { // Next DSS can not have same correlator
368
doSyntaxrmSemantics(CodePoint.SYNERRCD_CHAIN_OFF_SAME_NEXT_CORRELATOR);
369             }
370
371             // chaining bit not b'1', make sure no error continuation
372
if ((gdsFormatter & 0x20) == 0x20) { // must be 'do not continue on error'
373
doSyntaxrmSemantics(CodePoint.SYNERRCD_CHAIN_OFF_ERROR_CONTINUE);
374             }
375
376             dssIsChainedWithSameID_ = false;
377             dssIsChainedWithDiffID_ = false;
378             nextCorrelationID = 1;
379         }
380
381         correlationID =
382                 ((buffer_[pos_++] & 0xFF) << 8) +
383                 ((buffer_[pos_++] & 0xFF) << 0);
384
385         // corrid must be the one expected or a -1 which gets returned in some error cases.
386
if ((correlationID != dssCorrelationID_) && (correlationID != 0xFFFF)) {
387             doSyntaxrmSemantics(CodePoint.SYNERRCD_INVALID_CORRELATOR);
388         } else {
389             dssCorrelationID_ = nextCorrelationID;
390         }
391         dssLength_ -= 6;
392         if ((gdsFormatter & 0x04) == 0x04) {
393             decryptData(gdsFormatter, oldDssLength); //we have to decrypt data here because
394
}
395         //we need the decrypted codepoint. If
396
//Data is very long > 32767, we have to
397
//get all the data first because decrypt
398
//piece by piece doesn't work.
399
}
400
401
402     private final void decryptData(int gdsFormatter, int oldDssLength) throws DisconnectException {
403         boolean readHeader;
404
405         if (dssLength_ == 32761) {
406             ByteArrayOutputStream JavaDoc baos;
407             int copySize = 0;
408
409             baos = new ByteArrayOutputStream JavaDoc();
410
411             // set the amount to read for the first segment
412
copySize = dssLength_; // note: has already been adjusted for headers
413

414             do {
415                 // determine if a continuation header needs to be read after the data
416
if (dssIsContinued_) {
417                     readHeader = true;
418                 } else {
419                     readHeader = false;
420                 }
421
422                 // read the segment
423
ensureALayerDataInBuffer(copySize);
424                 adjustLengths(copySize);
425                 baos.write(buffer_, pos_, copySize);
426                 pos_ += copySize;
427
428                 // read the continuation header, if necessary
429
if (readHeader) {
430                     readDSSContinuationHeader();
431                 }
432
433                 copySize = dssLength_;
434             } while (readHeader == true);
435             byte[] cipherBytes = baos.toByteArray();
436             byte[] clearedByte = null;
437             try {
438                 clearedByte = netAgent_.netConnection_.getEncryptionManager().decryptData(cipherBytes,
439                         NetConfiguration.SECMEC_EUSRIDPWD,
440                         netAgent_.netConnection_.getTargetPublicKey(),
441                         netAgent_.netConnection_.getTargetPublicKey());
442             } catch (SqlException e) {
443                 //throw new SqlException (agent_.logWriter_, "error in decrypting data");
444
}
445
446             //The decrypted data is for one codepoint only. We need to save the data follows this codepoint
447
longBufferForDecryption_ = new byte[buffer_.length - pos_];
448             longPosForDecryption_ = 0;
449             count_ = count_ - pos_;
450             longCountForDecryption_ = count_;
451             System.arraycopy(buffer_, pos_, longBufferForDecryption_, 0, buffer_.length - pos_);
452
453             //copy the clear data to buffer_
454
if (clearedByte.length >= 32767) {
455                 System.arraycopy(clearedByte, 0, buffer_, 0, 32767);
456             } else {
457                 System.arraycopy(clearedByte, 0, buffer_, 0, clearedByte.length);
458             }
459
460             pos_ = 0;
461             dssLength_ = buffer_.length;
462
463             int lobLength = 0;
464             if (clearedByte.length > 32767) { //for extended length, length is the 4 bytes that follow codepoint
465
lobLength = ((clearedByte[4] & 0xFF) << 24) +
466                         ((clearedByte[5] & 0xFF) << 16) +
467                         ((clearedByte[6] & 0xFF) << 8) +
468                         ((clearedByte[7] & 0xFF) << 0);
469                 longValueForDecryption_ = new byte[lobLength];
470                 System.arraycopy(clearedByte, 8, longValueForDecryption_, 0, clearedByte.length - 8);
471             } else {
472                 lobLength = ((clearedByte[0] & 0xFF) << 8) +
473                         ((clearedByte[1] & 0xFF) << 0);
474                 longValueForDecryption_ = new byte[lobLength - 4];
475                 System.arraycopy(clearedByte, 4, longValueForDecryption_, 0, clearedByte.length - 4);
476             }
477         } else {
478             int bytesRead = ensureALayerDataInBuffer(dssLength_); //we need to get back all the data here, and then decrypt
479
if (bytesRead > 0) //we ensuredALayerDAtaInBuffer here and set the flag to true, so we don't need do this again later
480
{
481                 ensuredLengthForDecryption_ = true;
482             }
483             byte[] encryptedByte = new byte[dssLength_];
484             System.arraycopy(buffer_, pos_, encryptedByte, 0, dssLength_);
485             byte[] array1 = new byte[pos_];
486             System.arraycopy(buffer_, 0, array1, 0, pos_); //save the data before encrypted data in array1
487
byte[] array3 = new byte[buffer_.length - dssLength_ - pos_];
488             System.arraycopy(buffer_, pos_ + dssLength_, array3, 0, buffer_.length - dssLength_ - pos_); //save the data follows encrypted data in array3
489
byte[] clearedByte = null;
490             try {
491                 clearedByte = netAgent_.netConnection_.getEncryptionManager().decryptData(encryptedByte,
492                         NetConfiguration.SECMEC_EUSRIDPWD,
493                         netAgent_.netConnection_.getTargetPublicKey(),
494                         netAgent_.netConnection_.getTargetPublicKey());
495             } catch (SqlException e) {
496                 //throw new SqlException (agent_.logWriter_, "error in decrypting data");
497
}
498             dssLength_ -= (encryptedByte.length - clearedByte.length);
499             byte[] buffer = new byte[array1.length + clearedByte.length + array3.length];
500             System.arraycopy(array1, 0, buffer, 0, array1.length);
501             System.arraycopy(clearedByte, 0, buffer, array1.length, clearedByte.length);
502             System.arraycopy(array3, 0, buffer, array1.length + clearedByte.length, array3.length);
503             buffer_ = buffer;
504             int oldCount = count_;
505             count_ = count_ - (encryptedByte.length - clearedByte.length);
506             if (((clearedByte[2] & 0xff) << 8) + ((clearedByte[3] & 0xff) << 0) == 0x146c) {
507                 int firstLobLength = ((clearedByte[0] & 0xFF) << 8) +
508                         ((clearedByte[1] & 0xFF) << 0);
509
510                 boolean flag = false;
511                 if (gdsFormatter == 0x54) {
512                     flag = true;
513                 }
514                 if (flag) {
515                     if (oldCount - oldDssLength < 6) {
516                         int totalBytesRead = fill(6); //sometimes the 2nd EXTDTA doesn't come back, need to fetch again to get it
517
if (totalBytesRead > 0) {
518                             longBufferForDecryption_ = new byte[totalBytesRead];
519                             longPosForDecryption_ = 0;
520                             System.arraycopy(buffer_, pos_ + firstLobLength, longBufferForDecryption_, 0,
521                                     totalBytesRead);
522                         }
523
524                     } else {
525                         longBufferForDecryption_ = new byte[count_ - pos_ - firstLobLength];
526                         longPosForDecryption_ = 0;
527                         System.arraycopy(buffer_, pos_ + firstLobLength, longBufferForDecryption_, 0,
528                                 longBufferForDecryption_.length);
529
530                     }
531                 } //end if(flag)
532
int lobLength = ((clearedByte[0] & 0xFF) << 8) +
533                         ((clearedByte[1] & 0xFF) << 0) - 4;
534
535                 longValueForDecryption_ = new byte[lobLength];
536
537                 System.arraycopy(clearedByte, 4, longValueForDecryption_, 0, clearedByte.length - 4); //copy the decrypted lob value (excluded length an dcodepoint) to longValue_
538
} else if (((clearedByte[2] & 0xff) << 8) + ((clearedByte[3] & 0xff) << 0) == 0x241B) {
539                 int length = ((clearedByte[0] & 0xFF) << 8) +
540                         ((clearedByte[1] & 0xFF) << 0);
541                 boolean noData = false;
542                 if (clearedByte[4] == -1 && clearedByte[5] == -1) {
543                     noData = true; //there is no data, no need to do the copy
544
}
545                 if (!noData) {
546                     if (length == 32776) {
547                         length = ((clearedByte[4] & 0xFF) << 24) +
548                                 ((clearedByte[5] & 0xFF) << 16) +
549                                 ((clearedByte[6] & 0xFF) << 8) +
550                                 ((clearedByte[7] & 0xFF) << 0);
551                         longValueForDecryption_ = new byte[length];
552                         System.arraycopy(clearedByte, 8, longValueForDecryption_, 0,
553                                 clearedByte.length - 8);
554                         longCountForDecryption_ = count_ - (pos_ + length + 8);
555                         longBufferForDecryption_ = new byte[buffer_.length - pos_ - length - 8];
556                         System.arraycopy(buffer_, pos_ + length + 8, longBufferForDecryption_, 0,
557                                 longBufferForDecryption_.length);
558
559                     } else {
560                         longPosForDecryption_ = 0;
561                         longCountForDecryption_ = count_ - (pos_ + length);
562                         longBufferForDecryption_ = new byte[buffer_.length - pos_ - length];
563                         System.arraycopy(buffer_, pos_ + length, longBufferForDecryption_, 0,
564                                 longBufferForDecryption_.length);
565
566                         longValueForDecryption_ = new byte[length - 4];
567
568                         System.arraycopy(clearedByte, 4, longValueForDecryption_, 0,
569                                 clearedByte.length - 4);
570                     }
571                 }
572             }
573         }
574     }
575
576
577     final int readUnsignedShort() throws DisconnectException {
578         // should we be checking dss lengths and ddmScalarLengths here
579
// if yes, i am not sure this is the correct place if we should be checking
580
ensureBLayerDataInBuffer(2);
581         adjustLengths(2);
582         return ((buffer_[pos_++] & 0xff) << 8) +
583                 ((buffer_[pos_++] & 0xff) << 0);
584     }
585
586     final short readShort() throws DisconnectException {
587         // should we be checking dss lengths and ddmScalarLengths here
588
ensureBLayerDataInBuffer(2);
589         adjustLengths(2);
590         short s = SignedBinary.getShort(buffer_, pos_);
591
592         pos_ += 2;
593
594         return s;
595     }
596
597     final int readInt() throws DisconnectException {
598         // should we be checking dss lengths and ddmScalarLengths here
599
ensureBLayerDataInBuffer(4);
600         adjustLengths(4);
601         int i = SignedBinary.getInt(buffer_, pos_);
602         pos_ += 4;
603
604         return i;
605     }
606
607     final void readIntArray(int[] array) throws DisconnectException {
608         ensureBLayerDataInBuffer(array.length * 4);
609         adjustLengths(array.length * 4);
610
611         for (int i = 0; i < array.length; i++) {
612             array[i] = SignedBinary.getInt(buffer_, pos_);
613             pos_ += 4;
614         }
615     }
616
617
618     final long readLong() throws DisconnectException {
619         // should we be checking dss lengths and ddmScalarLengths here
620
ensureBLayerDataInBuffer(8);
621         adjustLengths(8);
622         long l = SignedBinary.getLong(buffer_, pos_);
623
624         pos_ += 8;
625
626         return l;
627     }
628
629
630     final int[] readUnsignedShortList() throws DisconnectException {
631         int len = ddmScalarLen_;
632         ensureBLayerDataInBuffer(len);
633         adjustLengths(len);
634
635         int count = len / 2;
636         int[] list = new int[count];
637
638         for (int i = 0; i < count; i++) {
639             list[i] = ((buffer_[pos_++] & 0xff) << 8) +
640                     ((buffer_[pos_++] & 0xff) << 0);
641         }
642
643         return list;
644     }
645
646     final int readUnsignedByte() throws DisconnectException {
647         ensureBLayerDataInBuffer(1);
648         adjustLengths(1);
649         return (buffer_[pos_++] & 0xff);
650     }
651
652     final byte readByte() throws DisconnectException {
653         ensureBLayerDataInBuffer(1);
654         adjustLengths(1);
655         return (byte) (buffer_[pos_++] & 0xff);
656     }
657
658     final boolean readBoolean() throws DisconnectException {
659         ensureBLayerDataInBuffer(1);
660         adjustLengths(1);
661         return buffer_[pos_++] != 0;
662     }
663
664     final String JavaDoc readString(int length) throws DisconnectException {
665         ensureBLayerDataInBuffer(length);
666         adjustLengths(length);
667
668         String JavaDoc result = ccsidManager_.convertToUCS2(buffer_, pos_, length);
669         pos_ += length;
670         return result;
671     }
672
673     final String JavaDoc readString(int length, String JavaDoc encoding) throws DisconnectException {
674         ensureBLayerDataInBuffer(length);
675         adjustLengths(length);
676         String JavaDoc s = null;
677
678         try {
679             s = new String JavaDoc(buffer_, pos_, length, encoding);
680         } catch (java.io.UnsupportedEncodingException JavaDoc e) {
681             agent_.accumulateChainBreakingReadExceptionAndThrow(
682                 new DisconnectException(agent_,
683                     new ClientMessageId(SQLState.NET_ENCODING_NOT_SUPPORTED),
684                     e));
685         }
686
687         pos_ += length;
688         return s;
689     }
690
691     final String JavaDoc readString() throws DisconnectException {
692         int len = ddmScalarLen_;
693         ensureBLayerDataInBuffer(len);
694         adjustLengths(len);
695         String JavaDoc result = ccsidManager_.convertToUCS2(buffer_, pos_, len);
696         pos_ += len;
697         return result;
698     }
699
700     final byte[] readBytes(int length) throws DisconnectException {
701         ensureBLayerDataInBuffer(length);
702         adjustLengths(length);
703
704         byte[] b = new byte[length];
705         System.arraycopy(buffer_, pos_, b, 0, length);
706         pos_ += length;
707         return b;
708     }
709
710     final byte[] readBytes() throws DisconnectException {
711         int len = ddmScalarLen_;
712         ensureBLayerDataInBuffer(len);
713         adjustLengths(len);
714
715         byte[] b = new byte[len];
716         System.arraycopy(buffer_, pos_, b, 0, len);
717         pos_ += len;
718         return b;
719     }
720
721     final byte[] readLDBytes() throws DisconnectException {
722         ensureBLayerDataInBuffer(2);
723         int len = ((buffer_[pos_++] & 0xff) << 8) + ((buffer_[pos_++] & 0xff) << 0);
724
725         if (len == 0) {
726             adjustLengths(2);
727             return null;
728         }
729
730         ensureBLayerDataInBuffer(len);
731         adjustLengths(len + 2);
732
733         byte[] b = new byte[len];
734         System.arraycopy(buffer_, pos_, b, 0, len);
735         pos_ += len;
736         return b;
737     }
738
739     final void skipBytes(int length) throws DisconnectException {
740         ensureBLayerDataInBuffer(length);
741         adjustLengths(length);
742         pos_ += length;
743     }
744
745     final void skipBytes() throws DisconnectException {
746         int len = ddmScalarLen_;
747         ensureBLayerDataInBuffer(len);
748         adjustLengths(len);
749         pos_ += len;
750     }
751
752     // This will be the new and improved getData that handles all QRYDTA/EXTDTA
753
// Returns the stream so that the caller can cache it
754
final ByteArrayOutputStream JavaDoc getData(ByteArrayOutputStream JavaDoc existingBuffer) throws DisconnectException {
755         boolean readHeader;
756         int copySize;
757         ByteArrayOutputStream JavaDoc baos;
758
759         // note: an empty baos can yield an allocated and empty byte[]
760
if (existingBuffer != null) {
761             baos = existingBuffer;
762         } else {
763             if (ddmScalarLen_ != -1) {
764                 // allocate a stream based on a known amount of data
765
baos = new ByteArrayOutputStream JavaDoc(ddmScalarLen_);
766             } else {
767                 // allocate a stream to hold an unknown amount of data
768
baos = new ByteArrayOutputStream JavaDoc();
769                 //isLengthAndNullabilityUnknown = true;
770
}
771         }
772
773         // set the amount to read for the first segment
774
copySize = dssLength_; // note: has already been adjusted for headers
775

776         do {
777             // determine if a continuation header needs to be read after the data
778
if (dssIsContinued_) {
779                 readHeader = true;
780             } else {
781                 readHeader = false;
782             }
783
784             // read the segment
785
ensureALayerDataInBuffer(copySize);
786             adjustLengths(copySize);
787             baos.write(buffer_, pos_, copySize);
788             pos_ += copySize;
789
790             // read the continuation header, if necessary
791
if (readHeader) {
792                 readDSSContinuationHeader();
793             }
794
795             copySize = dssLength_;
796         } while (readHeader == true);
797
798         return baos;
799     }
800
801     // reads a DSS continuation header
802
// prereq: pos_ is positioned on the first byte of the two-byte header
803
// post: dssIsContinued_ is set to true if the continuation bit is on, false otherwise
804
// dssLength_ is set to DssConstants.MAX_DSS_LEN - 2 (don't count the header for the next read)
805
// helper method for getEXTDTAData
806
protected final void readDSSContinuationHeader() throws DisconnectException {
807         ensureALayerDataInBuffer(2);
808
809         dssLength_ =
810                 ((buffer_[pos_++] & 0xFF) << 8) +
811                 ((buffer_[pos_++] & 0xFF) << 0);
812
813         if ((dssLength_ & 0x8000) == 0x8000) {
814             dssLength_ = DssConstants.MAX_DSS_LEN;
815             dssIsContinued_ = true;
816         } else {
817             dssIsContinued_ = false;
818         }
819         // it is a syntax error if the dss continuation header length
820
// is less than or equal to two
821
if (dssLength_ <= 2) {
822             doSyntaxrmSemantics(CodePoint.SYNERRCD_DSS_CONT_LESS_OR_EQUAL_2);
823         }
824
825         dssLength_ -= 2; // avoid consuming the DSS cont header
826
}
827
828
829     // As part of parsing the reply, the client can detect that the
830
// data sent from the target agent does not structurally
831
// conform to the requirements of the DDM architecture. These are
832
// the same checks performed by the target server on the messages
833
// it receives from the protocolj code. Server side detected errors
834
// result in a SYNTAXRM being returned from the AS. According to the
835
// DDM manual, parsing of the DSS is terminated when the error is
836
// detected. The Syntax Error Code, SYNERRCD, describes the various errors.
837
//
838
// Note: Not all of these may be valid at the client. See descriptions for
839
// which ones make sense for client side errors/checks.
840
// Syntax Error Code Description of Error
841
// ----------------- --------------------
842
// 0x01 Dss header Length is less than 6.
843
// 0x02 Dss header Length does not match the
844
// number of bytes of data found.
845
// 0x03 Dss header C-byte not D0.
846
// 0x04 Dss header f-bytes either not
847
// recognized or not supported.
848
// 0x05 DSS continuation specified but not found.
849
// For example, DSS continuation is specified
850
// on the last DSS, and the SNA LU 6.2 communication
851
// facility returned the SEND indicator.
852
// 0x06 DSS chaining specified but no DSS found.
853
// For example, DSS chaining is specified
854
// on the last DSS, and the SNA LU 6.2 communication
855
// facility returned the SEND indicator.
856
// 0x07 Object length less than four. For example,
857
// a command parameter's length is specified
858
// as two, or a command's length is specified as three.
859
// 0x08 Object length does not match the number of bytes of data
860
// found. For example, a RQSDSS with a length of 150
861
// contains a command whose length is 125 or a SRVDGN parameter
862
// specifies a length of 200 but there are only 50
863
// bytes left in the DSS.
864
// 0x09 Object length greater than maximum allowed.
865
// For example, a RECCNT parameter specifies a
866
// length of ten, but the parameter is defined
867
// to have a maximum length of eight.
868
// 0x0A Object length less than the minimum required.
869
// For example, a SVRCOD parameter specifies a
870
// length of five, but the parameter is defined
871
// to have a fixed length of six.
872
// 0x0B Object length not allowed. For example,
873
// a FILEXDPT parameter is specified with a length of
874
// 11, but this would indicate that only half of the hours
875
// field is present instead of the complete hours field.
876
// 0x0C Incorrect large object extended length field (see
877
// description of DSS). For example, an extended
878
// length field is present, but it is only three bytes
879
// long when it is defined to be a multiple of two bytes.
880
// 0x0D Object code point index not supported.
881
// For example, a code point of 8032 is encountered
882
// but x'8' is a reserved code point index.
883
// 0x0E Required object not found. For example, a CLEAR
884
// command does not have a filnam parameter present,
885
// or a MODREC command is not followed by a RECORD
886
// command data object.
887
// 0x0F Too many command data objects sent. For example,
888
// a MODREC command is followed by two RECORD command
889
// command data objects, or a DECREC command is followed
890
// by RECORD object.
891
// 0x10 Mutually exclusive objects present.
892
// For example, a CRTDIRF command specifies both
893
// a DCLNAM and FILNAM parameters.
894
// 0x11 Too few command data objects sent.
895
// For example, an INSRECEF command that
896
// specified RECCNT95) is followed by only
897
// 4 RECORD command data objects.
898
// 0x12 Duplicate object present.
899
// For example, a LSTFAT command has tow FILNAM
900
// parameters specified.
901
// 0x13 Invalid request correlator specified.
902
// Use PRCCNVRM with PRCCNVDC of 04 or 05 instead
903
// of this error code. This error code is being retained
904
// for compatibility with Level 1 of the architecture.
905
// 0x14 Required value not found.
906
// 0x15 Reserved value not allowed. For example,
907
// a INSRECEF command specified a RECCNT(0) parameter.
908
// 0x16 DSS continuation less than or equal to two.
909
// For example, the length bytes of the DSS continuation
910
// have the value of one.
911
// 0x17 Objects not in required order. For example, a RECAL
912
// object contains a RECORD object followed by a RECNBR
913
// object with is not in the defined order.
914
// 0x18 DSS chaining byt not b'1', but DSSFMT bit3 set to b'1'.
915
// 0x19 Previous DSS indicated current DSS has the same
916
// request correlator, but the request correlators are
917
// not the same.
918
// 0x1A DSS cahining bit not b'1', but error continuation requested.
919
// 0x1B Mutually exclusive parameter values not specified.
920
// For example, an OPEN command specified PRPSHD(TRUE)
921
// and FILSHR(READER).
922
// 0x1D Code point not valid command. For example, the first
923
// code point in RQSDSS either is not in the dictionary
924
// or is not a code point for a command.
925
//
926
// When the client detects these errors, it will be handled as if a SYNTAXRM is returned
927
// from the server. In this SYNTAXRM case, PROTOCOL architects an SQLSTATE of 58008 or 58009.
928
//
929
// Messages
930
// SQLSTATE : 58009
931
// Execution failed due to a distribution protocol error that caused deallocation of the conversation.
932
// SQLCODE : -30020
933
// Execution failed because of a Distributed Protocol
934
// Error that will affect the successful execution of subsequent
935
// commands and SQL statements: Reason Code <reason-code>.
936
// Some possible reason codes include:
937
// 121C Indicates that the user is not authorized to perform the requested command.
938
// 1232 The command could not be completed because of a permanent error.
939
// In most cases, the server will be in the process of an abend.
940
// 220A The target server has received an invalid data description.
941
// If a user SQLDA is specified, ensure that the fields are
942
// initialized correctly. Also, ensure that the length does not
943
// exceed the maximum allowed length for the data type being used.
944
//
945
// The command or statement cannot be processed. The current
946
// transaction is rolled back and the application is disconnected
947
// from the remote database.
948
final void doSyntaxrmSemantics(int syntaxErrorCode) throws DisconnectException {
949         agent_.accumulateChainBreakingReadExceptionAndThrow(
950             new DisconnectException(agent_,
951                 new ClientMessageId(SQLState.DRDA_CONNECTION_TERMINATED),
952                 SqlException.getMessageUtil().getTextMessage(
953                     MessageId.CONN_DRDA_DATASTREAM_SYNTAX_ERROR,
954                     new Integer JavaDoc(syntaxErrorCode))));
955     }
956
957
958 // the names of these methods start with a letter z.
959
// the z will be removed when they are finalized...
960

961     protected final void pushLengthOnCollectionStack() {
962         ddmCollectionLenStack_[++topDdmCollectionStack_] = ddmScalarLen_;
963         ddmScalarLen_ = 0;
964     }
965
966     protected final void adjustLengths(int length) {
967         ddmScalarLen_ -= length;
968         adjustCollectionAndDssLengths(length);
969         /*
970         for (int i = 0; i <= topDdmCollectionStack_; i++) {
971           ddmCollectionLenStack_[i] -= length;
972         }
973         dssLength_ -= length;
974         */

975     }
976
977     protected int adjustDdmLength(int ddmLength, int length) {
978         ddmLength -= length;
979         if (ddmLength == 0) {
980             adjustLengths(getDdmLength());
981         }
982         return ddmLength;
983     }
984
985     // Pop the collection Length stack.
986
// pre: The collection length stack must not be empty and the top value
987
// on the stack must be 0.
988
// post: The top 0 value on the stack will be popped.
989
protected final void popCollectionStack() {
990         topDdmCollectionStack_--;
991     }
992
993     protected final int peekCodePoint() throws DisconnectException {
994         if (topDdmCollectionStack_ != EMPTY_STACK) {
995             if (ddmCollectionLenStack_[topDdmCollectionStack_] == 0) {
996                 return END_OF_COLLECTION;
997             } else if (ddmCollectionLenStack_[topDdmCollectionStack_] < 4) {
998                 // error
999
}
1000        }
1001
1002        // if there is no more data in the current dss, and the dss is not
1003
// continued, indicate the end of the same Id chain or read the next dss header.
1004
if ((dssLength_ == 0) && (!dssIsContinued_)) {
1005            if (!dssIsChainedWithSameID_) {
1006                return END_OF_SAME_ID_CHAIN;
1007            }
1008            readDssHeader();
1009        }
1010
1011        if (longBufferForDecryption_ == null) //we don't need to do this if it's data stream encryption
1012
{
1013            ensureBLayerDataInBuffer(4);
1014        }
1015        peekedLength_ = ((buffer_[pos_] & 0xff) << 8) + ((buffer_[pos_ + 1] & 0xff) << 0);
1016        peekedCodePoint_ = ((buffer_[pos_ + 2] & 0xff) << 8) + ((buffer_[pos_ + 3] & 0xff) << 0);
1017
1018        // check for extended length
1019
if ((peekedLength_ & 0x8000) == 0x8000) {
1020            peekExtendedLength();
1021        } else {
1022            peekedNumOfExtendedLenBytes_ = 0;
1023        }
1024        return peekedCodePoint_;
1025    }
1026
1027    // Read out the 2-byte length without moving the pos_ pointer.
1028
protected final int peekLength() throws DisconnectException {
1029        ensureBLayerDataInBuffer(2);
1030        return (((buffer_[pos_] & 0xff) << 8) +
1031                ((buffer_[pos_ + 1] & 0xff) << 0));
1032    }
1033
1034    // Read "length" number of bytes from the buffer into the byte array b starting from offset
1035
// "offset". The current offset in the buffer does not change.
1036
protected final int peekFastBytes(byte[] b, int offset, int length) throws DisconnectException {
1037        for (int i = 0; i < length; i++) {
1038            b[offset + i] = buffer_[pos_ + i];
1039        }
1040        return offset + length;
1041    }
1042
1043    protected final void parseLengthAndMatchCodePoint(int expectedCodePoint) throws DisconnectException {
1044        int actualCodePoint = 0;
1045        if (peekedCodePoint_ == END_OF_COLLECTION) {
1046            actualCodePoint = readLengthAndCodePoint();
1047        } else {
1048            actualCodePoint = peekedCodePoint_;
1049            pos_ += (4 + peekedNumOfExtendedLenBytes_);
1050            ddmScalarLen_ = peekedLength_;
1051            if (peekedNumOfExtendedLenBytes_ == 0 && ddmScalarLen_ != -1) {
1052                adjustLengths(4);
1053            } else {
1054                adjustCollectionAndDssLengths(4 + peekedNumOfExtendedLenBytes_);
1055            }
1056            peekedLength_ = 0;
1057            peekedCodePoint_ = END_OF_COLLECTION;
1058            peekedNumOfExtendedLenBytes_ = 0;
1059        }
1060
1061        if (actualCodePoint != expectedCodePoint) {
1062            agent_.accumulateChainBreakingReadExceptionAndThrow(
1063                new DisconnectException(agent_,
1064                    new ClientMessageId(SQLState.NET_NOT_EXPECTED_CODEPOINT),
1065                    new Integer JavaDoc(actualCodePoint),
1066                    new Integer JavaDoc(expectedCodePoint)));
1067        }
1068    }
1069
1070    protected final int readLengthAndCodePoint() throws DisconnectException {
1071        if (topDdmCollectionStack_ != EMPTY_STACK) {
1072            if (ddmCollectionLenStack_[topDdmCollectionStack_] == 0) {
1073                return END_OF_COLLECTION;
1074            } else if (ddmCollectionLenStack_[topDdmCollectionStack_] < 4) {
1075                agent_.accumulateChainBreakingReadExceptionAndThrow(
1076                    new DisconnectException(agent_,
1077                    new ClientMessageId(SQLState.NET_DDM_COLLECTION_TOO_SMALL)));
1078            }
1079        }
1080
1081        // if there is no more data in the current dss, and the dss is not
1082
// continued, indicate the end of the same Id chain or read the next dss header.
1083
if ((dssLength_ == 0) && (!dssIsContinued_)) {
1084            if (!dssIsChainedWithSameID_) {
1085                return END_OF_SAME_ID_CHAIN;
1086            }
1087            readDssHeader();
1088        }
1089
1090        ensureBLayerDataInBuffer(4);
1091        ddmScalarLen_ =
1092                ((buffer_[pos_++] & 0xff) << 8) +
1093                ((buffer_[pos_++] & 0xff) << 0);
1094        int codePoint = ((buffer_[pos_++] & 0xff) << 8) +
1095                ((buffer_[pos_++] & 0xff) << 0);
1096        adjustLengths(4);
1097
1098        // check for extended length
1099
if ((ddmScalarLen_ & 0x8000) == 0x8000) {
1100            readExtendedLength();
1101        }
1102        return codePoint;
1103    }
1104
1105    private final void readExtendedLength() throws DisconnectException {
1106        int numberOfExtendedLenBytes = (ddmScalarLen_ - 0x8000); // fix scroll problem was - 4
1107
int adjustSize = 0;
1108        switch (numberOfExtendedLenBytes) {
1109        case 4:
1110            ensureBLayerDataInBuffer(4);
1111            ddmScalarLen_ =
1112                    ((buffer_[pos_++] & 0xff) << 24) +
1113                    ((buffer_[pos_++] & 0xff) << 16) +
1114                    ((buffer_[pos_++] & 0xff) << 8) +
1115                    ((buffer_[pos_++] & 0xff) << 0);
1116            adjustSize = 4;
1117            break;
1118        case 0:
1119            ddmScalarLen_ = -1;
1120            adjustSize = 0;
1121            break;
1122        default:
1123            doSyntaxrmSemantics(CodePoint.SYNERRCD_INCORRECT_EXTENDED_LEN);
1124        }
1125
1126        adjustCollectionAndDssLengths(adjustSize);
1127        /*
1128        // adjust the lengths here. this is a special case since the
1129        // extended length bytes do not include their own length.
1130        for (int i = 0; i <= topDdmCollectionStack_; i++) {
1131          ddmCollectionLenStack_[i] -= adjustSize;
1132        }
1133        dssLength_ -= adjustSize;
1134        */

1135    }
1136
1137    private final void adjustCollectionAndDssLengths(int length) {
1138        // adjust the lengths here. this is a special case since the
1139
// extended length bytes do not include their own length.
1140
for (int i = 0; i <= topDdmCollectionStack_; i++) {
1141            ddmCollectionLenStack_[i] -= length;
1142        }
1143        dssLength_ -= length;
1144    }
1145
1146    protected final void startSameIdChainParse() throws DisconnectException {
1147        readDssHeader();
1148        netAgent_.clearSvrcod();
1149    }
1150
1151    protected final void endOfSameIdChainData() throws DisconnectException {
1152        netAgent_.targetTypdef_ = netAgent_.originalTargetTypdef_;
1153        netAgent_.targetSqlam_ = netAgent_.orignalTargetSqlam_;
1154
1155        if (this.topDdmCollectionStack_ != Reply.EMPTY_STACK) {
1156            agent_.accumulateChainBreakingReadExceptionAndThrow(
1157                new DisconnectException(agent_,
1158                new ClientMessageId(SQLState.NET_COLLECTION_STACK_NOT_EMPTY)));
1159        }
1160        if (this.dssLength_ != 0) {
1161            agent_.accumulateChainBreakingReadExceptionAndThrow(
1162                new DisconnectException(agent_,
1163                new ClientMessageId(SQLState.NET_DSS_NOT_ZERO)));
1164        }
1165        if (dssIsChainedWithSameID_ == true) {
1166            agent_.accumulateChainBreakingReadExceptionAndThrow(
1167                new DisconnectException(agent_,
1168                new ClientMessageId(SQLState.NET_DSS_CHAINED_WITH_SAME_ID)));
1169        }
1170    }
1171    
1172    protected final int peekTotalColumnCount(int tripletLength) throws DisconnectException {
1173        int columnCount = 0;
1174        int offset = 0;
1175        int tripletType = FdocaConstants.CPT_TRIPLET_TYPE;
1176        while (tripletType == FdocaConstants.CPT_TRIPLET_TYPE) {
1177            columnCount += ((tripletLength - 3) / 3);
1178            // Peek ahead for the next triplet's tripletLength and tripletType.
1179
// The number of bytes to skip before the next tripletType is tripletLength - 3.
1180
ensureBLayerDataInBuffer(tripletLength - 3);
1181            offset += (tripletLength - 3);
1182            tripletLength = (buffer_[pos_ + offset++] & 0xff);
1183            tripletType = (buffer_[pos_ + offset++] & 0xff);
1184            // Skip the 1-byte tripletId.
1185
offset++;
1186        }
1187        return columnCount;
1188    }
1189
1190    private final void peekExtendedLength() throws DisconnectException {
1191        peekedNumOfExtendedLenBytes_ = (peekedLength_ - 0x8004);
1192        switch (peekedNumOfExtendedLenBytes_) {
1193        case 4:
1194            // L L C P Extended Length
1195
// -->2-bytes<-- --->4-bytes<---
1196
// We are only peeking the length here, the actual pos_ is still before LLCP. We ensured
1197
// 4-bytes in peedCodePoint() for the LLCP, and we need to ensure 4-bytes(of LLCP) + the
1198
// extended length bytes here.
1199
if (longBufferForDecryption_ == null) //we ddon't need to do this if it's data stream encryption
1200
{
1201                ensureBLayerDataInBuffer(4 + 4);
1202            }
1203            // The ddmScalarLen_ we peek here does not include the LLCP and the extended length bytes
1204
// themselves. So we will add those back to the ddmScalarLen_ so it can be adjusted
1205
// correctly in parseLengthAndMatchCodePoint(). (since the adjustLengths() method will
1206
// subtract the length from ddmScalarLen_)
1207
peekedLength_ =
1208                    ((buffer_[pos_ + 4] & 0xff) << 24) +
1209                    ((buffer_[pos_ + 5] & 0xff) << 16) +
1210                    ((buffer_[pos_ + 6] & 0xff) << 8) +
1211                    ((buffer_[pos_ + 7] & 0xff) << 0);
1212            break;
1213        case 0:
1214            peekedLength_ = -1; // this ddm is streamed, so set -1 -> length unknown
1215
break;
1216        default:
1217            doSyntaxrmSemantics(CodePoint.SYNERRCD_INCORRECT_EXTENDED_LEN);
1218        }
1219    }
1220
1221    final int readFastUnsignedByte() throws DisconnectException {
1222        return (buffer_[pos_++] & 0xff);
1223    }
1224
1225    final short readFastShort() throws DisconnectException {
1226        short s = SignedBinary.getShort(buffer_, pos_);
1227        pos_ += 2;
1228        return s;
1229    }
1230
1231    final int readFastUnsignedShort() throws DisconnectException {
1232        return ((buffer_[pos_++] & 0xff) << 8) +
1233                ((buffer_[pos_++] & 0xff) << 0);
1234    }
1235
1236    final int readFastInt() throws DisconnectException {
1237        int i = SignedBinary.getInt(buffer_, pos_);
1238        pos_ += 4;
1239        return i;
1240    }
1241
1242    final String JavaDoc readFastString(int length) throws DisconnectException {
1243        String JavaDoc result = ccsidManager_.convertToUCS2(buffer_, pos_, length);
1244        pos_ += length;
1245        return result;
1246    }
1247
1248    final byte[] readFastBytes(int length) throws DisconnectException {
1249        byte[] b = new byte[length];
1250        System.arraycopy(buffer_, pos_, b, 0, length);
1251        pos_ += length;
1252        return b;
1253    }
1254
1255    protected final int peekFastLength() throws DisconnectException {
1256        return (((buffer_[pos_] & 0xff) << 8) +
1257                ((buffer_[pos_ + 1] & 0xff) << 0));
1258    }
1259
1260    final void skipFastBytes(int length) throws DisconnectException {
1261        pos_ += length;
1262    }
1263
1264    final void readFastIntArray(int[] array) throws DisconnectException {
1265        for (int i = 0; i < array.length; i++) {
1266            array[i] = SignedBinary.getInt(buffer_, pos_);
1267            pos_ += 4;
1268        }
1269    }
1270
1271    final String JavaDoc readFastString(int length, String JavaDoc encoding) throws DisconnectException {
1272        String JavaDoc s = null;
1273
1274        try {
1275            s = new String JavaDoc(buffer_, pos_, length, encoding);
1276        } catch (java.io.UnsupportedEncodingException JavaDoc e) {
1277            agent_.accumulateChainBreakingReadExceptionAndThrow(
1278                new DisconnectException(agent_,
1279                    new ClientMessageId(SQLState.NET_ENCODING_NOT_SUPPORTED),
1280                    e));
1281        }
1282        pos_ += length;
1283        return s;
1284    }
1285
1286    final byte[] readFastLDBytes() throws DisconnectException {
1287        int len = ((buffer_[pos_++] & 0xff) << 8) + ((buffer_[pos_++] & 0xff) << 0);
1288        if (len == 0) {
1289            return null;
1290        }
1291
1292        byte[] b = new byte[len];
1293        System.arraycopy(buffer_, pos_, b, 0, len);
1294        pos_ += len;
1295        return b;
1296    }
1297
1298    final long readFastLong() throws DisconnectException {
1299        long l = SignedBinary.getLong(buffer_, pos_);
1300        pos_ += 8;
1301        return l;
1302    }
1303
1304    final byte readFastByte() throws DisconnectException {
1305        return (byte) (buffer_[pos_++] & 0xff);
1306    }
1307
1308    final void mark() {
1309        currentPos_ = pos_;
1310    }
1311
1312    // remove and return the top offset value from mark stack.
1313
final int popMark() {
1314        return currentPos_;
1315    }
1316
1317    final int getFastSkipSQLCARDrowLength() {
1318        return pos_ - popMark();
1319    }
1320
1321    // The only difference between this method and the original getData() method is this method
1322
// is not doing an ensureALayerDataInBuffer
1323
final ByteArrayOutputStream JavaDoc getFastData(ByteArrayOutputStream JavaDoc existingBuffer) throws DisconnectException {
1324        boolean readHeader;
1325        int copySize;
1326        ByteArrayOutputStream JavaDoc baos;
1327
1328        // note: an empty baos can yield an allocated and empty byte[]
1329
if (existingBuffer != null) {
1330            baos = existingBuffer;
1331        } else {
1332            if (ddmScalarLen_ != -1) {
1333                // allocate a stream based on a known amount of data
1334
baos = new ByteArrayOutputStream JavaDoc(ddmScalarLen_);
1335            } else {
1336                // allocate a stream to hold an unknown amount of data
1337
baos = new ByteArrayOutputStream JavaDoc();
1338                //isLengthAndNullabilityUnknown = true;
1339
}
1340        }
1341
1342        // set the amount to read for the first segment
1343
copySize = dssLength_; // note: has already been adjusted for headers
1344

1345        do {
1346            // determine if a continuation header needs to be read after the data
1347
if (dssIsContinued_) {
1348                readHeader = true;
1349            } else {
1350                readHeader = false;
1351            }
1352
1353            // read the segment
1354
//ensureALayerDataInBuffer (copySize);
1355
adjustLengths(copySize);
1356            baos.write(buffer_, pos_, copySize);
1357            pos_ += copySize;
1358
1359            // read the continuation header, if necessary
1360
if (readHeader) {
1361                readDSSContinuationHeader();
1362            }
1363
1364            copySize = dssLength_;
1365        } while (readHeader == true);
1366
1367        return baos;
1368    }
1369
1370    // This method is only used to match the codePoint for those class instance variables
1371
// that are embedded in other reply messages.
1372
final protected void matchCodePoint(int expectedCodePoint) throws DisconnectException {
1373        int actualCodePoint = 0;
1374        actualCodePoint = peekedCodePoint_;
1375        pos_ += 4;
1376        if (actualCodePoint != expectedCodePoint) {
1377            agent_.accumulateChainBreakingReadExceptionAndThrow(
1378                new DisconnectException(agent_,
1379                    new ClientMessageId(SQLState.NET_NOT_EXPECTED_CODEPOINT),
1380                    new Integer JavaDoc(actualCodePoint),
1381                    new Integer JavaDoc(expectedCodePoint)));
1382        }
1383    }
1384
1385
1386    protected final int peekNumOfColumns() throws DisconnectException {
1387        // skip the 4-byte LLCP and any extended length bytes + 1-byte null sqlcagrp null indicator
1388
int offset = (4 + peekedNumOfExtendedLenBytes_ + 1);
1389
1390        offset = skipSQLDHROW(offset);
1391
1392        return SignedBinary.getShort(buffer_, pos_ + offset);
1393    }
1394
1395    protected final boolean peekForNullSqlcagrp() {
1396        // skip the 4-byte LLCP and any extended length bytes
1397
int offset = (4 + peekedNumOfExtendedLenBytes_);
1398        int nullInd = buffer_[pos_ + offset] & 0xff;
1399        return (nullInd == CodePoint.NULLDATA);
1400    }
1401
1402    private final int skipSQLDHROW(int offset) throws DisconnectException {
1403        int sqldhrowgrpNullInd = buffer_[pos_ + offset++] & 0xff;
1404        if (sqldhrowgrpNullInd == CodePoint.NULLDATA) {
1405            return offset;
1406        }
1407
1408        offset += 12;
1409
1410        // skip sqldrdbnam
1411
int stringLength = ((buffer_[pos_ + offset++] & 0xff) << 8) +
1412                ((buffer_[pos_ + offset++] & 0xff) << 0);
1413        offset += stringLength;
1414
1415        // skip sqldschema
1416
stringLength = ((buffer_[pos_ + offset++] & 0xff) << 8) +
1417                ((buffer_[pos_ + offset++] & 0xff) << 0);
1418        offset += stringLength;
1419
1420        stringLength = ((buffer_[pos_ + offset++] & 0xff) << 8) +
1421                ((buffer_[pos_ + offset++] & 0xff) << 0);
1422        offset += stringLength;
1423
1424        return offset;
1425    }
1426}
1427
1428
1429
1430
1431
Popular Tags