KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2
3    Derby - Class org.apache.derby.client.net.Request
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 package org.apache.derby.client.net;
22
23 import org.apache.derby.client.am.DisconnectException;
24 import org.apache.derby.client.am.EncryptionManager;
25 import org.apache.derby.client.am.ClientMessageId;
26 import org.apache.derby.client.am.SqlException;
27 import org.apache.derby.client.am.Utils;
28 import org.apache.derby.shared.common.reference.SQLState;
29
30 import java.io.UnsupportedEncodingException JavaDoc;
31
32 public class Request {
33
34     // byte array buffer used for constructing requests.
35
// currently requests are built starting at the beginning of the buffer.
36
protected byte[] bytes_;
37
38     // keeps track of the next position to place a byte in the buffer.
39
// so the last valid byte in the message is at bytes_[offset - 1]
40
protected int offset_;
41
42     // a stack is used to keep track of offsets into the buffer where 2 byte
43
// ddm length values are located. these length bytes will be automatically updated
44
// by this object when construction of a particular object has completed.
45
// right now the max size of the stack is 10. this is an arbitrary number which
46
// should be sufficiently large enough to handle all situations.
47
private final static int MAX_MARKS_NESTING = 10;
48     private int[] markStack_ = new int[MAX_MARKS_NESTING];
49     private int top_ = 0;
50
51     // the ccsid manager for the connection is stored in this object. it will
52
// be used when constructing character ddm data. it will NOT be used for
53
// building any FDOCA data.
54
protected CcsidManager ccsidManager_;
55
56     // This Object tracks the location of the current
57
// Dss header length bytes. This is done so
58
// the length bytes can be automatically
59
// updated as information is added to this stream.
60
private int dssLengthLocation_ = 0;
61
62     // tracks the request correlation ID to use for commands and command objects.
63
// this is automatically updated as commands are built and sent to the server.
64
private int correlationID_ = 0;
65
66     private boolean simpleDssFinalize = false;
67
68     // Used to mask out password when trace is on.
69
protected boolean passwordIncluded_ = false;
70     protected int passwordStart_ = 0;
71     protected int passwordLength_ = 0;
72
73     protected NetAgent netAgent_;
74
75
76     // construct a request object specifying the minimum buffer size
77
// to be used to buffer up the built requests. also specify the ccsid manager
78
// instance to be used when building ddm character data.
79
Request(NetAgent netAgent, int minSize, CcsidManager ccsidManager) {
80         netAgent_ = netAgent;
81         bytes_ = new byte[minSize];
82         ccsidManager_ = ccsidManager;
83         clearBuffer();
84     }
85
86     // construct a request object specifying the ccsid manager instance
87
// to be used when building ddm character data. This will also create
88
// a buffer using the default size (see final static DEFAULT_BUFFER_SIZE value).
89
Request(NetAgent netAgent, CcsidManager ccsidManager, int bufferSize) {
90         //this (netAgent, Request.DEFAULT_BUFFER_SIZE, ccsidManager);
91
this(netAgent, bufferSize, ccsidManager);
92     }
93
94     protected final void clearBuffer() {
95         offset_ = 0;
96         top_ = 0;
97         for (int i = 0; i < markStack_.length; i++) {
98             if (markStack_[i] != 0) {
99                 markStack_[i] = 0;
100             } else {
101                 break;
102             }
103         }
104         dssLengthLocation_ = 0;
105     }
106
107     final void initialize() {
108         clearBuffer();
109         correlationID_ = 0;
110     }
111
112     // set the ccsid manager value. this method allows the ccsid manager to be
113
// changed so a request object can be reused by different connections with
114
// different ccsid managers.
115
final void setCcsidMgr(CcsidManager ccsidManager) {
116         ccsidManager_ = ccsidManager;
117     }
118
119     // ensure length at the end of the buffer for a certain amount of data.
120
// if the buffer does not contain sufficient room for the data, the buffer
121
// will be expanded by the larger of (2 * current size) or (current size + length).
122
// the data from the previous buffer is copied into the larger buffer.
123
protected final void ensureLength(int length) {
124         if (length > bytes_.length) {
125             byte newBytes[] = new byte[Math.max(bytes_.length << 1, length)];
126             System.arraycopy(bytes_, 0, newBytes, 0, offset_);
127             bytes_ = newBytes;
128         }
129     }
130
131     // creates an request dss in the buffer to contain a ddm command
132
// object. calling this method means any previous dss objects in
133
// the buffer are complete and their length and chaining bytes can
134
// be updated appropriately.
135
protected final void createCommand() {
136         buildDss(false, false, false, DssConstants.GDSFMT_RQSDSS, ++correlationID_, false);
137     }
138
139     // creates an request dss in the buffer to contain a ddm command
140
// object. calling this method means any previous dss objects in
141
// the buffer are complete and their length and chaining bytes can
142
// be updated appropriately.
143
protected void createXACommand() {
144         buildDss(false, false, false, DssConstants.GDSFMT_RQSDSS_NOREPLY, ++correlationID_, false);
145     }
146
147     // creates an object dss in the buffer to contain a ddm command
148
// data object. calling this method means any previous dss objects in
149
// the buffer are complete and their length and chaining bytes can
150
// be updated appropriately.
151
final void createCommandData() {
152         buildDss(true,
153                 false,
154                 false,
155                 DssConstants.GDSFMT_OBJDSS,
156                 correlationID_,
157                 false);
158     }
159
160     final void createEncryptedCommandData() {
161         if (netAgent_.netConnection_.getSecurityMechanism() == NetConfiguration.SECMEC_EUSRIDDTA ||
162                 netAgent_.netConnection_.getSecurityMechanism() == NetConfiguration.SECMEC_EUSRPWDDTA) {
163             buildDss(true, false, false, DssConstants.GDSFMT_ENCOBJDSS, correlationID_, false);
164         } else {
165             buildDss(true,
166                     false,
167                     false,
168                     DssConstants.GDSFMT_OBJDSS,
169                     correlationID_,
170                     false);
171         }
172     }
173
174
175     // experimental lob section
176

177     private final void buildDss(boolean dssHasSameCorrelator,
178                                 boolean chainedToNextStructure,
179                                 boolean nextHasSameCorrelator,
180                                 int dssType,
181                                 int corrId,
182                                 boolean simpleFinalizeBuildingNextDss) {
183         if (doesRequestContainData()) {
184             if (simpleDssFinalize) {
185                 finalizeDssLength();
186             } else {
187                 finalizePreviousChainedDss(dssHasSameCorrelator);
188             }
189         }
190
191         ensureLength(offset_ + 6);
192
193         // save the length position and skip
194
// note: the length position is saved so it can be updated
195
// with a different value later.
196
dssLengthLocation_ = offset_;
197         // always turn on chaining flags... this is helpful for lobs...
198
// these bytes will get rest if dss lengths are finalized.
199
bytes_[offset_++] = (byte) 0xFF;
200         bytes_[offset_++] = (byte) 0xFF;
201
202         // insert the manditory 0xD0 and the dssType
203
bytes_[offset_++] = (byte) 0xD0;
204         if (chainedToNextStructure) {
205             dssType |= DssConstants.GDSCHAIN;
206             if (nextHasSameCorrelator) {
207                 dssType |= DssConstants.GDSCHAIN_SAME_ID;
208             }
209         }
210         bytes_[offset_++] = (byte) (dssType & 0xff);
211
212         // write the request correlation id
213
// use method that writes a short
214
bytes_[offset_++] = (byte) ((corrId >>> 8) & 0xff);
215         bytes_[offset_++] = (byte) (corrId & 0xff);
216
217         simpleDssFinalize = simpleFinalizeBuildingNextDss;
218     }
219     
220     
221     final void writeScalarStream(boolean chained,
222                                  boolean chainedWithSameCorrelator,
223                                  int codePoint,
224                                  int length,
225                                  java.io.InputStream JavaDoc in,
226                                  boolean writeNullByte,
227                                  int parameterIndex) throws DisconnectException, SqlException {
228         
229         if (netAgent_.netConnection_.getSecurityMechanism() == NetConfiguration.SECMEC_EUSRIDDTA ||
230             netAgent_.netConnection_.getSecurityMechanism() == NetConfiguration.SECMEC_EUSRPWDDTA) {
231             
232             writeEncryptedScalarStream(chained,
233                                        chainedWithSameCorrelator,
234                                        codePoint,
235                                        length,
236                                        in,
237                                        writeNullByte,
238                                        parameterIndex);
239
240         }else{
241             
242             writePlainScalarStream(chained,
243                                    chainedWithSameCorrelator,
244                                    codePoint,
245                                    length,
246                                    in,
247                                    writeNullByte,
248                                    parameterIndex);
249             
250         }
251
252     }
253
254     // We need to reuse the agent's sql exception accumulation mechanism
255
// for this write exception, pad if the length is too big, and truncation if the length is too small
256
final void writeEncryptedScalarStream(boolean chained,
257                                           boolean chainedWithSameCorrelator,
258                                           int codePoint,
259                                           int length,
260                                           java.io.InputStream JavaDoc in,
261                                           boolean writeNullByte,
262                                           int parameterIndex) throws DisconnectException, SqlException {
263         
264
265             
266         int leftToRead = length;
267         int extendedLengthByteCount = prepScalarStream(chained,
268                                                        chainedWithSameCorrelator,
269                                                        writeNullByte,
270                                                        leftToRead);
271         int bytesToRead;
272
273         if (writeNullByte) {
274             bytesToRead = Utils.min(leftToRead, DssConstants.MAX_DSS_LEN - 6 - 4 - 1 - extendedLengthByteCount);
275         } else {
276             bytesToRead = Utils.min(leftToRead, DssConstants.MAX_DSS_LEN - 6 - 4 - extendedLengthByteCount);
277         }
278             
279         byte[] lengthAndCodepoint;
280         lengthAndCodepoint = buildLengthAndCodePointForEncryptedLob(codePoint,
281                                                                     leftToRead,
282                                                                     writeNullByte,
283                                                                     extendedLengthByteCount);
284
285
286
287         // we need to stream the input, rather than fully materialize it
288
// write the data
289

290         byte[] clearedBytes = new byte[leftToRead];
291         int bytesRead = 0;
292         int totalBytesRead = 0;
293         int pos = 0;
294         do {
295             try {
296                 bytesRead = in.read(clearedBytes, pos, leftToRead);
297                 totalBytesRead += bytesRead;
298             } catch (java.io.IOException JavaDoc e) {
299                 padScalarStreamForError(leftToRead, bytesToRead);
300                 // set with SQLSTATE 01004: The value of a string was truncated when assigned to a host variable.
301
netAgent_.accumulateReadException(new SqlException(netAgent_.logWriter_,
302                                                                    new ClientMessageId(SQLState.NET_IOEXCEPTION_ON_READ),
303                                                                    new Integer JavaDoc(parameterIndex), e.getMessage(), e));
304                 return;
305             }
306             if (bytesRead == -1) {
307                 //padScalarStreamForError(leftToRead, bytesToRead);
308
// set with SQLSTATE 01004: The value of a string was truncated when assigned to a host variable.
309
/*throw new SqlException(netAgent_.logWriter_,
310                   "End of Stream prematurely reached while reading InputStream, parameter #" +
311                   parameterIndex +
312                   ". Remaining data has been padded with 0x0.");*/

313                 //is it OK to do a chain break Exception here. It's not good to
314
//pad it with 0 and encrypt and send it to the server because it takes too much time
315
//can't just throw a SQLException either because some of the data PRPSQLSTT etc have already
316
//been sent to the server, and server is waiting for EXTDTA, server hangs for this.
317
netAgent_.accumulateChainBreakingReadExceptionAndThrow(
318                                                                        new DisconnectException(netAgent_,
319                                                                                                new ClientMessageId(SQLState.NET_PREMATURE_EOS_DISCONNECT),
320                                                                                                new Integer JavaDoc(parameterIndex)));
321                 return;
322
323                 /*netAgent_.accumulateReadException(
324                   new SqlException(netAgent_.logWriter_,
325                   "End of Stream prematurely reached while reading InputStream, parameter #" +
326                   parameterIndex +
327                   ". Remaining data has been padded with 0x0."));
328                   return;*/

329             } else {
330                 pos += bytesRead;
331                 //offset_ += bytesRead; //comment this out for data stream encryption.
332
leftToRead -= bytesRead;
333             }
334
335         } while (leftToRead > 0);
336
337         // check to make sure that the specified length wasn't too small
338
try {
339             if (in.read() != -1) {
340                 // set with SQLSTATE 01004: The value of a string was truncated when assigned to a host variable.
341
netAgent_.accumulateReadException(new SqlException(
342                                                                    netAgent_.logWriter_,
343                                                                    new ClientMessageId(SQLState.NET_INPUTSTREAM_LENGTH_TOO_SMALL),
344                                                                    new Integer JavaDoc(parameterIndex)));
345             }
346         } catch (java.io.IOException JavaDoc e) {
347             netAgent_.accumulateReadException(new SqlException(
348                                                                netAgent_.logWriter_,
349                                                                new ClientMessageId(
350                                                                                    SQLState.NET_IOEXCEPTION_ON_STREAMLEN_VERIFICATION),
351                                                                new Integer JavaDoc(parameterIndex),
352                                                                e.getMessage(),
353                                                                e));
354         }
355
356         byte[] newClearedBytes = new byte[clearedBytes.length +
357                                           lengthAndCodepoint.length];
358         System.arraycopy(lengthAndCodepoint, 0, newClearedBytes, 0,
359                          lengthAndCodepoint.length);
360         System.arraycopy(clearedBytes, 0, newClearedBytes, lengthAndCodepoint.length, clearedBytes.length);
361         //it's wrong here, need to add in the real length after the codepoing 146c
362
byte[] encryptedBytes;
363         encryptedBytes = netAgent_.netConnection_.getEncryptionManager().
364             encryptData(newClearedBytes,
365                         NetConfiguration.SECMEC_EUSRIDPWD,
366                         netAgent_.netConnection_.getTargetPublicKey(),
367                         netAgent_.netConnection_.getTargetPublicKey());
368
369         int encryptedBytesLength = encryptedBytes.length;
370         int sendingLength = bytes_.length - offset_;
371         if (encryptedBytesLength > (bytes_.length - offset_)) {
372
373             System.arraycopy(encryptedBytes, 0, bytes_, offset_, (bytes_.length - offset_));
374             offset_ = 32767;
375             try {
376                 sendBytes(netAgent_.getOutputStream());
377             } catch (java.io.IOException JavaDoc ioe) {
378                 netAgent_.throwCommunicationsFailure(ioe);
379             }
380         } else {
381             System.arraycopy(encryptedBytes, 0, bytes_, offset_, encryptedBytesLength);
382             offset_ = offset_ + encryptedBytes.length;
383         }
384
385         encryptedBytesLength = encryptedBytesLength - sendingLength;
386         while (encryptedBytesLength > 0) {
387             //dssLengthLocation_ = offset_;
388
offset_ = 0;
389
390             if ((encryptedBytesLength - 32765) > 0) {
391                 bytes_[offset_++] = (byte) (0xff);
392                 bytes_[offset_++] = (byte) (0xff);
393                 System.arraycopy(encryptedBytes, sendingLength, bytes_, offset_, 32765);
394                 encryptedBytesLength -= 32765;
395                 sendingLength += 32765;
396                 offset_ = 32767;
397                 try {
398                     sendBytes(netAgent_.getOutputStream());
399                 } catch (java.io.IOException JavaDoc ioe) {
400                     netAgent_.throwCommunicationsFailure(ioe);
401                 }
402             } else {
403                 int leftlength = encryptedBytesLength + 2;
404                 bytes_[offset_++] = (byte) ((leftlength >>> 8) & 0xff);
405                 bytes_[offset_++] = (byte) (leftlength & 0xff);
406
407                 System.arraycopy(encryptedBytes, sendingLength, bytes_, offset_, encryptedBytesLength);
408
409                 offset_ += encryptedBytesLength;
410                 dssLengthLocation_ = offset_;
411                 encryptedBytesLength = 0;
412             }
413
414         }
415     }
416     
417     
418     // We need to reuse the agent's sql exception accumulation mechanism
419
// for this write exception, pad if the length is too big, and truncation if the length is too small
420
final void writePlainScalarStream(boolean chained,
421                                       boolean chainedWithSameCorrelator,
422                                       int codePoint,
423                                       int length,
424                                       java.io.InputStream JavaDoc in,
425                                       boolean writeNullByte,
426                                       int parameterIndex) throws DisconnectException, SqlException {
427         int leftToRead = length;
428         int extendedLengthByteCount = prepScalarStream(chained,
429                                                        chainedWithSameCorrelator,
430                                                        writeNullByte,
431                                                        leftToRead);
432         int bytesToRead;
433                 
434         if (writeNullByte) {
435             bytesToRead = Utils.min(leftToRead, DssConstants.MAX_DSS_LEN - 6 - 4 - 1 - extendedLengthByteCount);
436         } else {
437             bytesToRead = Utils.min(leftToRead, DssConstants.MAX_DSS_LEN - 6 - 4 - extendedLengthByteCount);
438         }
439                 
440         buildLengthAndCodePointForLob(codePoint,
441                                       leftToRead,
442                                       writeNullByte,
443                                       extendedLengthByteCount);
444
445         int bytesRead = 0;
446         int totalBytesRead = 0;
447         do {
448             do {
449                 try {
450                     bytesRead = in.read(bytes_, offset_, bytesToRead);
451                     totalBytesRead += bytesRead;
452                 } catch (java.io.IOException JavaDoc e) {
453                     padScalarStreamForError(leftToRead, bytesToRead);
454                     // set with SQLSTATE 01004: The value of a string was truncated when assigned to a host variable.
455
netAgent_.accumulateReadException(new SqlException(
456                                                                        netAgent_.logWriter_,
457                                                                        new ClientMessageId(SQLState.NET_IOEXCEPTION_ON_READ),
458                                                                        new Integer JavaDoc(parameterIndex),
459                                                                        e.getMessage(),
460                                                                        e));
461
462                     return;
463                 }
464                 if (bytesRead == -1) {
465                     padScalarStreamForError(leftToRead, bytesToRead);
466                     // set with SQLSTATE 01004: The value of a string was truncated when assigned to a host variable.
467
netAgent_.accumulateReadException(new SqlException(netAgent_.logWriter_,
468                                                                        new ClientMessageId(SQLState.NET_PREMATURE_EOS),
469                                                                        new Integer JavaDoc(parameterIndex)));
470                     return;
471                 } else {
472                     bytesToRead -= bytesRead;
473                     offset_ += bytesRead;
474                     leftToRead -= bytesRead;
475                 }
476             } while (bytesToRead > 0);
477
478             bytesToRead = flushScalarStreamSegment(leftToRead, bytesToRead);
479         } while (leftToRead > 0);
480
481         // check to make sure that the specified length wasn't too small
482
try {
483             if (in.read() != -1) {
484                 // set with SQLSTATE 01004: The value of a string was truncated when assigned to a host variable.
485
netAgent_.accumulateReadException(new SqlException(netAgent_.logWriter_,
486                                                                    new ClientMessageId(SQLState.NET_INPUTSTREAM_LENGTH_TOO_SMALL),
487                                                                    new Integer JavaDoc(parameterIndex)));
488             }
489         } catch (java.io.IOException JavaDoc e) {
490             netAgent_.accumulateReadException(new SqlException(
491                                                                netAgent_.logWriter_,
492                                                                new ClientMessageId(
493                                                                                    SQLState.NET_IOEXCEPTION_ON_STREAMLEN_VERIFICATION),
494                                                                new Integer JavaDoc(parameterIndex),
495                                                                e.getMessage(),
496                                                                e));
497         }
498     }
499
500
501     // Throw DataTruncation, instead of closing connection if input size mismatches
502
// An implication of this, is that we need to extend the chaining model
503
// for writes to accomodate chained write exceptoins
504
final void writeScalarStream(boolean chained,
505                                  boolean chainedWithSameCorrelator,
506                                  int codePoint,
507                                  int length,
508                                  java.io.Reader JavaDoc r,
509                                  boolean writeNullByte,
510                                  int parameterIndex) throws DisconnectException,
511                                                             SqlException{
512         
513         writeScalarStream(chained,
514                           chainedWithSameCorrelator,
515                           codePoint,
516                           length * 2,
517                           EncodedInputStream.createUTF16BEStream(r),
518                           writeNullByte,
519                           parameterIndex);
520     }
521
522
523     // prepScalarStream does the following prep for writing stream data:
524
// 1. Flushes an existing DSS segment, if necessary
525
// 2. Determines if extended length bytes are needed
526
// 3. Creates a new DSS/DDM header and a null byte indicator, if applicable
527
protected final int prepScalarStream(boolean chained,
528                                          boolean chainedWithSameCorrelator,
529                                          boolean writeNullByte,
530                                          int leftToRead) throws DisconnectException {
531         int extendedLengthByteCount;
532
533         int nullIndicatorSize = 0;
534         if (writeNullByte) {
535             // leftToRead is cast to (long) on the off chance that +4+1 pushes it outside the range of int
536
extendedLengthByteCount = calculateExtendedLengthByteCount((long) leftToRead + 4 + 1);
537             nullIndicatorSize = 1;
538         } else {
539             extendedLengthByteCount = calculateExtendedLengthByteCount(leftToRead + 4);
540         }
541
542         // flush the existing DSS segment if this stream will not fit in the send buffer
543
// leftToRead is cast to (long) on the off chance that +4+1 pushes it outside the range of int
544
if (10 + extendedLengthByteCount + nullIndicatorSize + (long) leftToRead + offset_ > DssConstants.MAX_DSS_LEN) {
545             try {
546                 if (simpleDssFinalize) {
547                     finalizeDssLength();
548                 } else {
549                     finalizePreviousChainedDss(true);
550                 }
551                 sendBytes(netAgent_.getOutputStream());
552             } catch (java.io.IOException JavaDoc e) {
553                 netAgent_.throwCommunicationsFailure(e);
554             }
555         }
556
557         if (netAgent_.netConnection_.getSecurityMechanism() == NetConfiguration.SECMEC_EUSRIDDTA ||
558                 netAgent_.netConnection_.getSecurityMechanism() == NetConfiguration.SECMEC_EUSRPWDDTA) {
559             buildDss(true,
560                     chained,
561                     chainedWithSameCorrelator,
562                     DssConstants.GDSFMT_ENCOBJDSS,
563                     correlationID_,
564                     true);
565         } else
566         // buildDss should not call ensure length.
567
{
568             buildDss(true,
569                     chained,
570                     chainedWithSameCorrelator,
571                     DssConstants.GDSFMT_OBJDSS,
572                     correlationID_,
573                     true);
574         }
575
576         return extendedLengthByteCount;
577     }
578
579
580     // Writes out a scalar stream DSS segment, along with DSS continuation headers,
581
// if necessary.
582
protected final int flushScalarStreamSegment(int leftToRead,
583                                                  int bytesToRead) throws DisconnectException {
584         int newBytesToRead = bytesToRead;
585
586         // either at end of data, end of dss segment, or both.
587
if (leftToRead != 0) {
588             // 32k segment filled and not at end of data.
589
if ((Utils.min(2 + leftToRead, 32767)) > (bytes_.length - offset_)) {
590                 try {
591                     sendBytes(netAgent_.getOutputStream());
592                 } catch (java.io.IOException JavaDoc ioe) {
593                     netAgent_.throwCommunicationsFailure(ioe);
594                 }
595             }
596             dssLengthLocation_ = offset_;
597             bytes_[offset_++] = (byte) (0xff);
598             bytes_[offset_++] = (byte) (0xff);
599             newBytesToRead = Utils.min(leftToRead, 32765);
600         }
601
602         return newBytesToRead;
603     }
604
605     // the offset_ must not be updated when an error is encountered
606
// note valid data may be overwritten
607
protected final void padScalarStreamForError(int leftToRead, int bytesToRead) throws DisconnectException {
608         do {
609             do {
610                 bytes_[offset_++] = (byte) (0x0); // use 0x0 as the padding byte
611
bytesToRead--;
612                 leftToRead--;
613             } while (bytesToRead > 0);
614
615             bytesToRead = flushScalarStreamSegment(leftToRead, bytesToRead);
616         } while (leftToRead > 0);
617     }
618
619     private final void writeExtendedLengthBytes(int extendedLengthByteCount, long length) {
620         int shiftSize = (extendedLengthByteCount - 1) * 8;
621         for (int i = 0; i < extendedLengthByteCount; i++) {
622             bytes_[offset_++] = (byte) ((length >>> shiftSize) & 0xff);
623             shiftSize -= 8;
624         }
625     }
626
627     private final byte[] writeExtendedLengthBytesForEncryption(int extendedLengthByteCount, long length) {
628         int shiftSize = (extendedLengthByteCount - 1) * 8;
629         byte[] extendedLengthBytes = new byte[extendedLengthByteCount];
630         for (int i = 0; i < extendedLengthByteCount; i++) {
631             extendedLengthBytes[i] = (byte) ((length >>> shiftSize) & 0xff);
632             shiftSize -= 8;
633         }
634         return extendedLengthBytes;
635     }
636
637     // experimental lob section - end
638

639     // used to finialize a dss which is already in the buffer
640
// before another dss is built. this includes updating length
641
// bytes and chaining bits.
642
protected final void finalizePreviousChainedDss(boolean dssHasSameCorrelator) {
643         finalizeDssLength();
644         bytes_[dssLengthLocation_ + 3] |= 0x40;
645         if (dssHasSameCorrelator) // for blobs
646
{
647             bytes_[dssLengthLocation_ + 3] |= 0x10;
648         }
649     }
650
651     // method to determine if any data is in the request.
652
// this indicates there is a dss object already in the buffer.
653
protected final boolean doesRequestContainData() {
654         return offset_ != 0;
655     }
656
657     // signal the completion of a Dss Layer A object. The length of
658
// dss object will be calculated based on the difference between the
659
// start of the dss, saved on the beginDss call, and the current
660
// offset into the buffer which marks the end of the data. In the event
661
// the length requires the use of continuation Dss headers, one for each 32k
662
// chunk of data, the data will be shifted and the continuation headers
663
// will be inserted with the correct values as needed.
664
// Note: In the future, we may try to optimize this approach
665
// in an attempt to avoid these shifts.
666
protected final void finalizeDssLength() {
667         // calculate the total size of the dss and the number of bytes which would
668
// require continuation dss headers. The total length already includes the
669
// the 6 byte dss header located at the beginning of the dss. It does not
670
// include the length of any continuation headers.
671
int totalSize = offset_ - dssLengthLocation_;
672         int bytesRequiringContDssHeader = totalSize - 32767;
673
674         // determine if continuation headers are needed
675
if (bytesRequiringContDssHeader > 0) {
676
677             // the continuation headers are needed, so calculate how many.
678
// after the first 32767 worth of data, a continuation header is
679
// needed for every 32765 bytes (32765 bytes of data + 2 bytes of
680
// continuation header = 32767 Dss Max Size).
681
int contDssHeaderCount = bytesRequiringContDssHeader / 32765;
682             if (bytesRequiringContDssHeader % 32765 != 0) {
683                 contDssHeaderCount++;
684             }
685
686             // right now the code will shift to the right. In the future we may want
687
// to try something fancier to help reduce the copying (maybe keep
688
// space in the beginning of the buffer??).
689
// the offset points to the next available offset in the buffer to place
690
// a piece of data, so the last dataByte is at offset -1.
691
// various bytes will need to be shifted by different amounts
692
// depending on how many dss headers to insert so the amount to shift
693
// will be calculated and adjusted as needed. ensure there is enough room
694
// for all the conutinuation headers and adjust the offset to point to the
695
// new end of the data.
696
int dataByte = offset_ - 1;
697             int shiftOffset = contDssHeaderCount * 2;
698             ensureLength(offset_ + shiftOffset);
699             offset_ += shiftOffset;
700
701             // mark passOne to help with calculating the length of the final (first or
702
// rightmost) continuation header.
703
boolean passOne = true;
704             do {
705                 // calculate chunk of data to shift
706
int dataToShift = bytesRequiringContDssHeader % 32765;
707                 if (dataToShift == 0) {
708                     dataToShift = 32765;
709                 }
710
711                 // perform the shift
712
dataByte -= dataToShift;
713                 System.arraycopy(bytes_, dataByte + 1,bytes_, dataByte + shiftOffset + 1, dataToShift);
714
715                 // calculate the value the value of the 2 byte continuation dss header which
716
// includes the length of itself. On the first pass, if the length is 32767
717
// we do not want to set the continuation dss header flag.
718
int twoByteContDssHeader = dataToShift + 2;
719                 if (passOne) {
720                     passOne = false;
721                 } else {
722                     if (twoByteContDssHeader == 32767) {
723                         twoByteContDssHeader = 0xFFFF;
724                     }
725                 }
726
727                 // insert the header's length bytes
728
bytes_[dataByte + shiftOffset - 1] = (byte) ((twoByteContDssHeader >>> 8) & 0xff);
729                 bytes_[dataByte + shiftOffset] = (byte) (twoByteContDssHeader & 0xff);
730
731                 // adjust the bytesRequiringContDssHeader and the amount to shift for
732
// data in upstream headers.
733
bytesRequiringContDssHeader -= dataToShift;
734                 shiftOffset -= 2;
735
736                 // shift and insert another header for more data.
737
} while (bytesRequiringContDssHeader > 0);
738
739             // set the continuation dss header flag on for the first header
740
totalSize = 0xFFFF;
741
742         }
743
744         // insert the length bytes in the 6 byte dss header.
745
bytes_[dssLengthLocation_] = (byte) ((totalSize >>> 8) & 0xff);
746         bytes_[dssLengthLocation_ + 1] = (byte) (totalSize & 0xff);
747     }
748
749     // mark the location of a two byte ddm length field in the buffer,
750
// skip the length bytes for later update, and insert a ddm codepoint
751
// into the buffer. The value of the codepoint is not checked.
752
// this length will be automatically updated when construction of
753
// the ddm object is complete (see updateLengthBytes method).
754
// Note: this mechanism handles extended length ddms.
755
protected final void markLengthBytes(int codePoint) {
756         ensureLength(offset_ + 4);
757
758         // save the location of length bytes in the mark stack.
759
mark();
760
761         // skip the length bytes and insert the codepoint
762
offset_ += 2;
763         bytes_[offset_++] = (byte) ((codePoint >>> 8) & 0xff);
764         bytes_[offset_++] = (byte) (codePoint & 0xff);
765     }
766
767     // mark an offest into the buffer by placing the current offset value on
768
// a stack.
769
private final void mark() {
770         markStack_[top_++] = offset_;
771     }
772
773     // remove and return the top offset value from mark stack.
774
private final int popMark() {
775         return markStack_[--top_];
776     }
777
778     protected final void markForCachingPKGNAMCSN() {
779         mark();
780     }
781
782     protected final int popMarkForCachingPKGNAMCSN() {
783         return popMark();
784     }
785
786     // Called to update the last ddm length bytes marked (lengths are updated
787
// in the reverse order that they are marked). It is up to the caller
788
// to make sure length bytes were marked before calling this method.
789
// If the length requires ddm extended length bytes, the data will be
790
// shifted as needed and the extended length bytes will be automatically
791
// inserted.
792
protected final void updateLengthBytes() throws SqlException {
793         // remove the top length location offset from the mark stack\
794
// calculate the length based on the marked location and end of data.
795
int lengthLocation = popMark();
796         int length = offset_ - lengthLocation;
797
798         // determine if any extended length bytes are needed. the value returned
799
// from calculateExtendedLengthByteCount is the number of extended length
800
// bytes required. 0 indicates no exteneded length.
801
int extendedLengthByteCount = calculateExtendedLengthByteCount(length);
802         if (extendedLengthByteCount != 0) {
803
804             // ensure there is enough room in the buffer for the extended length bytes.
805
ensureLength(offset_ + extendedLengthByteCount);
806
807             // calculate the length to be placed in the extended length bytes.
808
// this length does not include the 4 byte llcp.
809
int extendedLength = length - 4;
810
811             // shift the data to the right by the number of extended length bytes needed.
812
int extendedLengthLocation = lengthLocation + 4;
813             System.arraycopy(bytes_,
814                     extendedLengthLocation,
815                     bytes_,
816                     extendedLengthLocation + extendedLengthByteCount,
817                     extendedLength);
818
819             // write the extended length
820
int shiftSize = (extendedLengthByteCount - 1) * 8;
821             for (int i = 0; i < extendedLengthByteCount; i++) {
822                 bytes_[extendedLengthLocation++] = (byte) ((extendedLength >>> shiftSize) & 0xff);
823                 shiftSize -= 8;
824             }
825             // adjust the offset to account for the shift and insert
826
offset_ += extendedLengthByteCount;
827
828             // the two byte length field before the codepoint contains the length
829
// of itself, the length of the codepoint, and the number of bytes used
830
// to hold the extended length. the 2 byte length field also has the first
831
// bit on to indicate extended length bytes were used.
832
length = extendedLengthByteCount + 4;
833             length |= 0x8000;
834         }
835
836         // write the 2 byte length field (2 bytes before codepoint).
837
bytes_[lengthLocation] = (byte) ((length >>> 8) & 0xff);
838         bytes_[lengthLocation + 1] = (byte) (length & 0xff);
839     }
840
841     // helper method to calculate the minimum number of extended length bytes needed
842
// for a ddm. a return value of 0 indicates no extended length needed.
843
private final int calculateExtendedLengthByteCount(long ddmSize) //throws SqlException
844
{
845         // according to Jim and some tests perfomred on Lob data,
846
// the extended length bytes are signed. Assume that
847
// if this is the case for Lobs, it is the case for
848
// all extended length scenarios.
849
if (ddmSize <= 0x7FFF) {
850             return 0;
851         } else if (ddmSize <= 0x7FFFFFFFL) {
852             return 4;
853         } else if (ddmSize <= 0x7FFFFFFFFFFFL) {
854             return 6;
855         } else {
856             return 8;
857         }
858     }
859
860     // insert the padByte into the buffer by length number of times.
861
final void padBytes(byte padByte, int length) {
862         ensureLength(offset_ + length);
863         for (int i = 0; i < length; i++) {
864             bytes_[offset_++] = padByte;
865         }
866     }
867
868     // insert an unsigned single byte value into the buffer.
869
final void write1Byte(int value) {
870         ensureLength(offset_ + 1);
871         bytes_[offset_++] = (byte) (value & 0xff);
872     }
873
874     // insert 3 unsigned bytes into the buffer. this was
875
// moved up from NetStatementRequest for performance
876
final void buildTripletHeader(int tripletLength,
877                                   int tripletType,
878                                   int tripletId) {
879         ensureLength(offset_ + 3);
880         bytes_[offset_++] = (byte) (tripletLength & 0xff);
881         bytes_[offset_++] = (byte) (tripletType & 0xff);
882         bytes_[offset_++] = (byte) (tripletId & 0xff);
883     }
884
885     final void writeLidAndLengths(int[][] lidAndLengthOverrides, int count, int offset) {
886         ensureLength(offset_ + (count * 3));
887         for (int i = 0; i < count; i++, offset++) {
888             bytes_[offset_++] = (byte) (lidAndLengthOverrides[offset][0] & 0xff);
889             bytes_[offset_++] = (byte) ((lidAndLengthOverrides[offset][1] >>> 8) & 0xff);
890             bytes_[offset_++] = (byte) (lidAndLengthOverrides[offset][1] & 0xff);
891         }
892     }
893
894     // if mdd overrides are not required, lids and lengths are copied straight into the
895
// buffer.
896
// otherwise, lookup the protocolType in the map. if an entry exists, substitute the
897
// protocolType with the corresponding override lid.
898
final void writeLidAndLengths(int[][] lidAndLengthOverrides,
899                                   int count,
900                                   int offset,
901                                   boolean mddRequired,
902                                   java.util.Hashtable JavaDoc map) {
903         if (!mddRequired) {
904             writeLidAndLengths(lidAndLengthOverrides, count, offset);
905         }
906         // if mdd overrides are required, lookup the protocolType in the map, and substitute
907
// the protocolType with the override lid.
908
else {
909             ensureLength(offset_ + (count * 3));
910             int protocolType, overrideLid;
911             Object JavaDoc entry;
912             for (int i = 0; i < count; i++, offset++) {
913                 protocolType = lidAndLengthOverrides[offset][0];
914                 // lookup the protocolType in the protocolType->overrideLid map
915
// if an entry exists, replace the protocolType with the overrideLid
916
entry = map.get(new Integer JavaDoc(protocolType));
917                 overrideLid = (entry == null) ? protocolType : ((Integer JavaDoc) entry).intValue();
918                 bytes_[offset_++] = (byte) (overrideLid & 0xff);
919                 bytes_[offset_++] = (byte) ((lidAndLengthOverrides[offset][1] >>> 8) & 0xff);
920                 bytes_[offset_++] = (byte) (lidAndLengthOverrides[offset][1] & 0xff);
921             }
922         }
923     }
924
925 // perf end
926

927     // insert a big endian unsigned 2 byte value into the buffer.
928
final void write2Bytes(int value) {
929         ensureLength(offset_ + 2);
930         bytes_[offset_++] = (byte) ((value >>> 8) & 0xff);
931         bytes_[offset_++] = (byte) (value & 0xff);
932     }
933
934     // insert a big endian unsigned 4 byte value into the buffer.
935
final void write4Bytes(long value) {
936         ensureLength(offset_ + 4);
937         bytes_[offset_++] = (byte) ((value >>> 24) & 0xff);
938         bytes_[offset_++] = (byte) ((value >>> 16) & 0xff);
939         bytes_[offset_++] = (byte) ((value >>> 8) & 0xff);
940         bytes_[offset_++] = (byte) (value & 0xff);
941     }
942
943     // copy length number of bytes starting at offset 0 of the byte array, buf,
944
// into the buffer. it is up to the caller to make sure buf has at least length
945
// number of elements. no checking will be done by this method.
946
final void writeBytes(byte[] buf, int length) {
947         ensureLength(offset_ + length);
948         System.arraycopy(buf, 0, bytes_, offset_, length);
949         offset_ += length;
950     }
951
952     final void writeBytes(byte[] buf) {
953         ensureLength(offset_ + buf.length);
954         System.arraycopy(buf, 0, bytes_, offset_, buf.length);
955         offset_ += buf.length;
956     }
957
958     // insert a pair of unsigned 2 byte values into the buffer.
959
final void writeCodePoint4Bytes(int codePoint, int value) { // should this be writeCodePoint2Bytes
960
ensureLength(offset_ + 4);
961         bytes_[offset_++] = (byte) ((codePoint >>> 8) & 0xff);
962         bytes_[offset_++] = (byte) (codePoint & 0xff);
963         bytes_[offset_++] = (byte) ((value >>> 8) & 0xff);
964         bytes_[offset_++] = (byte) (value & 0xff);
965     }
966
967     // insert a 4 byte length/codepoint pair and a 1 byte unsigned value into the buffer.
968
// total of 5 bytes inserted in buffer.
969
protected final void writeScalar1Byte(int codePoint, int value) {
970         ensureLength(offset_ + 5);
971         bytes_[offset_++] = 0x00;
972         bytes_[offset_++] = 0x05;
973         bytes_[offset_++] = (byte) ((codePoint >>> 8) & 0xff);
974         bytes_[offset_++] = (byte) (codePoint & 0xff);
975         bytes_[offset_++] = (byte) (value & 0xff);
976     }
977
978     // insert a 4 byte length/codepoint pair and a 2 byte unsigned value into the buffer.
979
// total of 6 bytes inserted in buffer.
980
final void writeScalar2Bytes(int codePoint, int value) {
981         ensureLength(offset_ + 6);
982         bytes_[offset_++] = 0x00;
983         bytes_[offset_++] = 0x06;
984         bytes_[offset_++] = (byte) ((codePoint >>> 8) & 0xff);
985         bytes_[offset_++] = (byte) (codePoint & 0xff);
986         bytes_[offset_++] = (byte) ((value >>> 8) & 0xff);
987         bytes_[offset_++] = (byte) (value & 0xff);
988     }
989
990     // insert a 4 byte length/codepoint pair and a 4 byte unsigned value into the
991
// buffer. total of 8 bytes inserted in the buffer.
992
protected final void writeScalar4Bytes(int codePoint, long value) {
993         ensureLength(offset_ + 8);
994         bytes_[offset_++] = 0x00;
995         bytes_[offset_++] = 0x08;
996         bytes_[offset_++] = (byte) ((codePoint >>> 8) & 0xff);
997         bytes_[offset_++] = (byte) (codePoint & 0xff);
998         bytes_[offset_++] = (byte) ((value >>> 24) & 0xff);
999         bytes_[offset_++] = (byte) ((value >>> 16) & 0xff);
1000        bytes_[offset_++] = (byte) ((value >>> 8) & 0xff);
1001        bytes_[offset_++] = (byte) (value & 0xff);
1002    }
1003
1004    // insert a 4 byte length/codepoint pair and a 8 byte unsigned value into the
1005
// buffer. total of 12 bytes inserted in the buffer.
1006
final void writeScalar8Bytes(int codePoint, long value) {
1007        ensureLength(offset_ + 12);
1008        bytes_[offset_++] = 0x00;
1009        bytes_[offset_++] = 0x0C;
1010        bytes_[offset_++] = (byte) ((codePoint >>> 8) & 0xff);
1011        bytes_[offset_++] = (byte) (codePoint & 0xff);
1012        bytes_[offset_++] = (byte) ((value >>> 56) & 0xff);
1013        bytes_[offset_++] = (byte) ((value >>> 48) & 0xff);
1014        bytes_[offset_++] = (byte) ((value >>> 40) & 0xff);
1015        bytes_[offset_++] = (byte) ((value >>> 32) & 0xff);
1016        bytes_[offset_++] = (byte) ((value >>> 24) & 0xff);
1017        bytes_[offset_++] = (byte) ((value >>> 16) & 0xff);
1018        bytes_[offset_++] = (byte) ((value >>> 8) & 0xff);
1019        bytes_[offset_++] = (byte) (value & 0xff);
1020    }
1021
1022    // insert a 4 byte length/codepoint pair into the buffer.
1023
// total of 4 bytes inserted in buffer.
1024
// Note: the length value inserted in the buffer is the same as the value
1025
// passed in as an argument (this value is NOT incremented by 4 before being
1026
// inserted).
1027
final void writeLengthCodePoint(int length, int codePoint) {
1028        ensureLength(offset_ + 4);
1029        bytes_[offset_++] = (byte) ((length >>> 8) & 0xff);
1030        bytes_[offset_++] = (byte) (length & 0xff);
1031        bytes_[offset_++] = (byte) ((codePoint >>> 8) & 0xff);
1032        bytes_[offset_++] = (byte) (codePoint & 0xff);
1033    }
1034
1035    final byte[] writeEXTDTALengthCodePointForEncryption(int length, int codePoint) {
1036        //how to encure length and offset later?
1037
byte[] clearedBytes = new byte[4];
1038        clearedBytes[0] = (byte) ((length >>> 8) & 0xff);
1039        clearedBytes[1] = (byte) (length & 0xff);
1040        clearedBytes[2] = (byte) ((codePoint >>> 8) & 0xff);
1041        clearedBytes[3] = (byte) (codePoint & 0xff);
1042        return clearedBytes;
1043    }
1044
1045    // insert a 4 byte length/codepoint pair into the buffer followed
1046
// by length number of bytes copied from array buf starting at offset 0.
1047
// the length of this scalar must not exceed the max for the two byte length
1048
// field. This method does not support extended length. The length
1049
// value inserted in the buffer includes the number of bytes to copy plus
1050
// the size of the llcp (or length + 4). It is up to the caller to make sure
1051
// the array, buf, contains at least length number of bytes.
1052
final void writeScalarBytes(int codePoint, byte[] buf, int length) {
1053        ensureLength(offset_ + length + 4);
1054        bytes_[offset_++] = (byte) (((length + 4) >>> 8) & 0xff);
1055        bytes_[offset_++] = (byte) ((length + 4) & 0xff);
1056        bytes_[offset_++] = (byte) ((codePoint >>> 8) & 0xff);
1057        bytes_[offset_++] = (byte) (codePoint & 0xff);
1058        for (int i = 0; i < length; i++) {
1059            bytes_[offset_++] = buf[i];
1060        }
1061    }
1062
1063    // insert a 4 byte length/codepoint pair into the buffer.
1064
// total of 4 bytes inserted in buffer.
1065
// Note: datalength will be incremented by the size of the llcp, 4,
1066
// before being inserted.
1067
final void writeScalarHeader(int codePoint, int dataLength) {
1068        ensureLength(offset_ + dataLength + 4);
1069        bytes_[offset_++] = (byte) (((dataLength + 4) >>> 8) & 0xff);
1070        bytes_[offset_++] = (byte) ((dataLength + 4) & 0xff);
1071        bytes_[offset_++] = (byte) ((codePoint >>> 8) & 0xff);
1072        bytes_[offset_++] = (byte) (codePoint & 0xff);
1073    }
1074
1075    // insert a 4 byte length/codepoint pair plus ddm character data into
1076
// the buffer. This method assumes that the String argument can be
1077
// converted by the ccsid manager. This should be fine because usually
1078
// there are restrictions on the characters which can be used for ddm
1079
// character data. This method also assumes that the string.length() will
1080
// be the number of bytes following the conversion.
1081
// The two byte length field will contain the length of the character data
1082
// and the length of the 4 byte llcp. This method does not handle
1083
// scenarios which require extended length bytes.
1084
final void writeScalarString(int codePoint, String JavaDoc string) throws SqlException {
1085        int stringLength = string.length();
1086        ensureLength(offset_ + stringLength + 4);
1087        bytes_[offset_++] = (byte) (((stringLength + 4) >>> 8) & 0xff);
1088        bytes_[offset_++] = (byte) ((stringLength + 4) & 0xff);
1089        bytes_[offset_++] = (byte) ((codePoint >>> 8) & 0xff);
1090        bytes_[offset_++] = (byte) (codePoint & 0xff);
1091        offset_ = ccsidManager_.convertFromUCS2(string, bytes_, offset_, netAgent_);
1092    }
1093
1094    // insert a 4 byte length/codepoint pair plus ddm character data into the
1095
// buffer. The ddm character data is padded if needed with the ccsid manager's
1096
// space character if the length of the character data is less than paddedLength.
1097
// Note: this method is not to be used for String truncation and the string length
1098
// must be <= paddedLength.
1099
// This method assumes that the String argument can be
1100
// converted by the ccsid manager. This should be fine because usually
1101
// there are restrictions on the characters which can be used for ddm
1102
// character data. This method also assumes that the string.length() will
1103
// be the number of bytes following the conversion. The two byte length field
1104
// of the llcp will contain the length of the character data including the pad
1105
// and the length of the llcp or 4. This method will not handle extended length
1106
// scenarios.
1107
final void writeScalarPaddedString(int codePoint, String JavaDoc string, int paddedLength) throws SqlException {
1108        int stringLength = string.length();
1109        ensureLength(offset_ + paddedLength + 4);
1110        bytes_[offset_++] = (byte) (((paddedLength + 4) >>> 8) & 0xff);
1111        bytes_[offset_++] = (byte) ((paddedLength + 4) & 0xff);
1112        bytes_[offset_++] = (byte) ((codePoint >>> 8) & 0xff);
1113        bytes_[offset_++] = (byte) (codePoint & 0xff);
1114        offset_ = ccsidManager_.convertFromUCS2(string, bytes_, offset_, netAgent_);
1115        for (int i = 0; i < paddedLength - stringLength; i++) {
1116            bytes_[offset_++] = ccsidManager_.space_;
1117        }
1118    }
1119
1120    // this method inserts ddm character data into the buffer and pad's the
1121
// data with the ccsid manager's space character if the character data length
1122
// is less than paddedLength.
1123
// Not: this method is not to be used for String truncation and the string length
1124
// must be <= paddedLength.
1125
// This method assumes that the String argument can be
1126
// converted by the ccsid manager. This should be fine because usually
1127
// there are restrictions on the characters which can be used for ddm
1128
// character data. This method also assumes that the string.length() will
1129
// be the number of bytes following the conversion.
1130
final void writeScalarPaddedString(String JavaDoc string, int paddedLength) throws SqlException {
1131        int stringLength = string.length();
1132        ensureLength(offset_ + paddedLength);
1133        offset_ = ccsidManager_.convertFromUCS2(string, bytes_, offset_, netAgent_);
1134        for (int i = 0; i < paddedLength - stringLength; i++) {
1135            bytes_[offset_++] = ccsidManager_.space_;
1136        }
1137    }
1138
1139    // this method writes a 4 byte length/codepoint pair plus the bytes contained
1140
// in array buff to the buffer.
1141
// the 2 length bytes in the llcp will contain the length of the data plus
1142
// the length of the llcp. This method does not handle scenarios which
1143
// require extended length bytes.
1144
final void writeScalarBytes(int codePoint, byte[] buff) {
1145        int buffLength = buff.length;
1146        ensureLength(offset_ + buffLength + 4);
1147        bytes_[offset_++] = (byte) (((buffLength + 4) >>> 8) & 0xff);
1148        bytes_[offset_++] = (byte) ((buffLength + 4) & 0xff);
1149        bytes_[offset_++] = (byte) ((codePoint >>> 8) & 0xff);
1150        bytes_[offset_++] = (byte) (codePoint & 0xff);
1151        System.arraycopy(buff, 0, bytes_, offset_, buffLength);
1152        offset_ += buffLength;
1153    }
1154
1155    // this method inserts a 4 byte length/codepoint pair plus length number of bytes
1156
// from array buff starting at offset start.
1157
// Note: no checking will be done on the values of start and length with respect
1158
// the actual length of the byte array. The caller must provide the correct
1159
// values so an array index out of bounds exception does not occur.
1160
// the length will contain the length of the data plus the length of the llcp.
1161
// This method does not handle scenarios which require extended length bytes.
1162
final void writeScalarBytes(int codePoint, byte[] buff, int start, int length) {
1163        ensureLength(offset_ + length + 4);
1164        bytes_[offset_++] = (byte) (((length + 4) >>> 8) & 0xff);
1165        bytes_[offset_++] = (byte) ((length + 4) & 0xff);
1166        bytes_[offset_++] = (byte) ((codePoint >>> 8) & 0xff);
1167        bytes_[offset_++] = (byte) (codePoint & 0xff);
1168        System.arraycopy(buff, start, bytes_, offset_, length);
1169        offset_ += length;
1170    }
1171
1172    // insert a 4 byte length/codepoint pair plus ddm binary data into the
1173
// buffer. The binary data is padded if needed with the padByte
1174
// if the data is less than paddedLength.
1175
// Note: this method is not to be used for truncation and buff.length
1176
// must be <= paddedLength.
1177
// The llcp length bytes will contain the length of the data plus
1178
// the length of the llcp or 4.
1179
// This method does not handle scenarios which require extended length bytes.
1180
final void writeScalarPaddedBytes(int codePoint, byte[] buff, int paddedLength, byte padByte) {
1181        int buffLength = buff.length;
1182        ensureLength(offset_ + paddedLength + 4);
1183        bytes_[offset_++] = (byte) (((paddedLength + 4) >>> 8) & 0xff);
1184        bytes_[offset_++] = (byte) ((paddedLength + 4) & 0xff);
1185        bytes_[offset_++] = (byte) ((codePoint >>> 8) & 0xff);
1186        bytes_[offset_++] = (byte) (codePoint & 0xff);
1187        System.arraycopy(buff, 0, bytes_, offset_, buffLength);
1188        offset_ += buffLength;
1189
1190        for (int i = 0; i < paddedLength - buffLength; i++) {
1191            bytes_[offset_++] = padByte;
1192        }
1193    }
1194
1195    // this method inserts binary data into the buffer and pads the
1196
// data with the padByte if the data length is less than the paddedLength.
1197
// Not: this method is not to be used for truncation and buff.length
1198
// must be <= paddedLength.
1199
final void writeScalarPaddedBytes(byte[] buff, int paddedLength, byte padByte) {
1200        int buffLength = buff.length;
1201        ensureLength(offset_ + paddedLength);
1202        System.arraycopy(buff, 0, bytes_, offset_, buffLength);
1203        offset_ += buffLength;
1204
1205        for (int i = 0; i < paddedLength - buffLength; i++) {
1206            bytes_[offset_++] = padByte;
1207        }
1208    }
1209
1210    // write the request to the OutputStream and flush the OutputStream.
1211
// trace the send if PROTOCOL trace is on.
1212
protected void flush(java.io.OutputStream JavaDoc socketOutputStream) throws java.io.IOException JavaDoc {
1213        if (doesRequestContainData()) {
1214            finalizeDssLength();
1215            sendBytes(socketOutputStream);
1216        }
1217    }
1218
1219    protected void sendBytes(java.io.OutputStream JavaDoc socketOutputStream) throws java.io.IOException JavaDoc {
1220        try {
1221            socketOutputStream.write(bytes_, 0, offset_);
1222            socketOutputStream.flush();
1223        } finally {
1224            if (netAgent_.logWriter_ != null && passwordIncluded_) {
1225                // if password is in the buffer, need to mask it out.
1226
maskOutPassword();
1227                passwordIncluded_ = false;
1228            }
1229            if (netAgent_.loggingEnabled()) {
1230                ((NetLogWriter) netAgent_.logWriter_).traceProtocolFlow(bytes_,
1231                        0,
1232                        offset_,
1233                        NetLogWriter.TYPE_TRACE_SEND,
1234                        "Request",
1235                        "flush",
1236                        1); // tracepoint
1237
}
1238            clearBuffer();
1239        }
1240    }
1241
1242    final void maskOutPassword() {
1243        try {
1244            String JavaDoc maskChar = "*";
1245            // construct a mask using the maskChar.
1246
StringBuffer JavaDoc mask = new StringBuffer JavaDoc();
1247            for (int i = 0; i < passwordLength_; i++) {
1248                mask.append(maskChar);
1249            }
1250            // try to write mask over password.
1251
ccsidManager_.convertFromUCS2(mask.toString(), bytes_, passwordStart_, netAgent_);
1252        } catch (SqlException sqle) {
1253            // failed to convert mask,
1254
// them simply replace with 0xFF.
1255
for (int i = 0; i < passwordLength_; i++) {
1256                bytes_[passwordStart_ + i] = (byte) 0xFF;
1257            }
1258        }
1259    }
1260
1261    // insert a java byte into the buffer.
1262
final void writeByte(byte v) {
1263        ensureLength(offset_ + 1);
1264        bytes_[offset_++] = v;
1265    }
1266
1267    // insert a java short into the buffer.
1268
final void writeShort(short v) {
1269        ensureLength(offset_ + 2);
1270        org.apache.derby.client.am.SignedBinary.shortToBigEndianBytes(bytes_, offset_, v);
1271        offset_ += 2;
1272    }
1273
1274    // insert a java int into the buffer.
1275
void writeInt(int v) {
1276        ensureLength(offset_ + 4);
1277        org.apache.derby.client.am.SignedBinary.intToBigEndianBytes(bytes_, offset_, v);
1278        offset_ += 4;
1279    }
1280
1281    // insert a java long into the buffer.
1282
final void writeLong(long v) {
1283        ensureLength(offset_ + 8);
1284        org.apache.derby.client.am.SignedBinary.longToBigEndianBytes(bytes_, offset_, v);
1285        offset_ += 8;
1286    }
1287
1288    //-- The following are the write short/int/long in bigEndian byte ordering --
1289

1290    // when writing Fdoca data.
1291
protected void writeShortFdocaData(short v) {
1292        ensureLength(offset_ + 2);
1293        org.apache.derby.client.am.SignedBinary.shortToBigEndianBytes(bytes_, offset_, v);
1294        offset_ += 2;
1295    }
1296
1297    // when writing Fdoca data.
1298
protected void writeIntFdocaData(int v) {
1299        ensureLength(offset_ + 4);
1300        org.apache.derby.client.am.SignedBinary.intToBigEndianBytes(bytes_, offset_, v);
1301        offset_ += 4;
1302    }
1303
1304    // when writing Fdoca data.
1305
protected void writeLongFdocaData(long v) {
1306        ensureLength(offset_ + 8);
1307        org.apache.derby.client.am.SignedBinary.longToBigEndianBytes(bytes_, offset_, v);
1308        offset_ += 8;
1309    }
1310
1311    // insert a java float into the buffer.
1312
protected void writeFloat(float v) {
1313        ensureLength(offset_ + 4);
1314        org.apache.derby.client.am.FloatingPoint.floatToIeee754Bytes(bytes_, offset_, v);
1315        offset_ += 4;
1316    }
1317
1318    // insert a java double into the buffer.
1319
protected void writeDouble(double v) {
1320        ensureLength(offset_ + 8);
1321        org.apache.derby.client.am.FloatingPoint.doubleToIeee754Bytes(bytes_, offset_, v);
1322        offset_ += 8;
1323    }
1324
1325    // insert a java.math.BigDecimal into the buffer.
1326
final void writeBigDecimal(java.math.BigDecimal JavaDoc v,
1327                               int declaredPrecision,
1328                               int declaredScale) throws SqlException {
1329        ensureLength(offset_ + 16);
1330        int length = org.apache.derby.client.am.Decimal.bigDecimalToPackedDecimalBytes(bytes_, offset_, v, declaredPrecision, declaredScale);
1331        offset_ += length;
1332    }
1333
1334    final void writeDate(java.sql.Date JavaDoc date) throws SqlException {
1335        try
1336        {
1337            ensureLength(offset_ + 10);
1338            org.apache.derby.client.am.DateTime.dateToDateBytes(bytes_, offset_, date);
1339            offset_ += 10;
1340        } catch (java.io.UnsupportedEncodingException JavaDoc e) {
1341            throw new SqlException(netAgent_.logWriter_,
1342                    new ClientMessageId(SQLState.UNSUPPORTED_ENCODING),
1343                    "java.sql.Date", "DATE", e);
1344        }
1345    }
1346
1347    final void writeTime(java.sql.Time JavaDoc time) throws SqlException {
1348        try{
1349            ensureLength(offset_ + 8);
1350            org.apache.derby.client.am.DateTime.timeToTimeBytes(bytes_, offset_, time);
1351            offset_ += 8;
1352        } catch(UnsupportedEncodingException JavaDoc e) {
1353            throw new SqlException(netAgent_.logWriter_,
1354                    new ClientMessageId(SQLState.UNSUPPORTED_ENCODING),
1355                    "java.sql.Time", "TIME", e);
1356      }
1357    }
1358
1359    final void writeTimestamp(java.sql.Timestamp JavaDoc timestamp) throws SqlException {
1360        try{
1361            ensureLength(offset_ + 26);
1362            org.apache.derby.client.am.DateTime.timestampToTimestampBytes(bytes_, offset_, timestamp);
1363            offset_ += 26;
1364        }catch(UnsupportedEncodingException JavaDoc e) {
1365            throw new SqlException(netAgent_.logWriter_,
1366                    new ClientMessageId(SQLState.UNSUPPORTED_ENCODING),
1367                    "java.sql.Timestamp", "TIMESTAMP", e);
1368        }
1369    }
1370
1371    // insert a java boolean into the buffer. the boolean is written
1372
// as a signed byte having the value 0 or 1.
1373
final void writeBoolean(boolean v) {
1374        ensureLength(offset_ + 1);
1375        bytes_[offset_++] = (byte) ((v ? 1 : 0) & 0xff);
1376    }
1377
1378    // follows the TYPDEF rules (note: don't think ddm char data is ever length
1379
// delimited)
1380
// should this throw SqlException
1381
// Will write a varchar mixed or single
1382
// this was writeLDString
1383
final void writeSingleorMixedCcsidLDString(String JavaDoc s, String JavaDoc encoding) throws SqlException {
1384        byte[] b;
1385        try {
1386            b = s.getBytes(encoding);
1387        } catch (UnsupportedEncodingException JavaDoc e) {
1388            throw new SqlException(netAgent_.logWriter_,
1389                    new ClientMessageId(SQLState.UNSUPPORTED_ENCODING),
1390                    "String", "byte", e);
1391        }
1392        if (b.length > 0x7FFF) {
1393            throw new SqlException(netAgent_.logWriter_,
1394                new ClientMessageId(SQLState.LANG_STRING_TOO_LONG),
1395                "32767");
1396        }
1397        ensureLength(offset_ + b.length + 2);
1398        writeLDBytesX(b.length, b);
1399    }
1400
1401
1402    final void writeLDBytes(byte[] bytes) {
1403        ensureLength(offset_ + bytes.length + 2);
1404        writeLDBytesX(bytes.length, bytes);
1405    }
1406
1407    // private helper method which should only be called by a Request method.
1408
// must call ensureLength before calling this method.
1409
// added for code reuse and helps perf by reducing ensureLength calls.
1410
// ldSize and bytes.length may not be the same. this is true
1411
// when writing graphic ld strings.
1412
private final void writeLDBytesX(int ldSize, byte[] bytes) {
1413        bytes_[offset_++] = (byte) ((ldSize >>> 8) & 0xff);
1414        bytes_[offset_++] = (byte) (ldSize & 0xff);
1415        System.arraycopy(bytes, 0, bytes_, offset_, bytes.length);
1416        offset_ += bytes.length;
1417    }
1418
1419    // does it follows
1420
// ccsid manager or typdef rules. should this method write ddm character
1421
// data or fodca data right now it is coded for ddm char data only
1422
final void writeDDMString(String JavaDoc s) throws SqlException {
1423        ensureLength(offset_ + s.length());
1424        offset_ = ccsidManager_.convertFromUCS2(s, bytes_, offset_, netAgent_);
1425    }
1426
1427
1428    private byte[] buildLengthAndCodePointForEncryptedLob(int codePoint,
1429                                                          int leftToRead,
1430                                                          boolean writeNullByte,
1431                                                          int extendedLengthByteCount) throws DisconnectException {
1432        byte[] lengthAndCodepoint = new byte[4];
1433        byte[] extendedLengthBytes = new byte[extendedLengthByteCount];
1434
1435        if (extendedLengthByteCount > 0) {
1436            // method should never ensure length
1437
lengthAndCodepoint = writeEXTDTALengthCodePointForEncryption(0x8004 + extendedLengthByteCount, codePoint);
1438
1439            if (writeNullByte) {
1440
1441                extendedLengthBytes = writeExtendedLengthBytesForEncryption(extendedLengthByteCount, leftToRead + 1);
1442            } else {
1443                extendedLengthBytes = writeExtendedLengthBytesForEncryption(extendedLengthByteCount, leftToRead);
1444            }
1445        } else {
1446            if (writeNullByte) {
1447                lengthAndCodepoint = writeEXTDTALengthCodePointForEncryption(leftToRead + 4 + 1, codePoint);
1448            } else {
1449                lengthAndCodepoint = writeEXTDTALengthCodePointForEncryption(leftToRead + 4, codePoint);
1450            }
1451        }
1452
1453        if (extendedLengthByteCount > 0) {
1454            byte[] newLengthAndCodepoint = new byte[4 + extendedLengthBytes.length];
1455            System.arraycopy(lengthAndCodepoint, 0, newLengthAndCodepoint, 0, lengthAndCodepoint.length);
1456            System.arraycopy(extendedLengthBytes, 0, newLengthAndCodepoint, lengthAndCodepoint.length, extendedLengthBytes.length);
1457            lengthAndCodepoint = newLengthAndCodepoint;
1458        }
1459
1460        if (writeNullByte) {
1461            byte[] nullByte = new byte[1 + lengthAndCodepoint.length];
1462            System.arraycopy(lengthAndCodepoint, 0, nullByte, 0, lengthAndCodepoint.length);
1463            nullByte[lengthAndCodepoint.length] = 0;
1464            lengthAndCodepoint = nullByte;
1465        }
1466        return lengthAndCodepoint;
1467    }
1468
1469
1470    private void buildLengthAndCodePointForLob(int codePoint,
1471                                               int leftToRead,
1472                                               boolean writeNullByte,
1473                                               int extendedLengthByteCount) throws DisconnectException {
1474        if (extendedLengthByteCount > 0) {
1475            // method should never ensure length
1476
writeLengthCodePoint(0x8004 + extendedLengthByteCount, codePoint);
1477
1478            if (writeNullByte) {
1479                writeExtendedLengthBytes(extendedLengthByteCount, leftToRead + 1);
1480            } else {
1481                writeExtendedLengthBytes(extendedLengthByteCount, leftToRead);
1482            }
1483        } else {
1484            if (writeNullByte) {
1485                writeLengthCodePoint(leftToRead + 4 + 1, codePoint);
1486            } else {
1487                writeLengthCodePoint(leftToRead + 4, codePoint);
1488            }
1489        }
1490
1491        // write the null byte, if necessary
1492
if (writeNullByte) {
1493            write1Byte(0x0);
1494        }
1495
1496    }
1497
1498    public void setDssLengthLocation(int location) {
1499        dssLengthLocation_ = location;
1500    }
1501
1502    public void setCorrelationID(int id) {
1503        correlationID_ = id;
1504    }
1505}
1506
Popular Tags