1 /* Copyright (c) 2001-2016, The HSQL Development Group
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * Redistributions of source code must retain the above copyright notice, this
8  * list of conditions and the following disclaimer.
9  *
10  * Redistributions in binary form must reproduce the above copyright notice,
11  * this list of conditions and the following disclaimer in the documentation
12  * and/or other materials provided with the distribution.
13  *
14  * Neither the name of the HSQL Development Group nor the names of its
15  * contributors may be used to endorse or promote products derived from this
16  * software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
22  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 
32 package org.hsqldb.result;
33 
34 import java.io.DataInput;
35 import java.io.IOException;
36 import java.io.InputStream;
37 import java.io.Reader;
38 
39 import org.hsqldb.SessionInterface;
40 import org.hsqldb.error.Error;
41 import org.hsqldb.error.ErrorCode;
42 import org.hsqldb.lib.DataOutputStream;
43 import org.hsqldb.lib.HsqlByteArrayOutputStream;
44 import org.hsqldb.rowio.RowOutputInterface;
45 
46 /**
47  * Sub-class of Result for communicating Blob and Clob operations.<p>
48  *
49  * @author Fred Toussi (fredt@users dot sourceforge.net)
50  * @version 2.0.1
51  * @since 1.9.0
52  */
53 public final class ResultLob extends Result {
54 
55     public interface LobResultTypes {
56 
57         int REQUEST_GET_BYTES                 = 1;
58         int REQUEST_SET_BYTES                 = 2;
59         int REQUEST_GET_CHARS                 = 3;
60         int REQUEST_SET_CHARS                 = 4;
61         int REQUEST_GET_BYTE_PATTERN_POSITION = 5;
62         int REQUEST_GET_CHAR_PATTERN_POSITION = 6;
63         int REQUEST_CREATE_BYTES              = 7;
64         int REQUEST_CREATE_CHARS              = 8;
65         int REQUEST_TRUNCATE                  = 9;
66         int REQUEST_GET_LENGTH                = 10;
67         int REQUEST_GET_LOB                   = 11;
68         int REQUEST_DUPLICATE_LOB             = 12;
69 
70         // non-network
71         int REQUEST_GET_TRUNCATE_LENGTH = 13;
72 
73         //
74         int RESPONSE_GET_BYTES                 = 21;
75         int RESPONSE_SET                       = 22;
76         int RESPONSE_GET_CHARS                 = 23;
77         int RESPONSE_GET_BYTE_PATTERN_POSITION = 25;
78         int RESPONSE_GET_CHAR_PATTERN_POSITION = 26;
79         int RESPONSE_CREATE_BYTES              = 27;
80         int RESPONSE_CREATE_CHARS              = 28;
81         int RESPONSE_TRUNCATE                  = 29;
82     }
83 
84     long        lobID;
85     int         subType;
86     long        blockOffset;
87     long        blockLength;
88     byte[]      byteBlock;
89     char[]      charBlock;
90     Reader      reader;
91     InputStream stream;
92 
ResultLob()93     private ResultLob() {
94         super(ResultConstants.LARGE_OBJECT_OP);
95     }
96 
newLobGetLengthRequest(long id)97     public static ResultLob newLobGetLengthRequest(long id) {
98 
99         ResultLob result = new ResultLob();
100 
101         result.subType = LobResultTypes.REQUEST_GET_LENGTH;
102         result.lobID   = id;
103 
104         return result;
105     }
106 
newLobGetBytesRequest(long id, long offset, int length)107     public static ResultLob newLobGetBytesRequest(long id, long offset,
108             int length) {
109 
110         ResultLob result = new ResultLob();
111 
112         result.subType     = LobResultTypes.REQUEST_GET_BYTES;
113         result.lobID       = id;
114         result.blockOffset = offset;
115         result.blockLength = length;
116 
117         return result;
118     }
119 
newLobGetCharsRequest(long id, long offset, int length)120     public static ResultLob newLobGetCharsRequest(long id, long offset,
121             int length) {
122 
123         ResultLob result = new ResultLob();
124 
125         result.subType     = LobResultTypes.REQUEST_GET_CHARS;
126         result.lobID       = id;
127         result.blockOffset = offset;
128         result.blockLength = length;
129 
130         return result;
131     }
132 
newLobSetBytesRequest(long id, long offset, byte[] block)133     public static ResultLob newLobSetBytesRequest(long id, long offset,
134             byte[] block) {
135 
136         ResultLob result = new ResultLob();
137 
138         result.subType     = LobResultTypes.REQUEST_SET_BYTES;
139         result.lobID       = id;
140         result.blockOffset = offset;
141         result.byteBlock   = block;
142         result.blockLength = block.length;
143 
144         return result;
145     }
146 
newLobSetCharsRequest(long id, long offset, char[] chars)147     public static ResultLob newLobSetCharsRequest(long id, long offset,
148             char[] chars) {
149 
150         ResultLob result = new ResultLob();
151 
152         result.subType     = LobResultTypes.REQUEST_SET_CHARS;
153         result.lobID       = id;
154         result.blockOffset = offset;
155         result.charBlock   = chars;
156         result.blockLength = chars.length;
157 
158         return result;
159     }
160 
newLobTruncateRequest(long id, long offset)161     public static ResultLob newLobTruncateRequest(long id, long offset) {
162 
163         ResultLob result = new ResultLob();
164 
165         result.subType     = LobResultTypes.REQUEST_TRUNCATE;
166         result.lobID       = id;
167         result.blockOffset = offset;
168 
169         return result;
170     }
171 
newLobGetBytesResponse(long id, long offset, byte[] block)172     public static ResultLob newLobGetBytesResponse(long id, long offset,
173             byte[] block) {
174 
175         ResultLob result = new ResultLob();
176 
177         result.subType     = LobResultTypes.RESPONSE_GET_BYTES;
178         result.lobID       = id;
179         result.blockOffset = offset;
180         result.byteBlock   = block;
181         result.blockLength = block.length;
182 
183         return result;
184     }
185 
newLobGetCharsResponse(long id, long offset, char[] chars)186     public static ResultLob newLobGetCharsResponse(long id, long offset,
187             char[] chars) {
188 
189         ResultLob result = new ResultLob();
190 
191         result.subType     = LobResultTypes.RESPONSE_GET_CHARS;
192         result.lobID       = id;
193         result.blockOffset = offset;
194         result.charBlock   = chars;
195         result.blockLength = chars.length;
196 
197         return result;
198     }
199 
newLobSetResponse(long id, long length)200     public static ResultLob newLobSetResponse(long id, long length) {
201 
202         ResultLob result = new ResultLob();
203 
204         result.subType     = LobResultTypes.RESPONSE_SET;
205         result.lobID       = id;
206         result.blockLength = length;
207 
208         return result;
209     }
210 
newLobGetBytePatternPositionRequest(long id, byte[] pattern, long offset)211     public static ResultLob newLobGetBytePatternPositionRequest(long id,
212             byte[] pattern, long offset) {
213 
214         ResultLob result = new ResultLob();
215 
216         result.subType     = LobResultTypes.REQUEST_GET_BYTE_PATTERN_POSITION;
217         result.lobID       = id;
218         result.blockOffset = offset;
219         result.byteBlock   = pattern;
220         result.blockLength = pattern.length;
221 
222         return result;
223     }
224 
newLobGetBytePatternPositionRequest(long id, long otherId, long offset)225     public static ResultLob newLobGetBytePatternPositionRequest(long id,
226             long otherId, long offset) {
227 
228         ResultLob result = new ResultLob();
229 
230         result.subType     = LobResultTypes.REQUEST_GET_BYTE_PATTERN_POSITION;
231         result.lobID       = id;
232         result.blockOffset = offset;
233 
234         return result;
235     }
236 
newLobGetCharPatternPositionRequest(long id, char[] pattern, long offset)237     public static ResultLob newLobGetCharPatternPositionRequest(long id,
238             char[] pattern, long offset) {
239 
240         ResultLob result = new ResultLob();
241 
242         result.subType     = LobResultTypes.REQUEST_GET_CHAR_PATTERN_POSITION;
243         result.lobID       = id;
244         result.blockOffset = offset;
245         result.charBlock   = pattern;
246         result.blockLength = pattern.length;
247 
248         return result;
249     }
250 
newLobGetCharPatternPositionRequest(long id, long otherId, long offset)251     public static ResultLob newLobGetCharPatternPositionRequest(long id,
252             long otherId, long offset) {
253 
254         ResultLob result = new ResultLob();
255 
256         result.subType     = LobResultTypes.REQUEST_GET_CHAR_PATTERN_POSITION;
257         result.lobID       = id;
258         result.blockOffset = offset;
259         result.blockLength = otherId;
260 
261         return result;
262     }
263 
newLobCreateBlobRequest(long sessionID, long lobID, InputStream stream, long length)264     public static ResultLob newLobCreateBlobRequest(long sessionID,
265             long lobID, InputStream stream, long length) {
266 
267         ResultLob result = new ResultLob();
268 
269         result.lobID       = lobID;
270         result.subType     = LobResultTypes.REQUEST_CREATE_BYTES;
271         result.blockLength = length;
272         result.stream      = stream;
273 
274         return result;
275     }
276 
newLobCreateClobRequest(long sessionID, long lobID, Reader reader, long length)277     public static ResultLob newLobCreateClobRequest(long sessionID,
278             long lobID, Reader reader, long length) {
279 
280         ResultLob result = new ResultLob();
281 
282         result.lobID       = lobID;
283         result.subType     = LobResultTypes.REQUEST_CREATE_CHARS;
284         result.blockLength = length;
285         result.reader      = reader;
286 
287         return result;
288     }
289 
newLobGetTruncateLength(long id)290     public static ResultLob newLobGetTruncateLength(long id) {
291 
292         ResultLob result = new ResultLob();
293 
294         result.subType = LobResultTypes.REQUEST_GET_TRUNCATE_LENGTH;
295         result.lobID   = id;
296 
297         return result;
298     }
299 
newLobCreateBlobResponse(long id)300     public static ResultLob newLobCreateBlobResponse(long id) {
301 
302         ResultLob result = new ResultLob();
303 
304         result.subType = LobResultTypes.RESPONSE_CREATE_BYTES;
305         result.lobID   = id;
306 
307         return result;
308     }
309 
newLobCreateClobResponse(long id)310     public static ResultLob newLobCreateClobResponse(long id) {
311 
312         ResultLob result = new ResultLob();
313 
314         result.subType = LobResultTypes.RESPONSE_CREATE_CHARS;
315         result.lobID   = id;
316 
317         return result;
318     }
319 
newLobTruncateResponse(long id, long length)320     public static ResultLob newLobTruncateResponse(long id, long length) {
321 
322         ResultLob result = new ResultLob();
323 
324         result.subType     = LobResultTypes.RESPONSE_TRUNCATE;
325         result.lobID       = id;
326         result.blockLength = length;
327 
328         return result;
329     }
330 
newLobGetRequest(long id, long offset, long length)331     public static ResultLob newLobGetRequest(long id, long offset,
332             long length) {
333 
334         ResultLob result = new ResultLob();
335 
336         result.subType     = LobResultTypes.REQUEST_GET_LOB;
337         result.lobID       = id;
338         result.blockOffset = offset;
339         result.blockLength = length;
340 
341         return result;
342     }
343 
newLobDuplicateRequest(long id)344     public static ResultLob newLobDuplicateRequest(long id) {
345 
346         ResultLob result = new ResultLob();
347 
348         result.subType = LobResultTypes.REQUEST_DUPLICATE_LOB;
349         result.lobID   = id;
350 
351         return result;
352     }
353 
newLob(DataInput dataInput, boolean readTerminate)354     public static ResultLob newLob(DataInput dataInput,
355                                    boolean readTerminate) throws IOException {
356 
357         ResultLob result = new ResultLob();
358 
359         result.databaseID = dataInput.readInt();
360         result.sessionID  = dataInput.readLong();
361         result.lobID      = dataInput.readLong();
362         result.subType    = dataInput.readInt();
363 
364         switch (result.subType) {
365 
366             case LobResultTypes.REQUEST_CREATE_BYTES :
367             case LobResultTypes.REQUEST_CREATE_CHARS :
368                 result.blockOffset = dataInput.readLong();
369                 result.blockLength = dataInput.readLong();
370                 break;
371 
372             case LobResultTypes.REQUEST_GET_LOB :
373             case LobResultTypes.REQUEST_DUPLICATE_LOB :
374 
375             //
376             case LobResultTypes.REQUEST_GET_BYTES :
377             case LobResultTypes.REQUEST_GET_CHARS :
378                 result.blockOffset = dataInput.readLong();
379                 result.blockLength = dataInput.readLong();
380                 break;
381 
382             case LobResultTypes.REQUEST_SET_BYTES :
383             case LobResultTypes.REQUEST_GET_BYTE_PATTERN_POSITION :
384                 result.blockOffset = dataInput.readLong();
385                 result.blockLength = dataInput.readLong();
386                 result.byteBlock   = new byte[(int) result.blockLength];
387 
388                 dataInput.readFully(result.byteBlock);
389                 break;
390 
391             case LobResultTypes.REQUEST_SET_CHARS :
392             case LobResultTypes.REQUEST_GET_CHAR_PATTERN_POSITION :
393                 result.blockOffset = dataInput.readLong();
394                 result.blockLength = dataInput.readLong();
395                 result.charBlock   = new char[(int) result.blockLength];
396 
397                 for (int i = 0; i < result.charBlock.length; i++) {
398                     result.charBlock[i] = dataInput.readChar();
399                 }
400                 break;
401 
402             case LobResultTypes.REQUEST_GET_LENGTH :
403             case LobResultTypes.REQUEST_TRUNCATE :
404                 result.blockOffset = dataInput.readLong();
405                 break;
406 
407             case LobResultTypes.RESPONSE_GET_BYTES :
408                 result.blockOffset = dataInput.readLong();
409                 result.blockLength = dataInput.readLong();
410                 result.byteBlock   = new byte[(int) result.blockLength];
411 
412                 dataInput.readFully(result.byteBlock);
413                 break;
414 
415             case LobResultTypes.RESPONSE_GET_CHARS :
416                 result.blockOffset = dataInput.readLong();
417                 result.blockLength = dataInput.readLong();
418                 result.charBlock   = new char[(int) result.blockLength];
419 
420                 for (int i = 0; i < result.charBlock.length; i++) {
421                     result.charBlock[i] = dataInput.readChar();
422                 }
423                 break;
424 
425             case LobResultTypes.RESPONSE_SET :
426             case LobResultTypes.RESPONSE_CREATE_BYTES :
427             case LobResultTypes.RESPONSE_CREATE_CHARS :
428             case LobResultTypes.RESPONSE_TRUNCATE :
429                 result.blockLength = dataInput.readLong();
430                 break;
431 
432             case LobResultTypes.RESPONSE_GET_BYTE_PATTERN_POSITION :
433             case LobResultTypes.RESPONSE_GET_CHAR_PATTERN_POSITION :
434                 result.blockOffset = dataInput.readLong();
435                 break;
436 
437             default :
438                 throw Error.runtimeError(ErrorCode.U_S0500, "ResultLob");
439         }
440 
441         if (readTerminate) {
442             dataInput.readByte();
443         }
444 
445         return result;
446     }
447 
write(SessionInterface session, DataOutputStream dataOut, RowOutputInterface rowOut)448     public void write(SessionInterface session, DataOutputStream dataOut,
449                       RowOutputInterface rowOut) throws IOException {
450 
451         writeBody(session, dataOut);
452         dataOut.writeByte(ResultConstants.NONE);
453         dataOut.flush();
454     }
455 
writeBody(SessionInterface session, DataOutputStream dataOut)456     public void writeBody(SessionInterface session,
457                           DataOutputStream dataOut) throws IOException {
458 
459         switch (subType) {
460 
461             case LobResultTypes.REQUEST_CREATE_BYTES :
462                 if (blockLength >= 0) {
463                     writeCreate(session, dataOut);
464 
465                     return;
466                 }
467 
468                 writeCreateByteSegments(session, dataOut);
469 
470                 return;
471 
472             case LobResultTypes.REQUEST_CREATE_CHARS : {
473                 if (blockLength >= 0) {
474                     writeCreate(session, dataOut);
475 
476                     return;
477                 }
478 
479                 writeCreateCharSegments(session, dataOut);
480 
481                 return;
482             }
483         }
484 
485         dataOut.writeByte(mode);
486         dataOut.writeInt(databaseID);
487         dataOut.writeLong(sessionID);
488         dataOut.writeLong(lobID);
489         dataOut.writeInt(subType);
490 
491         switch (subType) {
492 
493             case LobResultTypes.REQUEST_SET_BYTES :
494             case LobResultTypes.REQUEST_GET_BYTE_PATTERN_POSITION :
495                 dataOut.writeLong(blockOffset);
496                 dataOut.writeLong(blockLength);
497                 dataOut.write(byteBlock);
498                 break;
499 
500             case LobResultTypes.REQUEST_SET_CHARS :
501             case LobResultTypes.REQUEST_GET_CHAR_PATTERN_POSITION :
502                 dataOut.writeLong(blockOffset);
503                 dataOut.writeLong(blockLength);
504                 dataOut.writeChars(charBlock);
505                 break;
506 
507             case LobResultTypes.REQUEST_GET_LOB :
508             case LobResultTypes.REQUEST_DUPLICATE_LOB :
509 
510             //
511             case LobResultTypes.REQUEST_GET_BYTES :
512             case LobResultTypes.REQUEST_GET_CHARS :
513                 dataOut.writeLong(blockOffset);
514                 dataOut.writeLong(blockLength);
515                 break;
516 
517             case LobResultTypes.REQUEST_GET_LENGTH :
518             case LobResultTypes.REQUEST_TRUNCATE :
519                 dataOut.writeLong(blockOffset);
520                 break;
521 
522             case LobResultTypes.RESPONSE_GET_BYTES :
523                 dataOut.writeLong(blockOffset);
524                 dataOut.writeLong(blockLength);
525                 dataOut.write(byteBlock);
526                 break;
527 
528             case LobResultTypes.RESPONSE_GET_CHARS :
529                 dataOut.writeLong(blockOffset);
530                 dataOut.writeLong(blockLength);
531                 dataOut.writeChars(charBlock);
532                 break;
533 
534             case LobResultTypes.RESPONSE_SET :
535             case LobResultTypes.RESPONSE_CREATE_BYTES :
536             case LobResultTypes.RESPONSE_CREATE_CHARS :
537             case LobResultTypes.RESPONSE_TRUNCATE :
538                 dataOut.writeLong(blockLength);
539                 break;
540 
541             case LobResultTypes.RESPONSE_GET_BYTE_PATTERN_POSITION :
542             case LobResultTypes.RESPONSE_GET_CHAR_PATTERN_POSITION :
543                 dataOut.writeLong(blockOffset);
544                 break;
545 
546             default :
547                 throw Error.runtimeError(ErrorCode.U_S0500, "ResultLob");
548         }
549     }
550 
writeCreate(SessionInterface session, DataOutputStream dataOut)551     private void writeCreate(SessionInterface session,
552                              DataOutputStream dataOut) throws IOException {
553 
554         dataOut.writeByte(mode);
555         dataOut.writeInt(databaseID);
556         dataOut.writeLong(sessionID);
557         dataOut.writeLong(lobID);
558         dataOut.writeInt(subType);
559         dataOut.writeLong(blockOffset);
560         dataOut.writeLong(blockLength);
561 
562         switch (subType) {
563 
564             case LobResultTypes.REQUEST_CREATE_BYTES :
565                 dataOut.write(stream, blockLength);
566                 break;
567 
568             case LobResultTypes.REQUEST_CREATE_CHARS :
569                 dataOut.write(reader, blockLength);
570                 break;
571         }
572     }
573 
writeCreateByteSegments(SessionInterface session, DataOutputStream dataOut)574     private void writeCreateByteSegments(SessionInterface session,
575                                          DataOutputStream dataOut)
576                                          throws IOException {
577 
578         //
579         int  bufferLength  = session.getStreamBlockSize();
580         long currentOffset = blockOffset;
581 
582         dataOut.writeByte(mode);
583         dataOut.writeInt(databaseID);
584         dataOut.writeLong(sessionID);
585         dataOut.writeLong(lobID);
586         dataOut.writeInt(subType);
587 
588         HsqlByteArrayOutputStream byteArrayOS =
589             new HsqlByteArrayOutputStream(bufferLength);
590 
591         byteArrayOS.reset();
592         byteArrayOS.write(stream, bufferLength);
593         dataOut.writeLong(currentOffset);
594         dataOut.writeLong(byteArrayOS.size());
595         dataOut.write(byteArrayOS.getBuffer(), 0, byteArrayOS.size());
596 
597         currentOffset += byteArrayOS.size();
598 
599         if (byteArrayOS.size() < bufferLength) {
600             return;
601         }
602 
603         //
604         while (true) {
605             byteArrayOS.reset();
606             byteArrayOS.write(stream, bufferLength);
607 
608             if (byteArrayOS.size() == 0) {
609                 break;
610             }
611 
612             //
613             dataOut.writeByte(mode);
614             dataOut.writeInt(databaseID);
615             dataOut.writeLong(sessionID);
616             dataOut.writeLong(lobID);
617             dataOut.writeInt(LobResultTypes.REQUEST_SET_BYTES);
618             dataOut.writeLong(currentOffset);
619             dataOut.writeLong(byteArrayOS.size());
620             dataOut.write(byteArrayOS.getBuffer(), 0, byteArrayOS.size());
621 
622             currentOffset += byteArrayOS.size();
623 
624             if (byteArrayOS.size() < bufferLength) {
625                 break;
626             }
627         }
628     }
629 
writeCreateCharSegments(SessionInterface session, DataOutputStream dataOut)630     private void writeCreateCharSegments(SessionInterface session,
631                                          DataOutputStream dataOut)
632                                          throws IOException {
633 
634         //
635         int  bufferLength  = session.getStreamBlockSize();
636         long currentOffset = blockOffset;
637 
638         dataOut.writeByte(mode);
639         dataOut.writeInt(databaseID);
640         dataOut.writeLong(sessionID);
641         dataOut.writeLong(lobID);
642         dataOut.writeInt(subType);
643 
644         HsqlByteArrayOutputStream byteArrayOS =
645             new HsqlByteArrayOutputStream(bufferLength);
646 
647         byteArrayOS.reset();
648         byteArrayOS.write(reader, bufferLength / 2);
649 
650         //
651         dataOut.writeLong(currentOffset);
652         dataOut.writeLong(byteArrayOS.size() / 2);
653         dataOut.write(byteArrayOS.getBuffer(), 0, byteArrayOS.size());
654 
655         currentOffset += byteArrayOS.size() / 2;
656 
657         if (byteArrayOS.size() < bufferLength) {
658             return;
659         }
660 
661         //
662         while (true) {
663             byteArrayOS.reset();
664             byteArrayOS.write(reader, bufferLength / 2);
665 
666             if (byteArrayOS.size() == 0) {
667                 break;
668             }
669 
670             //
671             dataOut.writeByte(mode);
672             dataOut.writeInt(databaseID);
673             dataOut.writeLong(sessionID);
674             dataOut.writeLong(lobID);
675             dataOut.writeInt(LobResultTypes.REQUEST_SET_CHARS);
676             dataOut.writeLong(currentOffset);
677             dataOut.writeLong(byteArrayOS.size() / 2);
678             dataOut.write(byteArrayOS.getBuffer(), 0, byteArrayOS.size());
679 
680             currentOffset += byteArrayOS.size() / 2;
681 
682             if (byteArrayOS.size() < bufferLength) {
683                 break;
684             }
685         }
686     }
687 
getLobID()688     public long getLobID() {
689         return lobID;
690     }
691 
getSubType()692     public int getSubType() {
693         return subType;
694     }
695 
getOffset()696     public long getOffset() {
697         return blockOffset;
698     }
699 
getBlockLength()700     public long getBlockLength() {
701         return blockLength;
702     }
703 
getByteArray()704     public byte[] getByteArray() {
705         return byteBlock;
706     }
707 
getCharArray()708     public char[] getCharArray() {
709         return charBlock;
710     }
711 
getInputStream()712     public InputStream getInputStream() {
713         return stream;
714     }
715 
getReader()716     public Reader getReader() {
717         return reader;
718     }
719 }
720