64 /** 65 * The internal representation of the <code>Blob</code> object on which this 66 * <code>SerialBlob</code> object is based. 67 */ 68 private Blob blob; 69 70 /** 71 * The number of bytes in this <code>SerialBlob</code> object's 72 * array of bytes. 73 * @serial 74 */ 75 private long len; 76 77 /** 78 * The orginal number of bytes in this <code>SerialBlob</code> object's 79 * array of bytes when it was first established. 80 * @serial 81 */ 82 private long origLen; 83 84 /** 85 * Constructs a <code>SerialBlob</code> object that is a serialized version of 86 * the given <code>byte</code> array. 87 * <p> 88 * The new <code>SerialBlob</code> object is initialized with the data from the 89 * <code>byte</code> array, thus allowing disconnected <code>RowSet</code> 90 * objects to establish serialized <code>Blob</code> objects without 91 * touching the data source. 92 * 93 * @param b the <code>byte</code> array containing the data for the 94 * <code>Blob</code> object to be serialized 95 * @throws SerialException if an error occurs during serialization 96 * @throws SQLException if a SQL errors occurs 97 */ 98 public SerialBlob(byte[] b) throws SerialException, SQLException { 99 100 len = b.length; 101 buf = new byte[(int)len]; 102 for(int i = 0; i < len; i++) { 103 buf[i] = b[i]; 145 * Copies the specified number of bytes, starting at the given 146 * position, from this <code>SerialBlob</code> object to 147 * another array of bytes. 148 * <P> 149 * Note that if the given number of bytes to be copied is larger than 150 * the length of this <code>SerialBlob</code> object's array of 151 * bytes, the given number will be shortened to the array's length. 152 * 153 * @param pos the ordinal position of the first byte in this 154 * <code>SerialBlob</code> object to be copied; 155 * numbering starts at <code>1</code>; must not be less 156 * than <code>1</code> and must be less than or equal 157 * to the length of this <code>SerialBlob</code> object 158 * @param length the number of bytes to be copied 159 * @return an array of bytes that is a copy of a region of this 160 * <code>SerialBlob</code> object, starting at the given 161 * position and containing the given number of consecutive bytes 162 * @throws SerialException if the given starting position is out of bounds 163 */ 164 public byte[] getBytes(long pos, int length) throws SerialException { 165 if (length > len) { 166 length = (int)len; 167 } 168 169 if (pos < 1 || len - pos < 0 ) { 170 throw new SerialException("Invalid arguments: position cannot be " 171 + "less than 1 or greater than the length of the SerialBlob"); 172 } 173 174 pos--; // correct pos to array index 175 176 byte[] b = new byte[length]; 177 178 for (int i = 0; i < length; i++) { 179 b[i] = this.buf[(int)pos]; 180 pos++; 181 } 182 return b; 183 } 184 189 * @return a <code>long</code> indicating the length in bytes of this 190 * <code>SerialBlob</code> object's array of bytes 191 * @throws SerialException if an error occurs 192 */ 193 public long length() throws SerialException { 194 return len; 195 } 196 197 /** 198 * Returns this <code>SerialBlob</code> object as an input stream. 199 * Unlike the related method, <code>setBinaryStream</code>, 200 * a stream is produced regardless of whether the <code>SerialBlob</code> 201 * was created with a <code>Blob</code> object or a <code>byte</code> array. 202 * 203 * @return a <code>java.io.InputStream</code> object that contains 204 * this <code>SerialBlob</code> object's array of bytes 205 * @throws SerialException if an error occurs 206 * @see #setBinaryStream 207 */ 208 public java.io.InputStream getBinaryStream() throws SerialException { 209 InputStream stream = new ByteArrayInputStream(buf); 210 return stream; 211 } 212 213 /** 214 * Returns the position in this <code>SerialBlob</code> object where 215 * the given pattern of bytes begins, starting the search at the 216 * specified position. 217 * 218 * @param pattern the pattern of bytes for which to search 219 * @param start the position of the byte in this 220 * <code>SerialBlob</code> object from which to begin 221 * the search; the first position is <code>1</code>; 222 * must not be less than <code>1</code> nor greater than 223 * the length of this <code>SerialBlob</code> object 224 * @return the position in this <code>SerialBlob</code> object 225 * where the given pattern begins, starting at the specified 226 * position; <code>-1</code> if the pattern is not found 227 * or the given starting position is out of bounds; position 228 * numbering for the return value starts at <code>1</code> 229 * @throws SerialException if an error occurs when serializing the blob 230 * @throws SQLException if there is an error accessing the <code>BLOB</code> 231 * value from the database 232 */ 233 public long position(byte[] pattern, long start) 234 throws SerialException, SQLException { 235 if (start < 1 || start > len) { 236 return -1; 237 } 238 239 int pos = (int)start-1; // internally Blobs are stored as arrays. 240 int i = 0; 241 long patlen = pattern.length; 242 243 while (pos < len) { 244 if (pattern[i] == buf[pos]) { 245 if (i + 1 == patlen) { 246 return (pos + 1) - (patlen - 1); 247 } 248 i++; pos++; // increment pos, and i 249 } else if (pattern[i] != buf[pos]) { 250 pos++; // increment pos only 251 } 252 } 253 return -1; // not found 254 } 317 * value 318 * @param offset the offset in the <code>byte</code> array at which 319 * to start reading the bytes. The first offset position is 320 * <code>0</code>; must not be less than <code>0</code> nor greater 321 * than the length of the <code>byte</code> array 322 * @param length the number of bytes to be written to the 323 * <code>BLOB</code> value from the array of bytes <i>bytes</i>. 324 * 325 * @return the number of bytes written 326 * @throws SerialException if there is an error accessing the 327 * <code>BLOB</code> value; if an invalid position is set; if an 328 * invalid offset value is set; if number of bytes to be written 329 * is greater than the <code>SerialBlob</code> length; or the combined 330 * values of the length and offset is greater than the Blob buffer 331 * @throws SQLException if there is an error accessing the <code>BLOB</code> 332 * value from the database. 333 * @see #getBytes 334 */ 335 public int setBytes(long pos, byte[] bytes, int offset, int length) 336 throws SerialException, SQLException { 337 338 if (offset < 0 || offset > bytes.length) { 339 throw new SerialException("Invalid offset in byte array set"); 340 } 341 342 if (pos < 1 || pos > this.length()) { 343 throw new SerialException("Invalid position in BLOB object set"); 344 } 345 346 if ((long)(length) > origLen) { 347 throw new SerialException("Buffer is not sufficient to hold the value"); 348 } 349 350 if ((length + offset) > bytes.length) { 351 throw new SerialException("Invalid OffSet. Cannot have combined offset " + 352 "and length that is greater that the Blob buffer"); 353 } 354 355 int i = 0; 356 pos--; // correct to array indexing 385 if (this.blob != null) { 386 return this.blob.setBinaryStream(pos); 387 } else { 388 throw new SerialException("Unsupported operation. SerialBlob cannot " + 389 "return a writable binary stream, unless instantiated with a Blob object " + 390 "that provides a setBinaryStream() implementation"); 391 } 392 } 393 394 /** 395 * Truncates the <code>BLOB</code> value that this <code>Blob</code> 396 * object represents to be <code>len</code> bytes in length. 397 * 398 * @param length the length, in bytes, to which the <code>BLOB</code> 399 * value that this <code>Blob</code> object represents should be 400 * truncated 401 * @throws SerialException if there is an error accessing the Blob value; 402 * or the length to truncate is greater that the SerialBlob length 403 */ 404 public void truncate(long length) throws SerialException { 405 406 if (length > len) { 407 throw new SerialException 408 ("Length more than what can be truncated"); 409 } else if((int)length == 0) { 410 buf = new byte[0]; 411 len = length; 412 } else { 413 len = length; 414 buf = this.getBytes(1, (int)len); 415 } 416 } 417 418 419 /** 420 * Returns an <code>InputStream</code> object that contains a partial <code>Blob</code> value, 421 * starting with the byte specified by pos, which is length bytes in length. 422 * 423 * @param pos the offset to the first byte of the partial value to be retrieved. 424 * The first byte in the <code>Blob</code> is at position 1 425 * @param length the length in bytes of the partial value to be retrieved 426 * @return <code>InputStream</code> through which the partial <code>Blob</code> value can be read. 427 * @throws SQLException if pos is less than 1 or if pos is greater than the number of bytes 428 * in the <code>Blob</code> or if pos + length is greater than the number of bytes 429 * in the <code>Blob</code> 430 * 431 * @since 1.6 432 */ 433 public InputStream getBinaryStream(long pos,long length) throws SQLException { 434 throw new java.lang.UnsupportedOperationException("Not supported"); 435 } 436 437 438 /** 439 * This method frees the <code>Blob</code> object and releases the resources that it holds. 440 * <code>Blob</code> object. The object is invalid once the <code>free</code> 441 * method is called. If <code>free</code> is called multiple times, the subsequent 442 * calls to <code>free</code> are treated as a no-op. 443 * 444 * @throws SQLException if an error occurs releasing 445 * the Blob's resources 446 * @since 1.6 447 */ 448 public void free() throws SQLException { 449 throw new java.lang.UnsupportedOperationException("Not supported"); 450 } 451 /** 452 * The identifier that assists in the serialization of this <code>SerialBlob</code> 453 * object. 454 */ 455 456 static final long serialVersionUID = -8144641928112860441L; 457 } | 64 /** 65 * The internal representation of the <code>Blob</code> object on which this 66 * <code>SerialBlob</code> object is based. 67 */ 68 private Blob blob; 69 70 /** 71 * The number of bytes in this <code>SerialBlob</code> object's 72 * array of bytes. 73 * @serial 74 */ 75 private long len; 76 77 /** 78 * The orginal number of bytes in this <code>SerialBlob</code> object's 79 * array of bytes when it was first established. 80 * @serial 81 */ 82 private long origLen; 83 84 private transient boolean isFree = false; 85 86 /** 87 * Constructs a <code>SerialBlob</code> object that is a serialized version of 88 * the given <code>byte</code> array. 89 * <p> 90 * The new <code>SerialBlob</code> object is initialized with the data from the 91 * <code>byte</code> array, thus allowing disconnected <code>RowSet</code> 92 * objects to establish serialized <code>Blob</code> objects without 93 * touching the data source. 94 * 95 * @param b the <code>byte</code> array containing the data for the 96 * <code>Blob</code> object to be serialized 97 * @throws SerialException if an error occurs during serialization 98 * @throws SQLException if a SQL errors occurs 99 */ 100 public SerialBlob(byte[] b) throws SerialException, SQLException { 101 102 len = b.length; 103 buf = new byte[(int)len]; 104 for(int i = 0; i < len; i++) { 105 buf[i] = b[i]; 147 * Copies the specified number of bytes, starting at the given 148 * position, from this <code>SerialBlob</code> object to 149 * another array of bytes. 150 * <P> 151 * Note that if the given number of bytes to be copied is larger than 152 * the length of this <code>SerialBlob</code> object's array of 153 * bytes, the given number will be shortened to the array's length. 154 * 155 * @param pos the ordinal position of the first byte in this 156 * <code>SerialBlob</code> object to be copied; 157 * numbering starts at <code>1</code>; must not be less 158 * than <code>1</code> and must be less than or equal 159 * to the length of this <code>SerialBlob</code> object 160 * @param length the number of bytes to be copied 161 * @return an array of bytes that is a copy of a region of this 162 * <code>SerialBlob</code> object, starting at the given 163 * position and containing the given number of consecutive bytes 164 * @throws SerialException if the given starting position is out of bounds 165 */ 166 public byte[] getBytes(long pos, int length) throws SerialException { 167 if (isFree == true) { 168 throw new SerialException( 169 "Unsupported operation. SerialBlob cannot " 170 + "get bytes when it has already been freed with free()"); 171 } 172 173 if (length > len) { 174 length = (int)len; 175 } 176 177 if (pos < 1 || len - pos < 0 ) { 178 throw new SerialException("Invalid arguments: position cannot be " 179 + "less than 1 or greater than the length of the SerialBlob"); 180 } 181 182 pos--; // correct pos to array index 183 184 byte[] b = new byte[length]; 185 186 for (int i = 0; i < length; i++) { 187 b[i] = this.buf[(int)pos]; 188 pos++; 189 } 190 return b; 191 } 192 197 * @return a <code>long</code> indicating the length in bytes of this 198 * <code>SerialBlob</code> object's array of bytes 199 * @throws SerialException if an error occurs 200 */ 201 public long length() throws SerialException { 202 return len; 203 } 204 205 /** 206 * Returns this <code>SerialBlob</code> object as an input stream. 207 * Unlike the related method, <code>setBinaryStream</code>, 208 * a stream is produced regardless of whether the <code>SerialBlob</code> 209 * was created with a <code>Blob</code> object or a <code>byte</code> array. 210 * 211 * @return a <code>java.io.InputStream</code> object that contains 212 * this <code>SerialBlob</code> object's array of bytes 213 * @throws SerialException if an error occurs 214 * @see #setBinaryStream 215 */ 216 public java.io.InputStream getBinaryStream() throws SerialException { 217 if (isFree == true) { 218 throw new SerialException( 219 "Unsupported operation. SerialBlob cannot " 220 + "return a binary stream when it has already been freed with free()"); 221 } 222 223 InputStream stream = new ByteArrayInputStream(buf); 224 return stream; 225 } 226 227 /** 228 * Returns the position in this <code>SerialBlob</code> object where 229 * the given pattern of bytes begins, starting the search at the 230 * specified position. 231 * 232 * @param pattern the pattern of bytes for which to search 233 * @param start the position of the byte in this 234 * <code>SerialBlob</code> object from which to begin 235 * the search; the first position is <code>1</code>; 236 * must not be less than <code>1</code> nor greater than 237 * the length of this <code>SerialBlob</code> object 238 * @return the position in this <code>SerialBlob</code> object 239 * where the given pattern begins, starting at the specified 240 * position; <code>-1</code> if the pattern is not found 241 * or the given starting position is out of bounds; position 242 * numbering for the return value starts at <code>1</code> 243 * @throws SerialException if an error occurs when serializing the blob 244 * @throws SQLException if there is an error accessing the <code>BLOB</code> 245 * value from the database 246 */ 247 public long position(byte[] pattern, long start) 248 throws SerialException, SQLException { 249 if (isFree == true) { 250 throw new SerialException( 251 "Unsupported operation. SerialBlob has already been freed "); 252 } 253 254 if (start < 1 || start > len) { 255 return -1; 256 } 257 258 int pos = (int)start-1; // internally Blobs are stored as arrays. 259 int i = 0; 260 long patlen = pattern.length; 261 262 while (pos < len) { 263 if (pattern[i] == buf[pos]) { 264 if (i + 1 == patlen) { 265 return (pos + 1) - (patlen - 1); 266 } 267 i++; pos++; // increment pos, and i 268 } else if (pattern[i] != buf[pos]) { 269 pos++; // increment pos only 270 } 271 } 272 return -1; // not found 273 } 336 * value 337 * @param offset the offset in the <code>byte</code> array at which 338 * to start reading the bytes. The first offset position is 339 * <code>0</code>; must not be less than <code>0</code> nor greater 340 * than the length of the <code>byte</code> array 341 * @param length the number of bytes to be written to the 342 * <code>BLOB</code> value from the array of bytes <i>bytes</i>. 343 * 344 * @return the number of bytes written 345 * @throws SerialException if there is an error accessing the 346 * <code>BLOB</code> value; if an invalid position is set; if an 347 * invalid offset value is set; if number of bytes to be written 348 * is greater than the <code>SerialBlob</code> length; or the combined 349 * values of the length and offset is greater than the Blob buffer 350 * @throws SQLException if there is an error accessing the <code>BLOB</code> 351 * value from the database. 352 * @see #getBytes 353 */ 354 public int setBytes(long pos, byte[] bytes, int offset, int length) 355 throws SerialException, SQLException { 356 if (isFree == true) { 357 throw new SerialException( 358 "Unsupported operation. SerialBlob cannot " 359 + "set a binary stream when it has already been freed with free()"); 360 } 361 362 if (offset < 0 || offset > bytes.length) { 363 throw new SerialException("Invalid offset in byte array set"); 364 } 365 366 if (pos < 1 || pos > this.length()) { 367 throw new SerialException("Invalid position in BLOB object set"); 368 } 369 370 if ((long)(length) > origLen) { 371 throw new SerialException("Buffer is not sufficient to hold the value"); 372 } 373 374 if ((length + offset) > bytes.length) { 375 throw new SerialException("Invalid OffSet. Cannot have combined offset " + 376 "and length that is greater that the Blob buffer"); 377 } 378 379 int i = 0; 380 pos--; // correct to array indexing 409 if (this.blob != null) { 410 return this.blob.setBinaryStream(pos); 411 } else { 412 throw new SerialException("Unsupported operation. SerialBlob cannot " + 413 "return a writable binary stream, unless instantiated with a Blob object " + 414 "that provides a setBinaryStream() implementation"); 415 } 416 } 417 418 /** 419 * Truncates the <code>BLOB</code> value that this <code>Blob</code> 420 * object represents to be <code>len</code> bytes in length. 421 * 422 * @param length the length, in bytes, to which the <code>BLOB</code> 423 * value that this <code>Blob</code> object represents should be 424 * truncated 425 * @throws SerialException if there is an error accessing the Blob value; 426 * or the length to truncate is greater that the SerialBlob length 427 */ 428 public void truncate(long length) throws SerialException { 429 if (isFree == true) { 430 throw new SerialException( 431 "Unsupported operation. SerialBlob cannot " 432 + "truncate a SerialBlob when it has already been freed with free()"); 433 } 434 435 if (length > len) { 436 throw new SerialException 437 ("Length more than what can be truncated"); 438 } else if((int)length == 0) { 439 buf = new byte[0]; 440 len = length; 441 } else { 442 len = length; 443 buf = this.getBytes(1, (int)len); 444 } 445 } 446 447 448 /** 449 * Returns an <code>InputStream</code> object that contains a partial <code>Blob</code> value, 450 * starting with the byte specified by pos, which is length bytes in length. 451 * 452 * @param pos the offset to the first byte of the partial value to be retrieved. 453 * The first byte in the <code>Blob</code> is at position 1 454 * @param length the length in bytes of the partial value to be retrieved 455 * @return <code>InputStream</code> through which the partial <code>Blob</code> value can be read. 456 * @throws SQLException if pos is less than 1 or if pos is greater than the number of bytes 457 * in the <code>Blob</code> or if pos + length is greater than the number of bytes 458 * in the <code>Blob</code> 459 * 460 * @since 1.6 461 */ 462 public InputStream getBinaryStream(long pos,long length) throws SQLException { 463 if (isFree == true) { 464 throw new SerialException( 465 "Unsupported operation. SerialBlob cannot " 466 + "return a binary stream when it has already been freed with free()"); 467 } 468 469 if (pos < 1 || pos > len || length > len - pos + 1) { 470 throw new SerialException("Invalid pos in getBinaryStream"); 471 } 472 if (length > len - pos + 1) { 473 throw new SerialException("pos + length greater than total number of bytes"); 474 } 475 return new ByteArrayInputStream(buf, (int) pos - 1, (int) length); 476 } 477 478 479 /** 480 * This method frees the <code>Blob</code> object and releases the resources that it holds. 481 * <code>Blob</code> object. The object is invalid once the <code>free</code> 482 * method is called. If <code>free</code> is called multiple times, the subsequent 483 * calls to <code>free</code> are treated as a no-op. 484 * 485 * @throws SQLException if an error occurs releasing 486 * the Blob's resources 487 * @since 1.6 488 */ 489 public void free() throws SQLException { 490 if (isFree == false) { 491 len = -1; 492 origLen = -1; 493 buf = null; 494 blob = null; 495 496 isFree = true; 497 } 498 } 499 /** 500 * The identifier that assists in the serialization of this <code>SerialBlob</code> 501 * object. 502 */ 503 504 static final long serialVersionUID = -8144641928112860441L; 505 } |