KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > impl > jdbc > EmbedBlob


1 /*
2
3    Derby - Class org.apache.derby.impl.jdbc.EmbedBlob
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
23 package org.apache.derby.impl.jdbc;
24
25 import org.apache.derby.iapi.reference.SQLState;
26 import org.apache.derby.iapi.error.StandardException;
27 import org.apache.derby.iapi.services.sanity.SanityManager;
28 import org.apache.derby.iapi.types.DataValueDescriptor;
29 import org.apache.derby.iapi.types.Resetable;
30 import org.apache.derby.impl.jdbc.ConnectionChild;
31 import org.apache.derby.impl.jdbc.EmbedConnection;
32 import org.apache.derby.impl.jdbc.Util;
33 import org.apache.derby.iapi.services.io.NewByteArrayInputStream;
34 import org.apache.derby.iapi.services.io.InputStreamUtil;
35 import org.apache.derby.iapi.services.io.ArrayInputStream;
36
37 import java.sql.SQLException JavaDoc;
38 import java.sql.Blob JavaDoc;
39 import java.io.InputStream JavaDoc;
40 import java.io.EOFException JavaDoc;
41 import java.io.IOException JavaDoc;
42
43 /**
44     Implements java.sql.Blob (see the JDBC 2.0 spec).
45     A blob sits on top of a BINARY, VARBINARY or LONG VARBINARY column.
46     If its data is small (less than 1 page) it is a byte array taken from
47     the SQLBit class. If it is large (more than 1 page) it is a long column
48     in the database. The long column is accessed as a stream, and is implemented
49     in store as an OverflowInputStream. The Resetable interface allows sending
50     messages to that stream to initialize itself (reopen its container and
51     lock the corresponding row) and to reset itself to the beginning.
52
53     NOTE: In the case that the data is large, it is represented as a stream.
54     This stream is returned to the user in the getBinaryStream() method.
55     This means that we have limited control over the state of the stream,
56     since the user can read bytes from it at any time. Thus all methods
57     here reset the stream to the beginning before doing any work.
58     CAVEAT: The methods may not behave correctly if a user sets up
59     multiple threads and sucks data from the stream (returned from
60     getBinaryStream()) at the same time as calling the Blob methods.
61
62   <P><B>Supports</B>
63    <UL>
64    <LI> JSR169 - no subsetting for java.sql.Blob
65    <LI> JDBC 2.0
66    <LI> JDBC 3.0 - no new dependencies on new JDBC 3.0 or JDK 1.4 classes,
67         new update methods can safely be added into implementation.
68    </UL>
69
70  */

71
72 final class EmbedBlob extends ConnectionChild implements Blob JavaDoc
73 {
74     // blob is either bytes or stream
75
private boolean isBytes;
76     private InputStream myStream;
77     
78     /*
79      * Length of the BLOB if known. Set to -1 if
80      * the current length of the BLOB is not known.
81      */

82     private long myLength = -1;
83     
84     private byte[] myBytes;
85     // note: cannot control position of the stream since user can do a getBinaryStream
86
private long pos;
87     // this stream sits on top of myStream
88
private BinaryToRawStream biStream;
89
90     // buffer for reading in blobs from a stream (long column)
91
// and trashing them (to set the position of the stream etc.)
92
private static int BLOB_BUF_SIZE = 4096;
93     private byte buf[];
94     
95     //This boolean variable indicates whether the Blob object has
96
//been invalidated by calling free() on it
97
private boolean isValid = true;
98
99      /**
100      * This constructor is used to create a empty Blob object. It is used by the
101      * Connection interface method createBlob().
102      *
103      * @param blobBytes A byte array containing the data to be stores in the
104      * Blob.
105      *
106      * @param con The EmbedConnection object associated with this Blob object.
107      *
108      */

109     
110      EmbedBlob(byte [] blobBytes,EmbedConnection con) {
111          super(con);
112          myBytes = blobBytes;
113          isBytes = true;
114          myLength = myBytes.length;
115      }
116      
117     /*
118       This constructor should only be called by EmbedResultSet.getBlob
119     */

120     protected EmbedBlob(DataValueDescriptor dvd, EmbedConnection con)
121         throws StandardException
122     {
123         super(con);
124         // if the underlying column is null, ResultSet.getBlob will return null,
125
// never should get this far
126
if (SanityManager.DEBUG)
127             SanityManager.ASSERT(!dvd.isNull(), "blob is created on top of a null column");
128
129         myStream = dvd.getStream();
130         if (myStream == null)
131         {
132             isBytes = true;
133             // copy bytes into memory so that blob can live after result set
134
// is closed
135
byte[] dvdBytes = dvd.getBytes();
136
137             if (SanityManager.DEBUG)
138                 SanityManager.ASSERT(dvdBytes != null,"blob has a null value underneath");
139
140             myLength = dvdBytes.length;
141             myBytes = new byte[dvdBytes.length];
142             System.arraycopy(dvdBytes, 0, myBytes, 0, dvdBytes.length);
143         }
144         else
145         {
146             isBytes = false;
147
148             /*
149              We are expecting this stream to be a FormatIdInputStream with an
150              OverflowInputStream inside. FormatIdInputStream implements
151              Resetable. This should be the case when retrieving
152              data from a long column. However, SQLBit, which is the class
153              implementing the getStream() method for dvd.getStream(), does not
154              guarantee this for us
155              */

156             if (SanityManager.DEBUG)
157                 SanityManager.ASSERT(myStream instanceof Resetable);
158
159             try {
160                 ((Resetable) myStream).initStream();
161             } catch (StandardException se) {
162                 if (se.getMessageId().equals(SQLState.DATA_CONTAINER_CLOSED)) {
163                     throw StandardException
164                             .newException(SQLState.BLOB_ACCESSED_AFTER_COMMIT);
165                 }
166             }
167             // set up the buffer for trashing the bytes to set the position of
168
// the
169
// stream, only need a buffer when we have a long column
170
buf = new byte[BLOB_BUF_SIZE];
171         }
172         pos = 0;
173     }
174
175
176     /*
177         Sets the position of the stream to position newPos, where position 0 is
178         the beginning of the stream.
179
180         @param newPos the position to set to
181         @exception StandardException (BLOB_SETPOSITION_FAILED) throws this if
182         the stream runs out before we get to newPos
183     */

184     private void setPosition(long newPos)
185         throws StandardException, IOException JavaDoc
186     {
187         if (SanityManager.DEBUG)
188             SanityManager.ASSERT(newPos >= 0);
189         if (isBytes)
190             pos = newPos;
191         else
192         {
193             // Always resets the stream to the beginning first, because user can
194
// influence the state of the stream without letting us know.
195
((Resetable)myStream).resetStream();
196             // PT could try to save creating a new object each time
197
biStream = new BinaryToRawStream(myStream, this);
198             pos = 0;
199             while (pos < newPos)
200             {
201                 int size = biStream.read(
202                     buf,0,(int) Math.min((newPos-pos), (long) BLOB_BUF_SIZE));
203                 if (size <= 0) // ran out of stream
204
throw StandardException.newException(SQLState.BLOB_LENGTH_TOO_LONG);
205                 pos += size;
206             }
207         }
208     }
209
210
211     /*
212         Reads one byte, either from the byte array or else from the stream.
213     */

214     private int read()
215         throws IOException JavaDoc
216     {
217         int c;
218         if (isBytes)
219         {
220             if (pos >= myBytes.length)
221                 return -1;
222             else
223                 c = myBytes[(int) pos];
224         }
225         else
226             c = biStream.read();
227         pos++;
228         return c;
229     }
230
231   /**
232    * Returns the number of bytes in the <code>BLOB</code> value
233    * designated by this <code>Blob</code> object.
234    * @return length of the <code>BLOB</code> in bytes
235    * @exception SQLException if there is an error accessing the
236    * length of the <code>BLOB</code>
237    */

238     // PT stream part may get pushed to store
239
public long length()
240         throws SQLException JavaDoc
241     {
242         //call checkValidity to exit by throwing a SQLException if
243
//the Blob object has been freed by calling free() on it
244
checkValidity();
245         
246         if (myLength != -1)
247             return myLength;
248         
249         boolean pushStack = false;
250         try
251         {
252            // we have a stream
253
synchronized (getConnectionSynchronization())
254             {
255                 pushStack = !getEmbedConnection().isClosed();
256                 if (pushStack)
257                     setupContextStack();
258
259                 setPosition(0);
260                 // If possible get the length from the encoded
261
// length at the front of the raw stream.
262
if ((myLength = biStream.getLength()) != -1) {
263                     biStream.close();
264                    return myLength;
265                 }
266                 
267                 // Otherwise have to read the entire stream!
268
for (;;)
269                 {
270                     int size = biStream.read(buf);
271                     if (size == -1)
272                         break;
273                     pos += size;
274                 }
275                 // Save for future uses.
276
myLength = pos;
277                 biStream.close();
278                 return pos;
279             }
280         }
281         catch (Throwable JavaDoc t)
282         {
283             throw handleMyExceptions(t);
284         }
285         finally
286         {
287             if (pushStack)
288                 restoreContextStack();
289         }
290     }
291
292
293   /**
294    * Returns as an array of bytes part or all of the <code>BLOB</code>
295    * value that this <code>Blob</code> object designates. The byte
296    * array contains up to <code>length</code> consecutive bytes
297    * starting at position <code>startPos</code>.
298    * The starting position must be between 1 and the length
299    * of the BLOB plus 1. This allows for zero-length BLOB values, from
300    * which only zero-length byte arrays can be returned.
301    * If a larger length is requested than there are bytes available,
302    * characters from the start position to the end of the BLOB are returned.
303    * @param startPos the ordinal position of the first byte in the
304    * <code>BLOB</code> value to be extracted; the first byte is at
305    * position 1
306    * @param length is the number of consecutive bytes to be copied
307    * @return a byte array containing up to <code>length</code>
308    * consecutive bytes from the <code>BLOB</code> value designated
309    * by this <code>Blob</code> object, starting with the
310    * byte at position <code>startPos</code>.
311    * @exception SQLException if there is an error accessing the
312    * <code>BLOB</code>
313    * NOTE: If the starting position is the length of the BLOB plus 1,
314    * zero bytess are returned regardless of the length requested.
315    */

316     public byte[] getBytes(long startPos, int length)
317         throws SQLException JavaDoc
318     {
319         //call checkValidity to exit by throwing a SQLException if
320
//the Blob object has been freed by calling free() on it
321
checkValidity();
322         
323         boolean pushStack = false;
324         try
325         {
326             if (startPos < 1)
327                 throw StandardException.newException(
328                     SQLState.BLOB_BAD_POSITION, new Long JavaDoc(startPos));
329             if (length < 0)
330                 throw StandardException.newException(
331                     SQLState.BLOB_NONPOSITIVE_LENGTH, new Integer JavaDoc(length));
332
333             byte[] result;
334             // if we have a byte array, not a stream
335
if (isBytes)
336             {
337                 // if blob length is less than pos bytes + 1, raise an exception
338
if (myBytes.length + 1 < startPos)
339                     throw StandardException.newException(
340                         SQLState.BLOB_POSITION_TOO_LARGE, new Long JavaDoc(startPos));
341                 // cannot go over length of array
342
int lengthFromPos = myBytes.length - (int) startPos + 1;
343                 int actualLength = length > lengthFromPos ? lengthFromPos : length;
344                 result = new byte[actualLength];
345                 System.arraycopy(myBytes, ((int) startPos) - 1, result, 0, actualLength);
346             }
347             else // we have a stream
348
{
349                 synchronized (getConnectionSynchronization())
350                 {
351                     pushStack = !getEmbedConnection().isClosed();
352                     if (pushStack)
353                         setupContextStack();
354
355                     setPosition(startPos-1);
356                     // read length bytes into a string
357
result = new byte[length];
358                     int n = InputStreamUtil.readLoop(biStream,result,0,length);
359                     pos += n;
360                     /*
361                      According to the spec, if there are only n < length bytes
362                      to return, we should just return these bytes. Rather than
363                      return them in an array of size length, where the trailing
364                      bytes are not initialized, and the user cannot tell how
365                      many bytes were actually returned, we should return an
366                      array of n bytes.
367                      */

368                     if (n < length)
369                     {
370                         byte[] result2 = new byte[n];
371                         System.arraycopy(result,0,result2,0,n);
372                         return result2;
373                     }
374                 }
375             }
376             return result;
377         }
378         catch (StandardException e)
379         { // if this is a setPosition exception then we ran out of Blob
380
if (e.getMessageId().equals(SQLState.BLOB_LENGTH_TOO_LONG))
381                 e = StandardException.newException(
382                     SQLState.BLOB_POSITION_TOO_LARGE, new Long JavaDoc(startPos));
383             throw handleMyExceptions(e);
384         }
385         catch (Throwable JavaDoc t)
386         {
387             throw handleMyExceptions(t);
388         }
389         finally
390         {
391             if (pushStack)
392                 restoreContextStack();
393         }
394
395     }
396
397
398   /**
399    * Retrieves the <code>BLOB</code> designated by this
400    * <code>Blob</code> instance as a stream.
401    * @return a stream containing the <code>BLOB</code> data
402    * @exception SQLException if there is an error accessing the
403    * <code>BLOB</code>
404    */

405     public java.io.InputStream JavaDoc getBinaryStream()
406         throws SQLException JavaDoc
407     {
408         //call checkValidity to exit by throwing a SQLException if
409
//the Blob object has been freed by calling free() on it
410
checkValidity();
411         
412         boolean pushStack = false;
413         try
414         {
415             // if we have byte array, not a stream
416
if (isBytes)
417             {
418                 return new NewByteArrayInputStream(myBytes);
419             }
420             else
421             {
422                 // have a stream
423

424                 synchronized (getConnectionSynchronization())
425                 {
426                     pushStack = !getEmbedConnection().isClosed();
427                     if (pushStack)
428                         setupContextStack();
429
430                     setPosition(0);
431                     return biStream;
432                 }
433             }
434         }
435         catch (Throwable JavaDoc t)
436         {
437             throw handleMyExceptions(t);
438         }
439         finally
440         {
441             if (pushStack)
442                 restoreContextStack();
443         }
444     }
445
446
447   /**
448    * Determines the byte position at which the specified byte
449    * <code>pattern</code> begins within the <code>BLOB</code>
450    * value that this <code>Blob</code> object represents. The
451    * search for <code>pattern</code. begins at position
452    * <code>start</code>
453    * @param pattern the byte array for which to search
454    * @param start the position at which to begin searching; the
455    * first position is 1
456    * @return the position at which the pattern appears, else -1.
457    * @exception SQLException if there is an error accessing the
458    * <code>BLOB</code>
459    */

460     public long position(byte[] pattern, long start)
461         throws SQLException JavaDoc
462     {
463         //call checkValidity to exit by throwing a SQLException if
464
//the Blob object has been freed by calling free() on it
465
checkValidity();
466         
467         boolean pushStack = false;
468         try
469         {
470             if (start < 1)
471                 throw StandardException.newException(
472                     SQLState.BLOB_BAD_POSITION, new Long JavaDoc(start));
473             if (pattern == null)
474                 throw StandardException.newException(SQLState.BLOB_NULL_PATTERN_OR_SEARCH_STR);
475             if (pattern.length == 0)
476                 return start; // match DB2's SQL LOCATE function
477

478             synchronized (getConnectionSynchronization())
479             {
480                 pushStack = !getEmbedConnection().isClosed();
481                 if (pushStack)
482                     setupContextStack();
483
484                 setPosition(start-1);
485                 // look for first character
486
int lookFor = pattern[0];
487                 long curPos;
488                 int c;
489                 while (true)
490                 {
491                     c = read();
492                     if (c == -1) // run out of stream
493
return -1;
494                     if (c == lookFor)
495                     {
496                         curPos = pos;
497                         if (checkMatch(pattern))
498                             return curPos;
499                         else
500                             setPosition(curPos);
501                     }
502                 }
503             }
504         }
505         catch (StandardException e)
506         { // if this is a setPosition exception then not found
507
if (e.getMessageId().equals(SQLState.BLOB_LENGTH_TOO_LONG))
508                 return -1;
509             else
510                 throw handleMyExceptions(e);
511         }
512         catch (Throwable JavaDoc t)
513         {
514             throw handleMyExceptions(t);
515         }
516         finally
517         {
518             if (pushStack)
519                 restoreContextStack();
520         }
521
522     }
523
524
525     /*
526      check whether pattern (starting from the second byte) appears inside
527      posStream (at the current position)
528      @param posStream the stream to search inside
529      @param pattern the byte array passed in by the user to search with
530      @return true if match, false otherwise
531      */

532     private boolean checkMatch(byte[] pattern)
533         throws IOException JavaDoc
534     {
535        // check whether rest matches
536
// might improve performance by reading more
537
for (int i = 1; i < pattern.length; i++)
538         {
539             int b = read();
540             if ((b < 0) || (b != pattern[i])) // mismatch or stream runs out
541
return false;
542         }
543         return true;
544     }
545
546   /**
547    * Determines the byte position in the <code>BLOB</code> value
548    * designated by this <code>Blob</code> object at which
549    * <code>pattern</code> begins. The search begins at position
550    * <code>start</code>.
551    * @param pattern the <code>Blob</code> object designating
552    * the <code>BLOB</code> value for which to search
553    * @param start the position in the <code>BLOB</code> value
554    * at which to begin searching; the first position is 1
555    * @return the position at which the pattern begins, else -1
556    * @exception SQLException if there is an error accessing the
557    * <code>BLOB</code>
558    */

559     public long position(Blob JavaDoc pattern, long start)
560         throws SQLException JavaDoc
561     {
562         //call checkValidity to exit by throwing a SQLException if
563
//the Blob object has been freed by calling free() on it
564
checkValidity();
565         
566         boolean pushStack = false;
567         try
568         {
569             if (start < 1)
570                 throw StandardException.newException(
571                     SQLState.BLOB_BAD_POSITION, new Long JavaDoc(start));
572             if (pattern == null)
573                 throw StandardException.newException(SQLState.BLOB_NULL_PATTERN_OR_SEARCH_STR);
574             synchronized (getConnectionSynchronization())
575             {
576                 pushStack = !getEmbedConnection().isClosed();
577                 if (pushStack)
578                     setupContextStack();
579
580                 setPosition(start-1);
581                 // look for first character
582
byte[] b;
583                 try
584                 { // pattern is not necessarily a cloudscape Blob
585
b = pattern.getBytes(1,1);
586                 }
587                 catch (SQLException JavaDoc e)
588                 {
589                     throw StandardException.newException(SQLState.BLOB_UNABLE_TO_READ_PATTERN);
590                 }
591                 if (b == null || b.length < 1) // the 'empty' blob
592
return start; // match DB2's SQL LOCATE function
593
int lookFor = b[0];
594                 int c;
595                 long curPos;
596                 while (true)
597                 {
598                     c = read();
599                     if (c == -1) // run out of stream
600
return -1;
601                     if (c == lookFor)
602                     {
603                         curPos = pos;
604                         if (checkMatch(pattern))
605                             return curPos;
606                         else
607                             setPosition(curPos);
608                     }
609                 }
610             }
611         }
612         catch (StandardException e)
613         { // if this is a setPosition exception then not found
614
if (e.getMessageId().equals(SQLState.BLOB_LENGTH_TOO_LONG))
615                 return -1;
616             else
617                 throw handleMyExceptions(e);
618         }
619         catch (Throwable JavaDoc t)
620         {
621             throw handleMyExceptions(t);
622         }
623         finally
624         {
625             if (pushStack)
626                 restoreContextStack();
627         }
628
629     }
630
631
632     /*
633      check whether pattern (starting from the second byte) appears inside
634      posStream (at the current position)
635      @param posStream the stream to search inside
636      @param pattern the blob passed in by the user to search with
637      @return true if match, false otherwise
638      */

639     private boolean checkMatch(Blob JavaDoc pattern)
640         throws IOException JavaDoc
641     {
642         // check whether rest matches
643
// might improve performance by reading buffer at a time
644
InputStream pStream;
645         try
646         {
647             pStream = pattern.getBinaryStream();
648         }
649         catch (SQLException JavaDoc e)
650         {
651             return false;
652         }
653         if (pStream == null)
654             return false;
655         // throw away first character since we already read it in the calling
656
// method
657
int b1 = pStream.read();
658         if (b1 < 0)
659             return false;
660         while (true)
661         {
662             b1 = pStream.read();
663             if (b1 < 0) // search blob runs out
664
return true;
665             int b2 = read();
666             if ((b1 != b2) || (b2 < 0)) // mismatch or stream runs out
667
return false;
668         }
669     }
670
671     /*
672       Convert exceptions where needed before calling handleException to convert
673       them to SQLExceptions.
674     */

675     private SQLException JavaDoc handleMyExceptions(Throwable JavaDoc t)
676         throws SQLException JavaDoc
677     {
678         if (t instanceof StandardException)
679         {
680             // container closed means the blob or clob was accessed after commit
681
if (((StandardException) t).getMessageId().equals(SQLState.DATA_CONTAINER_CLOSED))
682             {
683                 t = StandardException.newException(SQLState.BLOB_ACCESSED_AFTER_COMMIT);
684             }
685         }
686         return handleException(t);
687     }
688
689
690    /*
691     If we have a stream, release the resources associated with it.
692     */

693     protected void finalize()
694     {
695         if (!isBytes)
696             ((Resetable)myStream).closeStream();
697     }
698
699     /**
700     Following methods are for the new JDBC 3.0 methods in java.sql.Blob
701     (see the JDBC 3.0 spec). We have the JDBC 3.0 methods in Local20
702     package, so we don't have to have a new class in Local30.
703     The new JDBC 3.0 methods don't make use of any new JDBC3.0 classes and
704     so this will work fine in jdbc2.0 configuration.
705     */

706
707     /////////////////////////////////////////////////////////////////////////
708
//
709
// JDBC 3.0 - New public methods
710
//
711
/////////////////////////////////////////////////////////////////////////
712

713     /**
714     * JDBC 3.0
715     *
716     * Writes the given array of bytes to the BLOB value that this Blob object
717     * represents, starting at position pos, and returns the number of bytes written.
718     *
719     * @param pos - the position in the BLOB object at which to start writing
720     * @param bytes - the array of bytes to be written to the BLOB value that this
721     * Blob object represents
722     * @return the number of bytes written
723     * @exception SQLException Feature not implemented for now.
724     */

725     public int setBytes(long pos,
726                     byte[] bytes)
727     throws SQLException JavaDoc
728     {
729         throw Util.notImplemented();
730     }
731
732     /**
733     * JDBC 3.0
734     *
735     * Writes all or part of the given array of byte array to the BLOB value that
736     * this Blob object represents and returns the number of bytes written.
737     * Writing starts at position pos in the BLOB value; len bytes from the given
738     * byte array are written.
739     *
740     * @param pos - the position in the BLOB object at which to start writing
741     * @param bytes - the array of bytes to be written to the BLOB value that this
742     * Blob object represents
743     * @param offset - the offset into the array bytes at which to start reading
744     * the bytes to be set
745     * @param len - the number of bytes to be written to the BLOB value from the
746     * array of bytes bytes
747     * @return the number of bytes written
748     * @exception SQLException Feature not implemented for now.
749     */

750     public int setBytes(long pos,
751                     byte[] bytes, int offset,
752                     int len)
753     throws SQLException JavaDoc
754     {
755         throw Util.notImplemented();
756     }
757
758     /**
759     * JDBC 3.0
760     *
761     * Retrieves a stream that can be used to write to the BLOB value that this
762     * Blob object represents. The stream begins at position pos.
763     *
764     * @param pos - the position in the BLOB object at which to start writing
765     * @return a java.io.OutputStream object to which data can be written
766     * @exception SQLException Feature not implemented for now.
767     */

768     public java.io.OutputStream JavaDoc setBinaryStream(long pos)
769     throws SQLException JavaDoc
770     {
771         throw Util.notImplemented();
772     }
773
774     /**
775     * JDBC 3.0
776     *
777     * Truncates the BLOB value that this Blob object represents to be len bytes
778     * in length.
779     *
780     * @param len - the length, in bytes, to which the BLOB value that this Blob
781     * object represents should be truncated
782     * @exception SQLException Feature not implemented for now.
783     */

784     public void truncate(long len)
785     throws SQLException JavaDoc
786     {
787         throw Util.notImplemented();
788     }
789
790     /////////////////////////////////////////////////////////////////////////
791
//
792
// JDBC 4.0 - New public methods
793
//
794
/////////////////////////////////////////////////////////////////////////
795
/**
796      * This method frees the <code>Blob</code> object and releases the resources that
797      * it holds. The object is invalid once the <code>free</code>
798      * method is called. If <code>free</code> is called multiple times, the subsequent
799      * calls to <code>free</code> are treated as a no-op.
800      *
801      * @throws SQLException if an error occurs releasing
802      * the Blob's resources
803      */

804     public void free()
805         throws SQLException JavaDoc {
806         //calling free() on a already freed object is treated as a no-op
807
if (!isValid) return;
808         
809         //now that free has been called the Blob object is no longer
810
//valid
811
isValid = false;
812         
813         //initialialize length to default value -1
814
myLength = -1;
815         
816         //if it is a stream then close it.
817
//if a array of bytes then initialize it to null
818
//to free up space
819
if (!isBytes)
820             ((Resetable)myStream).closeStream();
821         else
822             myBytes = null;
823     }
824     
825     /**
826      * Returns an <code>InputStream</code> object that contains a partial
827      * <code>Blob</code> value, starting with the byte specified by pos,
828      * which is length bytes in length.
829      *
830      * @param pos the offset to the first byte of the partial value to be
831      * retrieved. The first byte in the <code>Blob</code> is at
832      * position 1
833      * @param length the length in bytes of the partial value to be retrieved
834      * @return through which the partial <code>Blob</code> value can be read.
835      * @throws SQLException if pos is less than 1 or if pos is greater than
836      * the number of bytes in the <code>Blob</code> or if pos + length is
837      * greater than the number of bytes in the <code>Blob</code>
838      */

839     public InputStream getBinaryStream(long pos, long length)
840         throws SQLException JavaDoc {
841         throw Util.notImplemented();
842     }
843     
844     /*
845      * Checks is isValid is true. If it is not true throws
846      * a SQLException stating that a method has been called on
847      * an invalid LOB object
848      *
849      * throws SQLException if isvalid is not true.
850      */

851     private void checkValidity() throws SQLException JavaDoc{
852         if(!isValid)
853             throw newSQLException(SQLState.LOB_OBJECT_INVALID);
854     }
855 }
856
Popular Tags