KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > impl > drda > DDMReader


1 /*
2
3    Derby - Class org.apache.derby.impl.drda.DDMReader
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.impl.drda;
23 import org.apache.derby.iapi.services.sanity.SanityManager;
24 import java.io.IOException JavaDoc;
25 import java.io.InputStream JavaDoc;
26 import java.io.ByteArrayOutputStream JavaDoc;
27 import java.io.ByteArrayInputStream JavaDoc;
28 import java.math.BigDecimal JavaDoc;
29
30 /**
31     The DDMReader is used to read DRDA protocol. DRDA Protocol is divided into
32     three layers corresponding to the DDM three-tier architecture. For each layer,
33     their is a DSS (Data Stream Structure) defined.
34         Layer A Communications management services
35         Layer B Agent services
36         Layer C Data management services
37     <P>
38     At layer A are request, reply and data correlation, structure chaining,
39     continuation or termination of chains when errors are detected, interleaving
40     and multi-leaving request, reply, and data DSSs for multitasking environments.
41     For TCP/IP, the format of the DDM envelope is
42         2 bytes Length of the data
43         1 byte 'D0' - indicates DDM data
44         1 byte DDM format byte(DSSFMT) - type of DSS(RQSDSS,RPYDSS), whether it is
45                     chained, information about the next chained DSS
46         2 bytes request correlation identifier
47     <P>
48     The correlation identifier ties together a request, the request data and the
49     reply. In a chained DSS, each request has a correlation identifier which
50     is higher than the previous request (all correlation identifiers must
51     be greater than 0).
52     <P>
53     At layer B are object mapping, object validation and command routing.
54     Layer B objects with data 5 bytes less than 32K bytes consist of
55         2 bytes Length
56         2 bytes Type of the object (code point)
57         Object data
58     Object data is either SCALAR or COLLECTION data. Scalar data consists of
59     a string of bytes formatted as the class description of the object required.
60     Collections consist of a set of objects in which the entries in the collection
61     are nested within the length/ code point of the collection.
62     <P>
63     Layer B objects with data >=32763 bytes long format is
64         2 bytes Length - length of class, length, and extended total length fields
65                     (high order bit set, indicating >=32763)
66         2 bytes Type of the object (code point)
67         n bytes Extended total length - length of the object
68                     (n = Length - 4)
69         Object data
70     <P>
71     At layer C are services each class of DDM object provides.
72
73             |-------------------------------------------|
74     Layer C | Specific | Specific | Specific |
75             | Commands | Replies | Scalars and |
76             | and their | and their | Collections |
77             |-------------------------------------------|----------------|
78     Layer B | Commands | Reply | Scalars and | Communications |
79             | | Messages | Collections | |
80             |-----------|---------------|---------------|----------------|
81     Layer A | RQSDSS | RPYDSS | OBJDSS | CMNDSS |
82             | | | | Mapped Data |
83             |-----------|---------------|---------------|----------------|
84             | DDM Data Stream Structures |
85             |------------------------------------------------------------|
86             
87     DSS's may be chained so that more than one can be transmitted at a time
88     to improve performance.
89     For more details, see DRDA Volume 3 (Distributed Data Management(DDM)
90         Architecture (DDS definition)
91 */

92 class DDMReader
93 {
94     private final static int DEFAULT_BUFFER_SIZE = 32767;
95     private final static int MAX_MARKS_NESTING = 10;
96     private final static int NO_CODEPOINT = -1;
97     private final static int EMPTY_STACK = -1;
98     private final static boolean ADJUST_LENGTHS = true;
99     private final static boolean NO_ADJUST_LENGTHS = false;
100     private final static long MAX_EXTDTA_SIZE= Long.MAX_VALUE;
101     private static boolean internalTrace = true;
102
103     // magnitude represented in an int array, used in BigDecimal conversion
104
private static final int[][] tenRadixMagnitude = {
105       { 0x3b9aca00 }, // 10^9
106
{ 0x0de0b6b3, 0xa7640000 }, // 10^18
107
{ 0x033b2e3c, 0x9fd0803c, 0xe8000000 }, // 10^27
108
};
109
110     private DRDAConnThread agent;
111     private CcsidManager ccsidManager;
112
113     // data buffer
114
private byte[] buffer;
115     private int pos;
116     private int count;
117
118     // DDM object collection
119
// top of stack
120
private int topDdmCollectionStack;
121     // length of each object in the stack
122
private long[] ddmCollectionLenStack;
123
124     // DDM object length
125
private long ddmScalarLen;
126
127     // DSS Length
128
private int dssLength;
129
130     // DSS is larger than 32762 (continuation bit is set) so DSS is continued
131
private boolean dssIsContinued;
132
133     private boolean terminateChainOnErr;
134
135     // next DSS in the chain has the same correlator
136
private boolean dssIsChainedWithSameID;
137
138     // next DSS in the chain has a different correlator
139
private boolean dssIsChainedWithDiffID;
140     
141     // correlation id for the current DSS
142
private int dssCorrelationID;
143
144     // previous corelation id
145
private int prevCorrelationID;
146
147     // current server codepoint
148
private int svrcod;
149
150     // trace object of the associated session
151
private DssTrace dssTrace;
152
153     // input stream
154
private InputStream JavaDoc inputStream;
155
156     // constructor
157
DDMReader (DRDAConnThread agent, DssTrace dssTrace)
158     {
159         buffer = new byte[DEFAULT_BUFFER_SIZE];
160         ddmCollectionLenStack = new long[MAX_MARKS_NESTING];
161         initialize(agent, dssTrace);
162     }
163     /**
164      * This constructor is used for testing the protocol
165      * It is used by TestProto to read the protocol returned by the
166      * server
167      */

168     DDMReader(CcsidManager ccsidManager, InputStream JavaDoc inputStream)
169     {
170         buffer = new byte[DEFAULT_BUFFER_SIZE];
171         ddmCollectionLenStack = new long[MAX_MARKS_NESTING];
172         this.ccsidManager = ccsidManager;
173         this.inputStream = inputStream;
174         initialize(null, null);
175         // turn off tracing
176
internalTrace = false;
177     }
178     /**
179      * This initializer is used for testing the protocol
180      * It is used by TestProto for the reader it uses
181      */

182     protected void initialize(InputStream JavaDoc inputStream)
183     {
184         this.inputStream = inputStream;
185         initialize(null, null);
186     }
187
188     /**
189      * Initialize values for this session, the reader is reused so we need to
190      * set null and 0 values
191      */

192     protected void initialize(DRDAConnThread agent, DssTrace dssTrace)
193     {
194         this.agent = agent;
195         if (agent != null)
196         {
197             ccsidManager = agent.ccsidManager;
198             inputStream = agent.getInputStream();
199         }
200         topDdmCollectionStack = EMPTY_STACK;
201         svrcod = 0;
202         pos = 0;
203         count = 0;
204         ddmScalarLen = 0;
205         dssLength = 0;
206         prevCorrelationID = DssConstants.CORRELATION_ID_UNKNOWN;
207         dssCorrelationID = DssConstants.CORRELATION_ID_UNKNOWN;
208         this.dssTrace = dssTrace;
209     }
210
211     protected boolean terminateChainOnErr()
212     {
213         return terminateChainOnErr;
214     }
215
216     /**
217      * Next DSS has same correlator as current DSS
218      *
219      * @return true if next DSS has the same correlator as current DSS
220      */

221     protected boolean isChainedWithSameID()
222     {
223         return dssIsChainedWithSameID;
224     }
225
226     /**
227      * Next DSS has different correlator than current DSS
228      *
229      * @return true if next DSS has a different correlator than current DSS
230      */

231     protected boolean isChainedWithDiffID()
232     {
233         return dssIsChainedWithDiffID;
234     }
235
236     /**
237      * Length of current DDM object
238      *
239      * @return length of DDM object
240      */

241     protected long getDdmLength()
242     {
243         return ddmScalarLen;
244     }
245
246     /**
247      * Is there more in this DDM object
248      *
249      * @return true if DDM length is > 0
250      */

251     protected boolean moreDdmData()
252     {
253         return ddmScalarLen > 0;
254     }
255
256     /**
257      * Is there more in this DDS object
258      *
259      * @return true if DDS length is > 0
260      */

261     protected boolean moreDssData()
262     {
263         return dssLength > 0;
264     }
265
266     /**
267      * Is there more data in the buffer
268      *
269      * @return true if there is more data in the buffer
270      */

271     protected boolean moreData()
272     {
273         return (pos - count) > 0;
274     }
275
276     /**
277      * Check for the command protocol
278      *
279      * @return true if this is a command; false otherwise
280      *
281      * @exception DRDProtocolException
282      */

283     protected boolean isCmd() throws DRDAProtocolException, java.io.UnsupportedEncodingException JavaDoc
284     {
285         ensureALayerDataInBuffer(4);
286         String JavaDoc val = new String JavaDoc(buffer, 0, 4, NetworkServerControlImpl.DEFAULT_ENCODING);
287         return NetworkServerControlImpl.isCmd(val);
288     }
289
290     /**
291      * Read DSS header
292      * DSS Header format is
293      * 2 bytes - length
294      * 1 byte - 'D0' - indicates DDM data
295      * 1 byte - DSS format
296      * |---|---------|----------|
297      * | 0 | flags | type |
298      * |---|---------|----------|
299      * | 0 | 1 2 3 | 4 5 6 7 |
300      * |---|---------|----------|
301      * bit 0 - '0'
302      * bit 1 - '0' - unchained, '1' - chained
303      * bit 2 - '0' - do not continue on error, '1' - continue on error
304      * bit 3 - '0' - next DSS has different correlator, '1' - next DSS has
305      * same correlator
306      * type - 1 - Request DSS
307      * - 2 - Reply DSS
308      * - 3 - Object DSS
309      * - 4 - Communications DSS
310      * - 5 - Request DSS where no reply is expected
311      * 2 bytes - request correlation id
312      *
313      * @exception DRDProtocolException
314      */

315     protected int readDssHeader () throws DRDAProtocolException
316     {
317         ensureALayerDataInBuffer (6);
318
319         // read out the DSS length
320
dssLength = ((buffer[pos] & 0xff) << 8) +
321                     ((buffer[pos + 1] & 0xff) << 0);
322         pos += 2;
323         // check for the continuation bit and update length as needed.
324
if ((dssLength & DssConstants.CONTINUATION_BIT) ==
325                 DssConstants.CONTINUATION_BIT)
326         {
327             dssLength = DssConstants.MAX_DSS_LENGTH;
328             dssIsContinued = true;
329         }
330         else
331         {
332             dssIsContinued = false;
333         }
334
335         if (dssLength < 6)
336             agent.throwSyntaxrm(CodePoint.SYNERRCD_DSS_LESS_THAN_6,
337                                DRDAProtocolException.NO_CODPNT_ARG);
338
339         // If the GDS id is not valid, or
340
// if the reply is not an RQSDSS nor
341
// a OBJDSS, then throw an exception.
342

343         if ((buffer[pos++] & 0xff) != DssConstants.DSS_ID)
344             agent.throwSyntaxrm(CodePoint.SYNERRCD_CBYTE_NOT_D0,
345                                DRDAProtocolException.NO_CODPNT_ARG);
346
347         int gdsFormatter = buffer[pos++] & 0xff;
348         
349         if (((gdsFormatter & 0x0F) != DssConstants.DSSFMT_RQSDSS)
350             &&((gdsFormatter & 0x0F) != DssConstants.DSSFMT_OBJDSS))
351         {
352             agent.throwSyntaxrm(CodePoint.SYNERRCD_FBYTE_NOT_SUPPORTED,
353                                DRDAProtocolException.NO_CODPNT_ARG);
354         }
355
356         // Determine if the current DSS is chained with the
357
// next DSS, with the same or different request ID.
358
if ((gdsFormatter & DssConstants.DSSCHAIN) == DssConstants.DSSCHAIN)
359         { // on indicates structure chained to next structure
360
if ((gdsFormatter & DssConstants.DSSCHAIN_SAME_ID)
361                     == DssConstants.DSSCHAIN_SAME_ID)
362             {
363                 dssIsChainedWithSameID = true;
364                 dssIsChainedWithDiffID = false;
365             }
366             else
367             {
368                 dssIsChainedWithSameID = false;
369                 dssIsChainedWithDiffID = true;
370             }
371             if ((gdsFormatter & DssConstants.DSSCHAIN_ERROR_CONTINUE)
372                 == DssConstants.DSSCHAIN_ERROR_CONTINUE)
373                 terminateChainOnErr = false;
374             else
375                 terminateChainOnErr = true;
376         }
377         else
378         {
379             // chaining bit not b'1', make sure DSSFMT same id not b'1'
380
if ((gdsFormatter & DssConstants.DSSCHAIN_SAME_ID)
381                     == DssConstants.DSSCHAIN_SAME_ID)
382             { // Next DSS can not have same correlator
383
agent.throwSyntaxrm(CodePoint.SYNERRCD_CHAIN_OFF_SAME_NEXT_CORRELATOR,
384                                    DRDAProtocolException.NO_CODPNT_ARG);
385             }
386             // chaining bit not b'1', make sure no error continuation
387
if ((gdsFormatter & DssConstants.DSSCHAIN_ERROR_CONTINUE)
388                 == DssConstants.DSSCHAIN_ERROR_CONTINUE)
389             { // must be 'do not continue on error'
390
agent.throwSyntaxrm(CodePoint.SYNERRCD_CHAIN_OFF_ERROR_CONTINUE,
391                                    DRDAProtocolException.NO_CODPNT_ARG);
392             }
393
394             dssIsChainedWithSameID = false;
395             dssIsChainedWithDiffID = false;
396         }
397
398         dssCorrelationID =
399             ((buffer[pos] & 0xff) << 8) +
400             ((buffer[pos + 1] & 0xff) << 0);
401         pos += 2;
402         if (SanityManager.DEBUG)
403             trace("dssLength = " + dssLength + " correlationID = " + dssCorrelationID);
404
405         //check that correlationID is the same as previous
406
if (prevCorrelationID != DssConstants.CORRELATION_ID_UNKNOWN &&
407             dssCorrelationID != prevCorrelationID)
408         {
409             agent.throwSyntaxrm(CodePoint.SYNERRCD_CHAIN_OFF_ERROR_CONTINUE,
410                                DRDAProtocolException.NO_CODPNT_ARG);
411         }
412         
413         // set up previous correlation id to check that next DSS is correctly
414
// formatted
415
if (dssIsChainedWithSameID)
416             prevCorrelationID = dssCorrelationID;
417         else
418             prevCorrelationID = DssConstants.CORRELATION_ID_UNKNOWN;
419
420         dssLength -= 6;
421
422         return dssCorrelationID;
423     }
424     /**
425      * Read Reply DSS
426      * This is used in testing the protocol. We shouldn't see a reply
427      * DSS when we are servicing DRDA commands
428      *
429      * @exception DRDProtocolException
430      */

431     protected void readReplyDss() throws DRDAProtocolException
432     {
433         ensureALayerDataInBuffer (6);
434
435         // read out the DSS length
436
dssLength = ((buffer[pos++] & 0xff) << 8) +
437                     ((buffer[pos++] & 0xff) << 0);
438
439         // check for the continuation bit and update length as needed.
440
if ((dssLength & DssConstants.CONTINUATION_BIT) ==
441                 DssConstants.CONTINUATION_BIT)
442         {
443             dssLength = DssConstants.MAX_DSS_LENGTH;
444             dssIsContinued = true;
445         }
446         else
447         {
448             dssIsContinued = false;
449         }
450
451         if (dssLength < 6)
452             agent.throwSyntaxrm(CodePoint.SYNERRCD_DSS_LESS_THAN_6,
453                                DRDAProtocolException.NO_CODPNT_ARG);
454
455         // If the GDS id is not valid, throw exception
456

457         if ((buffer[pos++] & 0xff) != DssConstants.DSS_ID)
458             agent.throwSyntaxrm(CodePoint.SYNERRCD_CBYTE_NOT_D0,
459                                DRDAProtocolException.NO_CODPNT_ARG);
460
461         int gdsFormatter = buffer[pos++] & 0xff;
462         
463         // Determine if the current DSS is chained with the
464
// next DSS, with the same or different request ID.
465
if ((gdsFormatter & DssConstants.DSSCHAIN) == DssConstants.DSSCHAIN)
466         { // on indicates structure chained to next structure
467
if ((gdsFormatter & DssConstants.DSSCHAIN_SAME_ID)
468                     == DssConstants.DSSCHAIN_SAME_ID)
469             {
470                 dssIsChainedWithSameID = true;
471                 dssIsChainedWithDiffID = false;
472             }
473             else
474             {
475                 dssIsChainedWithSameID = false;
476                 dssIsChainedWithDiffID = true;
477             }
478         }
479         else
480         {
481             dssIsChainedWithSameID = false;
482             dssIsChainedWithDiffID = false;
483         }
484
485         dssCorrelationID =
486             ((buffer[pos++] & 0xff) << 8) +
487             ((buffer[pos++] & 0xff) << 0);
488
489         if (SanityManager.DEBUG)
490             trace("dssLength = " + dssLength + " correlationID = " + dssCorrelationID);
491
492         dssLength -= 6;
493
494     }
495
496     /**
497      * Read the DDM Length and CodePoint
498      *
499      * @return - returns codepoint
500      *
501      * @exception DRDProtocolException
502      */

503     protected int readLengthAndCodePoint() throws DRDAProtocolException
504     {
505         ensureBLayerDataInBuffer (4, NO_ADJUST_LENGTHS);
506
507         ddmScalarLen = readCodePoint();
508         int codePoint = readCodePoint();
509         
510         if (SanityManager.DEBUG)
511             trace("length = "+ ddmScalarLen + " codepoint = " + java.lang.Integer.toHexString(codePoint));
512         // SYNERRCD 0x0D - Object code point index not supported.
513
// the object codepoint index will not be checked here since
514
// the parse methods will catch any incorrect/unexpected codepoint values
515
// and report them as unsupported objects or parameters.
516

517         // Check if this DDM has extended length field
518
if ((ddmScalarLen & DssConstants.CONTINUATION_BIT) == DssConstants.CONTINUATION_BIT)
519         {
520             int numberOfExtendedLenBytes = ((int)ddmScalarLen -
521                     DssConstants.CONTINUATION_BIT) - 4;
522             int adjustSize = 0;
523             ensureBLayerDataInBuffer (numberOfExtendedLenBytes, NO_ADJUST_LENGTHS);
524             switch (numberOfExtendedLenBytes) {
525             case 8:
526                  ddmScalarLen =
527                     ((buffer[pos++] & 0xff) << 56) +
528                     ((buffer[pos++] & 0xff) << 48) +
529                     ((buffer[pos++] & 0xff) << 40) +
530                     ((buffer[pos++] & 0xff) << 32) +
531                     ((buffer[pos++] & 0xff) << 24) +
532                     ((buffer[pos++] & 0xff) << 16) +
533                     ((buffer[pos++] & 0xff) << 8) +
534                     ((buffer[pos++] & 0xff) << 0);
535                 adjustSize = 12;
536                 break;
537             case 6:
538                 ddmScalarLen =
539                     ((buffer[pos++] & 0xff) << 40) +
540                     ((buffer[pos++] & 0xff) << 32) +
541                     ((buffer[pos++] & 0xff) << 24) +
542                     ((buffer[pos++] & 0xff) << 16) +
543                     ((buffer[pos++] & 0xff) << 8) +
544                     ((buffer[pos++] & 0xff) << 0);
545                 adjustSize = 10;
546                 break;
547             case 4:
548                 ddmScalarLen =
549                     ((buffer[pos++] & 0xff) << 24) +
550                     ((buffer[pos++] & 0xff) << 16) +
551                     ((buffer[pos++] & 0xff) << 8) +
552                     ((buffer[pos++] & 0xff) << 0);
553                 adjustSize = 8;
554                 break;
555             default:
556                 agent.throwSyntaxrm(CodePoint.SYNERRCD_INCORRECT_EXTENDED_LEN,
557                                DRDAProtocolException.NO_CODPNT_ARG);
558         }
559
560             // adjust the lengths here. this is a special case since the
561
// extended length bytes do not include their own length.
562
for (int i = 0; i <= topDdmCollectionStack; i++) {
563                 ddmCollectionLenStack[i] -= adjustSize;
564             }
565             dssLength -= adjustSize;
566         }
567         else {
568             if (ddmScalarLen < 4)
569                 agent.throwSyntaxrm(CodePoint.SYNERRCD_OBJ_LEN_LESS_THAN_4,
570                                    DRDAProtocolException.NO_CODPNT_ARG);
571             adjustLengths (4);
572         }
573         return codePoint;
574     }
575
576     /**
577      * Read the CodePoint
578      *
579      * @return - returns codepoint
580      */

581     protected int readCodePoint()
582     {
583         return( ((buffer[pos++] & 0xff) << 8) +
584           ((buffer[pos++] & 0xff) << 0));
585     }
586
587     /**
588      * Push DDM Length on to collection stack
589      */

590     protected void markCollection()
591     {
592         ddmCollectionLenStack[++topDdmCollectionStack] = ddmScalarLen;
593         ddmScalarLen = 0;
594     }
595
596     /**
597      * Get the next CodePoint from a collection
598      * @return NO_CODEPOINT if collection stack is empty or remaining length is
599      * 0; otherwise, read length and code point
600      *
601      * @exception DRDProtocolException
602      */

603     protected int getCodePoint() throws DRDAProtocolException
604     {
605         if (topDdmCollectionStack == EMPTY_STACK)
606         {
607             return NO_CODEPOINT;
608         }
609         else
610         {
611             // if the collecion is exhausted then return NO_CODEPOINT
612
if (ddmCollectionLenStack[topDdmCollectionStack] == 0)
613             {
614                 // done with this collection so remove it's length from the stack
615
ddmCollectionLenStack[topDdmCollectionStack--] = 0;
616                 return NO_CODEPOINT;
617             }
618             else {
619                 return readLengthAndCodePoint();
620             }
621         }
622     }
623     /**
624      * Get the next CodePoint from a collection and check that it matches the specified
625      * CodePoint
626      * @param codePointCheck - codePoint to check against
627      * @return codePoint
628      *
629      * @exception DRDProtocolException
630      */

631     protected int getCodePoint(int codePointCheck) throws DRDAProtocolException
632     {
633         int codePoint = getCodePoint();
634         if (codePoint != codePointCheck)
635             agent.missingCodePoint(codePoint);
636         return codePoint;
637     }
638     /**
639      * The following routines read different types from the input stream
640      * Data can be in network order or platform order depending on whether the
641      * data is part of the protocol or data being received
642      * The platform is determined by EXCSAT protocol
643      */

644
645     /**
646      * Read byte value
647      * @return value
648      *
649      * @exception DRDProtocolException
650      */

651     protected byte readByte () throws DRDAProtocolException
652     {
653         ensureBLayerDataInBuffer (1, ADJUST_LENGTHS);
654         return buffer[pos++];
655     }
656
657     /**
658      * Read byte value and mask out high order bytes before returning
659      * @return value
660      */

661     protected int readUnsignedByte () throws DRDAProtocolException
662     {
663         ensureBLayerDataInBuffer (1, ADJUST_LENGTHS);
664         return (int ) (buffer[pos++] & 0xff);
665     }
666
667     /**
668      * Read network short value
669      * @return value
670      *
671      * @exception DRDProtocolException
672      */

673     protected int readNetworkShort () throws DRDAProtocolException
674     {
675         ensureBLayerDataInBuffer (2, ADJUST_LENGTHS);
676         return ((buffer[pos++] & 0xff) << 8) +
677           ((buffer[pos++] & 0xff) << 0);
678     }
679
680     /**
681      * Read signed network short value
682      * @return value
683      *
684      * @exception DRDProtocolException
685      */

686     protected int readSignedNetworkShort () throws DRDAProtocolException
687     {
688         ensureBLayerDataInBuffer (2, ADJUST_LENGTHS);
689         return (short)(((buffer[pos++] & 0xff) << 8) +
690           ((buffer[pos++] & 0xff) << 0));
691     }
692     /**
693      * Read platform short value
694      * @return value
695      *
696      * @exception DRDProtocolException
697      */

698     protected short readShort (int byteOrder) throws DRDAProtocolException
699     {
700         ensureBLayerDataInBuffer (2, ADJUST_LENGTHS);
701         short s = SignedBinary.getShort (buffer, pos, byteOrder);
702
703         pos += 2;
704
705         return s;
706     }
707
708     /**
709      * Read network int value
710      * @return value
711      *
712      * @exception DRDProtocolException
713      */

714     protected int readNetworkInt () throws DRDAProtocolException
715     {
716         ensureBLayerDataInBuffer (4, ADJUST_LENGTHS);
717         return ((buffer[pos++] & 0xff) << 24) +
718                ((buffer[pos++] & 0xff) << 16) +
719                ((buffer[pos++] & 0xff) << 8) +
720                ((buffer[pos++] & 0xff) << 0);
721     }
722
723     /**
724      * Read platform int value
725      * @return value
726      *
727      * @exception DRDProtocolException
728      */

729     protected int readInt (int byteOrder) throws DRDAProtocolException
730     {
731         ensureBLayerDataInBuffer (4, ADJUST_LENGTHS);
732         int i = SignedBinary.getInt (buffer, pos, byteOrder);
733
734         pos += 4;
735
736         return i;
737     }
738
739     /**
740      * Read network long value
741      * @return value
742      *
743      * @exception DRDProtocolException
744      */

745     protected long readNetworkLong () throws DRDAProtocolException
746     {
747         ensureBLayerDataInBuffer (8, ADJUST_LENGTHS);
748
749         return ((buffer[pos++] & 0xffL) << 56) +
750                ((buffer[pos++] & 0xffL) << 48) +
751                ((buffer[pos++] & 0xffL) << 40) +
752                ((buffer[pos++] & 0xffL) << 32) +
753                ((buffer[pos++] & 0xffL) << 24) +
754                ((buffer[pos++] & 0xffL) << 16) +
755                ((buffer[pos++] & 0xffL) << 8) +
756                ((buffer[pos++] & 0xffL) << 0);
757     }
758
759     
760     /**
761      * Read network six byte value and put it in a long v
762      * @return value
763      *
764      * @exception DRDProtocolException
765      */

766     protected long readNetworkSixByteLong() throws DRDAProtocolException
767     {
768         ensureBLayerDataInBuffer (6, ADJUST_LENGTHS);
769
770         return (
771                 ((buffer[pos++] & 0xffL) << 40) +
772                ((buffer[pos++] & 0xffL) << 32) +
773                ((buffer[pos++] & 0xffL) << 24) +
774                ((buffer[pos++] & 0xffL) << 16) +
775                ((buffer[pos++] & 0xffL) << 8) +
776                ((buffer[pos++] & 0xffL) << 0));
777     }
778
779     /**
780      * Read platform long value
781      * @return value
782      *
783      * @exception DRDProtocolException
784      */

785     protected long readLong (int byteOrder) throws DRDAProtocolException
786     {
787         ensureBLayerDataInBuffer (8, ADJUST_LENGTHS);
788         long l = SignedBinary.getLong (buffer, pos, byteOrder);
789
790         pos += 8;
791
792         return l;
793     }
794
795     /**
796      * Read platform float value
797      * @return value
798      *
799      * @exception DRDProtocolException
800      */

801     protected float readFloat(int byteOrder) throws DRDAProtocolException
802     {
803         return Float.intBitsToFloat(readInt(byteOrder));
804     }
805
806     /**
807      * Read platform double value
808      * @return value
809      *
810      * @exception DRDProtocolException
811      */

812     protected double readDouble(int byteOrder) throws DRDAProtocolException
813     {
814         return Double.longBitsToDouble(readLong(byteOrder));
815     }
816
817     /**
818      * Read a BigDecimal value
819      * @param precision of the BigDecimal
820      * @param scale of the BigDecimal
821      * @return value
822      *
823      * @exception DRDProtocolException
824      */

825     protected BigDecimal JavaDoc readBigDecimal(int precision, int scale) throws DRDAProtocolException
826     {
827       // The byte-length of a packed decimal with precision p is always p/2 + 1
828
int length = precision / 2 + 1;
829
830       ensureBLayerDataInBuffer (length, ADJUST_LENGTHS);
831
832       // check for sign.
833
int signum;
834       if ((buffer[pos+length-1] & 0x0F) == 0x0D)
835         signum = -1;
836       else
837         signum = 1;
838
839       if (precision <= 9) {
840         // can be handled by int without overflow.
841
int value = packedNybblesToInt(buffer, pos, 0, length*2-1);
842
843         // convert value to a byte array of magnitude.
844
byte[] magnitude = new byte[4];
845         magnitude[0] = (byte)(value >>> 24);
846         magnitude[1] = (byte)(value >>> 16);
847         magnitude[2] = (byte)(value >>> 8);
848         magnitude[3] = (byte)(value);
849
850         pos += length;
851         return new java.math.BigDecimal JavaDoc (new java.math.BigInteger JavaDoc(signum, magnitude), scale);
852       }
853       else if (precision <= 18) {
854         // can be handled by long without overflow.
855
long value = packedNybblesToLong(buffer, pos, 0, length*2-1);
856
857         // convert value to a byte array of magnitude.
858
byte[] magnitude = new byte[8];
859         magnitude[0] = (byte)(value >>> 56);
860         magnitude[1] = (byte)(value >>> 48);
861         magnitude[2] = (byte)(value >>> 40);
862         magnitude[3] = (byte)(value >>> 32);
863         magnitude[4] = (byte)(value >>> 24);
864         magnitude[5] = (byte)(value >>> 16);
865         magnitude[6] = (byte)(value >>> 8);
866         magnitude[7] = (byte)(value);
867
868         pos += length;
869         return new java.math.BigDecimal JavaDoc (new java.math.BigInteger JavaDoc(signum, magnitude), scale);
870       }
871       else if (precision <= 27) {
872         // get the value of last 9 digits (5 bytes).
873
int lo = packedNybblesToInt(buffer, pos, (length-5)*2, 9);
874         // get the value of another 9 digits (5 bytes).
875
int me = packedNybblesToInt(buffer, pos, (length-10)*2+1, 9);
876         // get the value of the rest digits.
877
int hi = packedNybblesToInt(buffer, pos, 0, (length-10)*2+1);
878
879         // compute the int array of magnitude.
880
int[] value = computeMagnitude(new int[] {hi, me, lo});
881
882         // convert value to a byte array of magnitude.
883
byte[] magnitude = new byte[12];
884         magnitude[0] = (byte)(value[0] >>> 24);
885         magnitude[1] = (byte)(value[0] >>> 16);
886         magnitude[2] = (byte)(value[0] >>> 8);
887         magnitude[3] = (byte)(value[0]);
888         magnitude[4] = (byte)(value[1] >>> 24);
889         magnitude[5] = (byte)(value[1] >>> 16);
890         magnitude[6] = (byte)(value[1] >>> 8);
891         magnitude[7] = (byte)(value[1]);
892         magnitude[8] = (byte)(value[2] >>> 24);
893         magnitude[9] = (byte)(value[2] >>> 16);
894         magnitude[10] = (byte)(value[2] >>> 8);
895         magnitude[11] = (byte)(value[2]);
896
897         pos += length;
898         return new java.math.BigDecimal JavaDoc (new java.math.BigInteger JavaDoc(signum, magnitude), scale);
899       }
900       else if (precision <= 31) {
901         // get the value of last 9 digits (5 bytes).
902
int lo = packedNybblesToInt(buffer, pos, (length-5)*2, 9);
903         // get the value of another 9 digits (5 bytes).
904
int meLo = packedNybblesToInt(buffer, pos, (length-10)*2+1, 9);
905         // get the value of another 9 digits (5 bytes).
906
int meHi = packedNybblesToInt(buffer, pos, (length-14)*2, 9);
907         // get the value of the rest digits.
908
int hi = packedNybblesToInt(buffer, pos, 0, (length-14)*2);
909
910         // compute the int array of magnitude.
911
int[] value = computeMagnitude(new int[] {hi, meHi, meLo, lo});
912
913         // convert value to a byte array of magnitude.
914
byte[] magnitude = new byte[16];
915         magnitude[0] = (byte)(value[0] >>> 24);
916         magnitude[1] = (byte)(value[0] >>> 16);
917         magnitude[2] = (byte)(value[0] >>> 8);
918         magnitude[3] = (byte)(value[0]);
919         magnitude[4] = (byte)(value[1] >>> 24);
920         magnitude[5] = (byte)(value[1] >>> 16);
921         magnitude[6] = (byte)(value[1] >>> 8);
922         magnitude[7] = (byte)(value[1]);
923         magnitude[8] = (byte)(value[2] >>> 24);
924         magnitude[9] = (byte)(value[2] >>> 16);
925         magnitude[10] = (byte)(value[2] >>> 8);
926         magnitude[11] = (byte)(value[2]);
927         magnitude[12] = (byte)(value[3] >>> 24);
928         magnitude[13] = (byte)(value[3] >>> 16);
929         magnitude[14] = (byte)(value[3] >>> 8);
930         magnitude[15] = (byte)(value[3]);
931
932         pos += length;
933         return new java.math.BigDecimal JavaDoc (new java.math.BigInteger JavaDoc(signum, magnitude), scale);
934       }
935       else {
936         pos += length;
937         // throw an exception here if nibbles is greater than 31
938
throw new java.lang.IllegalArgumentException JavaDoc("Decimal may only be up to 31 digits!");
939       }
940     }
941
942     
943
944     byte[] getExtData (boolean checkNullability) throws DRDAProtocolException
945     {
946         return getExtData(ddmScalarLen, checkNullability);
947     }
948
949     
950     /**
951      * Creates an InputStream which can stream EXTDTA objects.
952      * The InputStream uses this DDMReader to read data from network. The
953      * DDMReader should not be used before all data in the stream has been read.
954      * @param checkNullability used to check if the stream is null. If it is
955      * null, this method returns null
956      * @return EXTDTAReaderInputStream object which can be passed to prepared
957      * statement as a binary stream.
958      * @exception DRDAProtocolException standard DRDA protocol exception
959      */

960     EXTDTAReaderInputStream getEXTDTAReaderInputStream
961         (final boolean checkNullability)
962         throws DRDAProtocolException
963     {
964         if (checkNullability && isEXTDTANull()) {
965             return null;
966         } else {
967             return new EXTDTAReaderInputStream(this);
968         }
969     }
970
971     /**
972      * This method is used by EXTDTAReaderInputStream to read the first chunk
973      * of data.
974      * @param desiredLength the desired length of chunk
975      * @exception DRDAProtocolException standard DRDA protocol exception
976      */

977     ByteArrayInputStream JavaDoc readLOBInitStream(final long desiredLength)
978         throws DRDAProtocolException
979     {
980         return readLOBChunk(false, desiredLength);
981     }
982     
983     /**
984      * This method is used by EXTDTAReaderInputStream to read the next chunk
985      * of data.
986      * @param desiredLength the desired length of chunk
987      * @exception IOException IOException
988      */

989     ByteArrayInputStream JavaDoc readLOBContinuationStream (final long desiredLength)
990         throws IOException JavaDoc
991     {
992         try {
993             return readLOBChunk(true, desiredLength);
994         } catch (DRDAProtocolException e) {
995             e.printStackTrace(agent.getServer().logWriter);
996             throw new IOException JavaDoc(e.getMessage());
997         }
998     }
999
1000    /**
1001     * This method is used by EXTDTAReaderInputStream to read the next chunk
1002     * of data.
1003     * @param readHeader set to true if the dss continuation should be read
1004     * @param desiredLength the desired length of chunk
1005     * @exception DRDAProtocolException standard DRDA protocol exception
1006     */

1007    private ByteArrayInputStream JavaDoc readLOBChunk
1008        (final boolean readHeader, final long desiredLength)
1009        throws DRDAProtocolException
1010    {
1011        if (readHeader) {
1012            readDSSContinuationHeader();
1013        }
1014        int copySize = (int) Math.min(dssLength, desiredLength);
1015        
1016        // read the segment
1017
ensureALayerDataInBuffer (copySize);
1018        adjustLengths (copySize);
1019        
1020        // Create ByteArrayInputStream on top of buffer.
1021
// This will not make a copy of the buffer.
1022
ByteArrayInputStream JavaDoc bais =
1023            new ByteArrayInputStream JavaDoc(buffer, pos, copySize);
1024        pos += copySize;
1025        
1026        return bais;
1027    }
1028
1029    byte[] getExtData (long desiredLength, boolean checkNullability) throws DRDAProtocolException
1030  {
1031    boolean readHeader;
1032    int copySize;
1033    ByteArrayOutputStream JavaDoc baos;
1034    boolean isLengthAndNullabilityUnknown = false;
1035
1036    
1037    if (desiredLength != -1) {
1038        // allocate a stream based on a known amount of data
1039
baos = new ByteArrayOutputStream JavaDoc ((int) desiredLength);
1040    }
1041    else {
1042        // allocate a stream to hold an unknown amount of data
1043
baos = new ByteArrayOutputStream JavaDoc ();
1044        //isLengthAndNullabilityUnknown = true;
1045
// If we aren't given a length get the whole thing.
1046
desiredLength = MAX_EXTDTA_SIZE;
1047    }
1048    
1049
1050    // check for a null EXTDTA value, if it is nullable and if streaming
1051
if (checkNullability)
1052      if (isEXTDTANull())
1053        return null;
1054
1055    // set the amount to read for the first segment
1056
copySize = (int) Math.min(dssLength,desiredLength); //note: has already been adjusted for headers
1057

1058
1059    //if (checkNullability) // don't count the null byte we've already read
1060
//copySize--;
1061

1062    do {
1063      // determine if a continuation header needs to be read after the data
1064
if (dssIsContinued)
1065        readHeader = true;
1066      else
1067        readHeader = false;
1068
1069      // read the segment
1070
ensureALayerDataInBuffer (copySize);
1071      adjustLengths (copySize);
1072      baos.write (buffer, pos, copySize);
1073      pos += copySize;
1074      desiredLength -= copySize;
1075
1076      // read the continuation header, if necessary
1077
if (readHeader)
1078        readDSSContinuationHeader ();
1079
1080      copySize = (int) Math.min(dssLength,desiredLength); //note: has already been adjusted for headers
1081

1082    }
1083    while (readHeader == true && desiredLength > 0);
1084
1085    return baos.toByteArray();
1086  }
1087
1088
1089  // reads a DSS continuation header
1090
// prereq: pos is positioned on the first byte of the two-byte header
1091
// post: dssIsContinued is set to true if the continuation bit is on, false otherwise
1092
// dssLength is set to DssConstants.MAXDSS_LEN - 2 (don't count the header for the next read)
1093
// helper method for getEXTDTAData
1094
private void readDSSContinuationHeader () throws DRDAProtocolException
1095  {
1096    ensureALayerDataInBuffer(2);
1097
1098    dssLength =
1099      ((buffer[pos++]&0xFF) << 8) +
1100      ((buffer[pos++]&0xFF) << 0);
1101
1102    if ((dssLength & 0x8000) == 0x8000) {
1103      dssLength = DssConstants.MAX_DSS_LENGTH;
1104      dssIsContinued = true;
1105    }
1106    else {
1107      dssIsContinued = false;
1108    }
1109    // it is a syntax error if the dss continuation header length
1110
// is less than or equal to two
1111
if (dssLength <= 2) {
1112        agent.throwSyntaxrm(CodePoint.SYNERRCD_DSS_CONT_LESS_OR_EQUAL_2,
1113                               DRDAProtocolException.NO_CODPNT_ARG);
1114    }
1115
1116    dssLength -= 2; // avoid consuming the DSS cont header
1117
}
1118
1119// checks the null EXTDTA byte
1120
// returns true if null, false otherwise
1121
// helper method for getEXTDTAData
1122
private boolean isEXTDTANull () throws DRDAProtocolException
1123  {
1124    // make sure that the null byte is in the buffer
1125
ensureALayerDataInBuffer (1);
1126    adjustLengths (1);
1127
1128    // examine the null byte
1129
byte nullByte = buffer[pos++];
1130    if (nullByte == (byte)0x00)
1131      return false;
1132
1133    return true;
1134  }
1135
1136
1137   /**
1138    * Convert a range of packed nybbles (up to 9 digits without overflow) to an int.
1139    * Note that for performance purpose, it does not do array-out-of-bound checking.
1140    * @param buffer buffer to read from
1141    * @param offset offset in the buffer
1142    * @param startNybble start nybble
1143    * @param numberOfNybbles number of nybbles
1144    * @return an int value
1145    */

1146    private int packedNybblesToInt (byte[] buffer,
1147                                         int offset,
1148                                         int startNybble,
1149                                         int numberOfNybbles)
1150    {
1151      int value = 0;
1152
1153      int i = startNybble / 2;
1154      if ((startNybble % 2) != 0) {
1155        // process low nybble of the first byte if necessary.
1156
value += buffer[offset+i] & 0x0F;
1157        i++;
1158      }
1159
1160      int endNybble = startNybble + numberOfNybbles -1;
1161      for (; i<(endNybble+1)/2; i++) {
1162        value = value*10 + ((buffer[offset+i] & 0xF0) >>> 4); // high nybble.
1163
value = value*10 + (buffer[offset+i] & 0x0F); // low nybble.
1164
}
1165
1166      if ((endNybble % 2) == 0) {
1167        // process high nybble of the last byte if necessary.
1168
value = value*10 + ((buffer[offset+i] & 0xF0) >>> 4);
1169      }
1170
1171      return value;
1172    }
1173
1174    /**
1175     * Convert a range of packed nybbles (up to 18 digits without overflow) to a long.
1176     * Note that for performance purpose, it does not do array-out-of-bound checking.
1177     * @param buffer buffer to read from
1178     * @param offset offset in the buffer
1179     * @param startNybble start nybble
1180     * @param numberOfNybbles number of nybbles
1181     * @return an long value
1182     */

1183    private long packedNybblesToLong (byte[] buffer,
1184                                           int offset,
1185                                           int startNybble,
1186                                           int numberOfNybbles)
1187    {
1188      long value = 0;
1189
1190      int i = startNybble / 2;
1191      if ((startNybble % 2) != 0) {
1192        // process low nybble of the first byte if necessary.
1193
value += buffer[offset+i] & 0x0F;
1194        i++;
1195      }
1196
1197      int endNybble = startNybble + numberOfNybbles -1;
1198      for (; i<(endNybble+1)/2; i++) {
1199        value = value*10 + ((buffer[offset+i] & 0xF0) >>> 4); // high nybble.
1200
value = value*10 + (buffer[offset+i] & 0x0F); // low nybble.
1201
}
1202
1203      if ((endNybble % 2) == 0) {
1204        // process high nybble of the last byte if necessary.
1205
value = value*10 + ((buffer[offset+i] & 0xF0) >>> 4);
1206      }
1207
1208      return value;
1209    }
1210
1211    /**
1212     * Compute the int array of magnitude from input value segments.
1213     * @param input value segments
1214     * @return array of int magnitudes
1215     */

1216    private int[] computeMagnitude(int[] input)
1217    {
1218        int length = input.length;
1219        int[] mag = new int[length];
1220
1221        mag[length-1] = input[length-1];
1222        for (int i=0; i<length-1; i++) {
1223          int carry = 0;
1224          int j = tenRadixMagnitude[i].length-1;
1225          int k = length-1;
1226          for (; j>=0; j--, k--) {
1227            long product = (input[length-2-i] & 0xFFFFFFFFL) * (tenRadixMagnitude[i][j] & 0xFFFFFFFFL)
1228                         + (mag[k] & 0xFFFFFFFFL) // add previous value
1229
+ (carry & 0xFFFFFFFFL); // add carry
1230
carry = (int) (product >>> 32);
1231            mag[k] = (int) (product & 0xFFFFFFFFL);
1232          }
1233          mag[k] = (int) carry;
1234        }
1235        return mag;
1236    }
1237
1238    /**
1239     * Read boolean value
1240     * @return value
1241     *
1242     * @exception DRDProtocolException
1243     */

1244    protected boolean readBoolean () throws DRDAProtocolException
1245    {
1246        ensureBLayerDataInBuffer (1, ADJUST_LENGTHS);
1247        return buffer[pos++] != 0;
1248    }
1249
1250    /**
1251     * Read encrypted string
1252     * @param decryptM decryption manager
1253     * @param securityMechanism security mechanism
1254     * @param initVector initialization vector for cipher
1255     * @param sourcePublicKey public key (as in Deffie-Hellman algorithm)
1256     * from source (encryptor)
1257     * @return decrypted string
1258     *
1259     * @exception DRDProtocolException, SQLException(wrapping any exception in decryption)
1260     */

1261    protected String JavaDoc readEncryptedString (DecryptionManager decryptM, int securityMechanism,
1262                                         byte[] initVector, byte[] sourcePublicKey)
1263            throws DRDAProtocolException, java.sql.SQLException JavaDoc
1264    {
1265        byte[] cipherText = readBytes();
1266        byte[] plainText = null;
1267        plainText = decryptM.decryptData(cipherText, securityMechanism, initVector,
1268                                             sourcePublicKey);
1269        if (plainText == null)
1270            return null;
1271        else
1272            return ccsidManager.convertToUCS2(plainText);
1273    }
1274
1275    /**
1276     * Read string value
1277     * Strings in DRDA protocol are encoded in EBCDIC by default so we
1278     * need to convert to UCS2
1279     * @param length - length of string to read
1280     * @return value
1281     *
1282     * @exception DRDProtocolException
1283     */

1284    protected String JavaDoc readString (int length) throws DRDAProtocolException
1285    {
1286        ensureBLayerDataInBuffer (length, ADJUST_LENGTHS);
1287
1288        String JavaDoc result = ccsidManager.convertToUCS2 (buffer, pos, length);
1289        pos += length;
1290        return result;
1291    }
1292
1293    /**
1294     * Read string value into a <code>DRDAString</code> object.
1295     *
1296     * @param dst destination for the read string
1297     * @param size size (in bytes) of string to read
1298     * @param unpad if true, remove padding (trailing spaces)
1299     *
1300     * @exception DRDAProtocolException
1301     */

1302    protected void readString(DRDAString dst, int size, boolean unpad)
1303        throws DRDAProtocolException
1304    {
1305        ensureBLayerDataInBuffer(size, ADJUST_LENGTHS);
1306        int startPos = pos;
1307        pos += size;
1308        if (unpad) {
1309            while ((size > 0) &&
1310                   (buffer[startPos + size - 1] == ccsidManager.space)) {
1311                --size;
1312            }
1313        }
1314        dst.setBytes(buffer, startPos, size);
1315    }
1316
1317    /**
1318     * Read encoded string value
1319     * @param length - length of string to read
1320     * @return value
1321     *
1322     * @exception DRDProtocolException
1323     */

1324    protected String JavaDoc readString (int length, String JavaDoc encoding)
1325        throws DRDAProtocolException
1326    {
1327        ensureBLayerDataInBuffer (length, ADJUST_LENGTHS);
1328        String JavaDoc s = null;
1329
1330        try {
1331          s = new String JavaDoc (buffer, pos, length, encoding);
1332        }
1333        catch (java.io.UnsupportedEncodingException JavaDoc e) {
1334            agent.agentError("UnsupportedEncodingException in readString, encoding = "
1335                    + encoding);
1336            e.printStackTrace(agent.getServer().logWriter);
1337        }
1338        
1339        pos += length;
1340        return s;
1341    }
1342
1343    /**
1344     * Read string value in DDM data with default encoding
1345     * @return value
1346     *
1347     * @exception DRDProtocolException
1348     */

1349    protected String JavaDoc readStringData()
1350        throws DRDAProtocolException
1351    {
1352        return readString((int)ddmScalarLen, NetworkServerControlImpl.DEFAULT_ENCODING);
1353    }
1354
1355    /**
1356     * Read specified length of string value in DDM data with default encoding
1357     * @param length - length of string to read
1358     * @return value
1359     *
1360     * @exception DRDProtocolException
1361     */

1362    protected String JavaDoc readStringData(int length)
1363        throws DRDAProtocolException
1364    {
1365        return readString(length, NetworkServerControlImpl.DEFAULT_ENCODING);
1366    }
1367
1368    /**
1369     * Read length delimited string value in DDM data with default encoding
1370     * @return value
1371     *
1372     * @exception DRDProtocolException
1373     */

1374    protected String JavaDoc readLDStringData(String JavaDoc encoding)
1375        throws DRDAProtocolException
1376    {
1377        int length = readNetworkShort();
1378        return readString(length, encoding);
1379    }
1380
1381    /**
1382     * Read string value
1383     *
1384     * @exception DRDProtocolException
1385     */

1386    protected String JavaDoc readString () throws DRDAProtocolException
1387    {
1388        return readString((int)ddmScalarLen);
1389    }
1390
1391    /**
1392     * Read byte string value
1393     * @param length - length of string to read
1394     * @return byte array
1395     *
1396     * @exception DRDProtocolException
1397     */

1398    protected byte[] readBytes (int length) throws DRDAProtocolException
1399    {
1400        byte[] b;
1401
1402        if (length < DssConstants.MAX_DSS_LENGTH)
1403        {
1404            ensureBLayerDataInBuffer (length, ADJUST_LENGTHS);
1405            b = new byte[length];
1406            System.arraycopy(buffer,pos,b,0,length);
1407            pos +=length;
1408        }
1409        else
1410            b = getExtData(length,false);
1411        return b;
1412    }
1413    
1414    /**
1415     * Read byte string value
1416     * @return byte array
1417     *
1418     * @exception DRDProtocolException
1419     */

1420    protected byte[] readBytes () throws DRDAProtocolException
1421    {
1422        return readBytes((int)ddmScalarLen);
1423    }
1424
1425    /**
1426     * Skip byte string value
1427     * @param length - length of string to skip
1428     *
1429     * @exception DRDProtocolException
1430     */

1431    protected void skipBytes (int length) throws DRDAProtocolException
1432    {
1433        ensureBLayerDataInBuffer (length, ADJUST_LENGTHS);
1434        pos += length;
1435    }
1436
1437    /**
1438     * Skip byte string value
1439     *
1440     * @exception DRDAProtocolException
1441     */

1442    protected void skipBytes () throws DRDAProtocolException
1443    {
1444        skipBytes((int)ddmScalarLen);
1445    }
1446
1447    /**
1448     * Skip remaining DSS
1449     *
1450     * @exception DRDAProtocolException
1451     */

1452    protected void skipDss() throws DRDAProtocolException
1453    {
1454        while (dssIsContinued)
1455        {
1456            skipBytes((int)dssLength);
1457            readDSSContinuationHeader();
1458        }
1459        skipBytes((int)dssLength);
1460        topDdmCollectionStack = EMPTY_STACK;
1461        ddmScalarLen = 0;
1462        dssLength = 0;
1463
1464    }
1465
1466    protected void clearBuffer() throws DRDAProtocolException
1467    {
1468        skipBytes(java.lang.Math.min(dssLength, count - pos));
1469        dssIsChainedWithSameID = false;
1470        dssIsChainedWithDiffID = false;
1471    }
1472
1473    /**
1474     * Convert EBCDIC byte array to unicode string
1475     *
1476     * @param buf - byte array
1477     * @return string
1478     */

1479    protected String JavaDoc convertBytes(byte[] buf)
1480    {
1481        return ccsidManager.convertToUCS2 (buf, 0, buf.length);
1482    }
1483
1484    // Private methods
1485
/**
1486     * Adjust remaining length
1487     *
1488     * @param length - adjustment length
1489     */

1490    private void adjustLengths(int length)
1491    {
1492        ddmScalarLen -= length;
1493        for (int i = 0; i <= topDdmCollectionStack; i++) {
1494          ddmCollectionLenStack[i] -= length;
1495        }
1496        dssLength -= length;
1497    }
1498
1499    /********************************************************************/
1500    /* NetworkServerControl command protocol reading routines
1501     */

1502    /********************************************************************/
1503    /**
1504     * Read string value
1505     * @param length - length of string to read
1506     * @return value
1507     *
1508     * @exception DRDProtocolException
1509     */

1510    protected String JavaDoc readCmdString (int length) throws DRDAProtocolException, java.io.UnsupportedEncodingException JavaDoc
1511    {
1512        if (length == 0)
1513            return null;
1514
1515        ensureBLayerDataInBuffer (length, ADJUST_LENGTHS);
1516        String JavaDoc result = new String JavaDoc (buffer, pos, length,
1517                                        NetworkServerControlImpl.DEFAULT_ENCODING);
1518        pos += length;
1519        return result;
1520    }
1521    /**
1522     * Read string value
1523     * @return value
1524     *
1525     * @exception DRDProtocolException
1526     */

1527    protected String JavaDoc readCmdString () throws DRDAProtocolException, java.io.UnsupportedEncodingException JavaDoc
1528    {
1529        int length = readNetworkShort();
1530        return readCmdString(length);
1531        
1532    }
1533
1534    /**************************************************************************/
1535    /* Private methods
1536    /**************************************************************************/

1537    /**
1538     * Make sure a certain amount of Layer A data is in the buffer.
1539     * The data will be in the buffer after this method is called.
1540     *
1541     * @param desiredDataSize - amount of data we need
1542     *
1543     * @exception DRDAProtocolException
1544     */

1545    private void ensureALayerDataInBuffer (int desiredDataSize)
1546        throws DRDAProtocolException
1547    {
1548        // calulate the the number of bytes in the buffer.
1549
int avail = count - pos;
1550
1551        // read more bytes off the network if the data is not in the buffer already.
1552
if (avail < desiredDataSize)
1553        {
1554          fill (desiredDataSize - avail);
1555        }
1556    }
1557    /**
1558     * Make sure a certain amount of Layer B data is in the buffer.
1559     * The data will be in the buffer after this method is called.
1560     *
1561     * @param desiredDataSize - amount of data we need
1562     * @param adjustLen - whether to adjust the remaining lengths
1563     *
1564     * @exception DRDProtocolException
1565     */

1566    private void ensureBLayerDataInBuffer (int desiredDataSize, boolean adjustLen)
1567        throws DRDAProtocolException
1568    {
1569        ensureALayerDataInBuffer (desiredDataSize);
1570        if (dssIsContinued)
1571        {
1572            if (desiredDataSize > dssLength)
1573            {
1574                int continueDssHeaderCount =
1575                    (((desiredDataSize - dssLength) / DssConstants.MAX_DSS_LENGTH) + 1);
1576                compressBLayerData (continueDssHeaderCount);
1577            }
1578        }
1579        if (adjustLen)
1580            adjustLengths(desiredDataSize);
1581    }
1582
1583    /**
1584     * Compress B Layer data if extended total length is used
1585     * by removing the continuation headers
1586     *
1587     * @param continueDssHeaderCount - amount of data we need
1588     *
1589     * @exception throws DRDAProtocolException
1590     */

1591    private void compressBLayerData (int continueDssHeaderCount)
1592        throws DRDAProtocolException
1593    {
1594
1595        
1596        // jump to the last continuation header.
1597
int tempPos = 0;
1598        for (int i = 0; i < continueDssHeaderCount; i++)
1599        {
1600            // the first may be less than the size of a full DSS
1601
if (i == 0)
1602            {
1603                // only jump by the number of bytes remaining in the current DSS
1604
tempPos = pos + dssLength;
1605            }
1606            else
1607            {
1608                // all other jumps are for a full continued DSS
1609
tempPos += DssConstants.MAX_DSS_LENGTH;
1610            }
1611        }
1612
1613
1614        // for each of the DSS headers to remove,
1615
// read out the continuation header and increment the DSS length by the
1616
// size of the continuation bytes, then shift the continuation data as needed.
1617
int shiftSize = 0;
1618        int bytesToShift = 0;
1619        int continueHeaderLength = 0;
1620        int newdssLength = 0;
1621
1622
1623        for (int i = 0; i < continueDssHeaderCount; i++)
1624        {
1625            continueHeaderLength = ((buffer[tempPos] & 0xff) << 8) +
1626                ((buffer[tempPos + 1] & 0xff) << 0);
1627
1628            if (i == 0)
1629            {
1630                // if this is the last one (farthest down stream and first to strip out)
1631

1632                if ((continueHeaderLength & DssConstants.CONTINUATION_BIT)
1633                        == DssConstants.CONTINUATION_BIT)
1634                {
1635                  // the last DSS header is again continued
1636
continueHeaderLength = DssConstants.MAX_DSS_LENGTH;
1637                  dssIsContinued = true;
1638                }
1639                else
1640                {
1641                  // the last DSS header was not contiued so update continue state flag
1642
dssIsContinued = false;
1643                }
1644                // the very first shift size is 2
1645
shiftSize = 2;
1646            }
1647            else
1648            {
1649                // already removed the last header so make sure the chaining flag is on
1650
if ((continueHeaderLength & DssConstants.CONTINUATION_BIT) ==
1651                        DssConstants.CONTINUATION_BIT)
1652                {
1653                  continueHeaderLength = DssConstants.MAX_DSS_LENGTH;
1654                }
1655                else
1656                {
1657                  // this is a syntax error but not really certain which one.
1658
// for now pick 0x02 which is DSS header Length does not
1659
// match the number
1660
// of bytes of data found.
1661
agent.throwSyntaxrm(CodePoint.SYNERRCD_DSS_LENGTH_BYTE_NUMBER_MISMATCH,
1662                                       DRDAProtocolException.NO_CODPNT_ARG);
1663                }
1664                // increase the shift size by 2
1665
shiftSize += 2;
1666            }
1667
1668            // it is a syntax error if the DSS continuation is less
1669
// than or equal to two
1670
if (continueHeaderLength <= 2)
1671            {
1672                agent.throwSyntaxrm(CodePoint.SYNERRCD_DSS_CONT_LESS_OR_EQUAL_2,
1673                               DRDAProtocolException.NO_CODPNT_ARG);
1674            }
1675
1676            newdssLength += (continueHeaderLength-2);
1677
1678            // calculate the number of bytes to shift
1679
if (i != (continueDssHeaderCount - 1))
1680                bytesToShift = DssConstants.MAX_DSS_LENGTH;
1681            else
1682                bytesToShift = dssLength;
1683
1684            tempPos -= (bytesToShift - 2);
1685            System.arraycopy(buffer, tempPos - shiftSize, buffer, tempPos,
1686                             bytesToShift);
1687        }
1688        // reposition the start of the data after the final DSS shift.
1689
pos = tempPos;
1690        dssLength += newdssLength;
1691    }
1692
1693    /**
1694     * Methods to manage the data buffer.
1695     * Methods orginally from JCC
1696     * RESOLVE: need to check if this is the best performing way of doing this
1697     */

1698
1699    /**
1700     * This is a helper method which shifts the buffered bytes from
1701     * wherever they are in the current buffer to the beginning of
1702     * different buffer (note these buffers could be the same).
1703     * State information is updated as needed after the shift.
1704     * @param destinationBuffer - buffer to shift data to
1705     */

1706    private void shiftBuffer (byte[] destinationBuffer)
1707    {
1708        // calculate the size of the data in the current buffer.
1709
int sz = count - pos;
1710        if (SanityManager.DEBUG) {
1711            if ((sz < 0 || pos < 0) )
1712            {
1713                SanityManager.THROWASSERT(
1714                          "Unexpected data size or position. sz=" + sz +
1715                          " count=" + count +" pos=" + pos);
1716            }
1717        }
1718        
1719        // copy this data to the new buffer startsing at position 0.
1720
System.arraycopy (buffer, pos, destinationBuffer, 0, sz);
1721
1722        // update the state information for data in the new buffer.
1723
pos = 0;
1724        count = sz;
1725
1726        // replace the old buffer with the new buffer.
1727
buffer = destinationBuffer;
1728    }
1729    /**
1730     * This method makes sure there is enough room in the buffer
1731     * for a certain number of bytes. This method will allocate
1732     * a new buffer if needed and shift the bytes in the current buffer
1733     * to make ensure space is available for a fill. Right now
1734     * this method will shift bytes as needed to make sure there is
1735     * as much room as possible in the buffer before trying to
1736     * do the read. The idea is to try to have space to get as much data as possible
1737     * if we need to do a read on the socket's stream.
1738     *
1739     * @param desiredSpace - amount of data we need
1740     */

1741    private void ensureSpaceInBufferForFill (int desiredSpace)
1742    {
1743        // calculate the total unused space in the buffer.
1744
// this includes any space at the end of the buffer and any free
1745
// space at the beginning resulting from bytes already read.
1746
int currentAvailableSpace = (buffer.length - count) + pos;
1747
1748        // check to see if there is enough free space.
1749
if (currentAvailableSpace < desiredSpace) {
1750
1751            // there is not enough free space so we need more storage.
1752
// we are going to double the buffer unless that happens to still be
1753
// too small. If more than double the buffer is needed,
1754
// use the smallest amount over this as possible.
1755
int doubleBufferSize = (2 * buffer.length);
1756            int minumNewBufferSize = (desiredSpace - currentAvailableSpace) +
1757                buffer.length;
1758            int newsz = minumNewBufferSize <= doubleBufferSize ?
1759                doubleBufferSize : minumNewBufferSize;
1760
1761            byte[] newBuffer = new byte[newsz];
1762
1763            // shift everything from the old buffer to the new buffer
1764
shiftBuffer (newBuffer);
1765        }
1766        else {
1767
1768            // there is enough free space in the buffer but let's make sure
1769
// it is all at the end.
1770
// this is also important because if we are going to do a read,
1771
// it would be nice
1772
// to get as much data as possible and making room at the end
1773
// if the buffer helps to ensure this.
1774
if (pos != 0) {
1775                shiftBuffer (buffer);
1776            }
1777        }
1778    }
1779
1780    /**
1781     * This method will attempt to read a minimum number of bytes
1782     * from the underlying stream. This method will keep trying to
1783     * read bytes until it has obtained at least the minimum number.
1784     * @param minimumBytesNeeded - minimum required bytes
1785     *
1786     * @exception DRDProtocolException
1787     */

1788    private void fill (int minimumBytesNeeded) throws DRDAProtocolException
1789    {
1790        // make sure that there is enough space in the buffer to hold
1791
// the minimum number of bytes needed.
1792
ensureSpaceInBufferForFill (minimumBytesNeeded);
1793
1794        // read until the minimum number of bytes needed is now in the buffer.
1795
// hopefully the read method will return as many bytes as it can.
1796
int totalBytesRead = 0;
1797        int actualBytesRead = 0;
1798        do {
1799            try {
1800                actualBytesRead = inputStream.read (
1801                  buffer, count, buffer.length - count);
1802            }
1803            catch (java.io.IOException JavaDoc ioe) {
1804                agent.markCommunicationsFailure ("DDMReader.fill()",
1805                  "InputStream.read()", ioe.getMessage(), "*");
1806            }
1807            finally {
1808                if ((dssTrace != null) && dssTrace.isComBufferTraceOn())
1809                  dssTrace.writeComBufferData (buffer,
1810                                               count,
1811                                               actualBytesRead,
1812                                               DssTrace.TYPE_TRACE_RECEIVE,
1813                                               "Request",
1814                                               "fill",
1815                                               5);
1816            }
1817            if (actualBytesRead != -1)
1818            {
1819                count += actualBytesRead;
1820                totalBytesRead += actualBytesRead;
1821            }
1822
1823        }
1824        while ((totalBytesRead < minimumBytesNeeded) && (actualBytesRead != -1));
1825        if (actualBytesRead == -1)
1826        {
1827            if (totalBytesRead < minimumBytesNeeded)
1828            {
1829                agent.markCommunicationsFailure ("DDMReader.fill()",
1830                  "InputStream.read()", "insufficient data", "*");
1831            }
1832        }
1833    }
1834
1835    /**
1836     * Print a internal trace message
1837     */

1838    private void trace(String JavaDoc msg)
1839    {
1840        if (agent != null)
1841            agent.trace(msg);
1842    }
1843
1844    protected String JavaDoc toDebugString(String JavaDoc indent)
1845    {
1846        String JavaDoc s = indent + "***** DDMReader toDebugString ******\n";
1847        int buflen = 0;
1848        if (buffer != null)
1849            buflen = buffer.length;
1850       s += indent + "Reader buffer length = " + buffer.length + "\n";
1851       return s;
1852    }
1853
1854    /**
1855     * Return chaining bit for current DSS.
1856     */

1857    protected byte getCurrChainState() {
1858
1859        if (!dssIsChainedWithSameID && !dssIsChainedWithDiffID)
1860            return DssConstants.DSS_NOCHAIN;
1861
1862        if (dssIsChainedWithSameID)
1863            return DssConstants.DSSCHAIN_SAME_ID;
1864
1865        return DssConstants.DSSCHAIN;
1866
1867    }
1868
1869}
1870
Popular Tags