1 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 ; 38 import java.sql.Blob ; 39 import java.io.InputStream ; 40 import java.io.EOFException ; 41 import java.io.IOException ; 42 43 71 72 final class EmbedBlob extends ConnectionChild implements Blob 73 { 74 private boolean isBytes; 76 private InputStream myStream; 77 78 82 private long myLength = -1; 83 84 private byte[] myBytes; 85 private long pos; 87 private BinaryToRawStream biStream; 89 90 private static int BLOB_BUF_SIZE = 4096; 93 private byte buf[]; 94 95 private boolean isValid = true; 98 99 109 110 EmbedBlob(byte [] blobBytes,EmbedConnection con) { 111 super(con); 112 myBytes = blobBytes; 113 isBytes = true; 114 myLength = myBytes.length; 115 } 116 117 120 protected EmbedBlob(DataValueDescriptor dvd, EmbedConnection con) 121 throws StandardException 122 { 123 super(con); 124 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 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 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 buf = new byte[BLOB_BUF_SIZE]; 171 } 172 pos = 0; 173 } 174 175 176 184 private void setPosition(long newPos) 185 throws StandardException, IOException 186 { 187 if (SanityManager.DEBUG) 188 SanityManager.ASSERT(newPos >= 0); 189 if (isBytes) 190 pos = newPos; 191 else 192 { 193 ((Resetable)myStream).resetStream(); 196 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) throw StandardException.newException(SQLState.BLOB_LENGTH_TOO_LONG); 205 pos += size; 206 } 207 } 208 } 209 210 211 214 private int read() 215 throws IOException 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 238 public long length() 240 throws SQLException 241 { 242 checkValidity(); 245 246 if (myLength != -1) 247 return myLength; 248 249 boolean pushStack = false; 250 try 251 { 252 synchronized (getConnectionSynchronization()) 254 { 255 pushStack = !getEmbedConnection().isClosed(); 256 if (pushStack) 257 setupContextStack(); 258 259 setPosition(0); 260 if ((myLength = biStream.getLength()) != -1) { 263 biStream.close(); 264 return myLength; 265 } 266 267 for (;;) 269 { 270 int size = biStream.read(buf); 271 if (size == -1) 272 break; 273 pos += size; 274 } 275 myLength = pos; 277 biStream.close(); 278 return pos; 279 } 280 } 281 catch (Throwable t) 282 { 283 throw handleMyExceptions(t); 284 } 285 finally 286 { 287 if (pushStack) 288 restoreContextStack(); 289 } 290 } 291 292 293 316 public byte[] getBytes(long startPos, int length) 317 throws SQLException 318 { 319 checkValidity(); 322 323 boolean pushStack = false; 324 try 325 { 326 if (startPos < 1) 327 throw StandardException.newException( 328 SQLState.BLOB_BAD_POSITION, new Long (startPos)); 329 if (length < 0) 330 throw StandardException.newException( 331 SQLState.BLOB_NONPOSITIVE_LENGTH, new Integer (length)); 332 333 byte[] result; 334 if (isBytes) 336 { 337 if (myBytes.length + 1 < startPos) 339 throw StandardException.newException( 340 SQLState.BLOB_POSITION_TOO_LARGE, new Long (startPos)); 341 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 { 349 synchronized (getConnectionSynchronization()) 350 { 351 pushStack = !getEmbedConnection().isClosed(); 352 if (pushStack) 353 setupContextStack(); 354 355 setPosition(startPos-1); 356 result = new byte[length]; 358 int n = InputStreamUtil.readLoop(biStream,result,0,length); 359 pos += n; 360 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 (e.getMessageId().equals(SQLState.BLOB_LENGTH_TOO_LONG)) 381 e = StandardException.newException( 382 SQLState.BLOB_POSITION_TOO_LARGE, new Long (startPos)); 383 throw handleMyExceptions(e); 384 } 385 catch (Throwable t) 386 { 387 throw handleMyExceptions(t); 388 } 389 finally 390 { 391 if (pushStack) 392 restoreContextStack(); 393 } 394 395 } 396 397 398 405 public java.io.InputStream getBinaryStream() 406 throws SQLException 407 { 408 checkValidity(); 411 412 boolean pushStack = false; 413 try 414 { 415 if (isBytes) 417 { 418 return new NewByteArrayInputStream(myBytes); 419 } 420 else 421 { 422 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 t) 436 { 437 throw handleMyExceptions(t); 438 } 439 finally 440 { 441 if (pushStack) 442 restoreContextStack(); 443 } 444 } 445 446 447 460 public long position(byte[] pattern, long start) 461 throws SQLException 462 { 463 checkValidity(); 466 467 boolean pushStack = false; 468 try 469 { 470 if (start < 1) 471 throw StandardException.newException( 472 SQLState.BLOB_BAD_POSITION, new Long (start)); 473 if (pattern == null) 474 throw StandardException.newException(SQLState.BLOB_NULL_PATTERN_OR_SEARCH_STR); 475 if (pattern.length == 0) 476 return start; 478 synchronized (getConnectionSynchronization()) 479 { 480 pushStack = !getEmbedConnection().isClosed(); 481 if (pushStack) 482 setupContextStack(); 483 484 setPosition(start-1); 485 int lookFor = pattern[0]; 487 long curPos; 488 int c; 489 while (true) 490 { 491 c = read(); 492 if (c == -1) 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 (e.getMessageId().equals(SQLState.BLOB_LENGTH_TOO_LONG)) 508 return -1; 509 else 510 throw handleMyExceptions(e); 511 } 512 catch (Throwable t) 513 { 514 throw handleMyExceptions(t); 515 } 516 finally 517 { 518 if (pushStack) 519 restoreContextStack(); 520 } 521 522 } 523 524 525 532 private boolean checkMatch(byte[] pattern) 533 throws IOException 534 { 535 for (int i = 1; i < pattern.length; i++) 538 { 539 int b = read(); 540 if ((b < 0) || (b != pattern[i])) return false; 542 } 543 return true; 544 } 545 546 559 public long position(Blob pattern, long start) 560 throws SQLException 561 { 562 checkValidity(); 565 566 boolean pushStack = false; 567 try 568 { 569 if (start < 1) 570 throw StandardException.newException( 571 SQLState.BLOB_BAD_POSITION, new Long (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 byte[] b; 583 try 584 { b = pattern.getBytes(1,1); 586 } 587 catch (SQLException e) 588 { 589 throw StandardException.newException(SQLState.BLOB_UNABLE_TO_READ_PATTERN); 590 } 591 if (b == null || b.length < 1) return start; int lookFor = b[0]; 594 int c; 595 long curPos; 596 while (true) 597 { 598 c = read(); 599 if (c == -1) 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 (e.getMessageId().equals(SQLState.BLOB_LENGTH_TOO_LONG)) 615 return -1; 616 else 617 throw handleMyExceptions(e); 618 } 619 catch (Throwable t) 620 { 621 throw handleMyExceptions(t); 622 } 623 finally 624 { 625 if (pushStack) 626 restoreContextStack(); 627 } 628 629 } 630 631 632 639 private boolean checkMatch(Blob pattern) 640 throws IOException 641 { 642 InputStream pStream; 645 try 646 { 647 pStream = pattern.getBinaryStream(); 648 } 649 catch (SQLException e) 650 { 651 return false; 652 } 653 if (pStream == null) 654 return false; 655 int b1 = pStream.read(); 658 if (b1 < 0) 659 return false; 660 while (true) 661 { 662 b1 = pStream.read(); 663 if (b1 < 0) return true; 665 int b2 = read(); 666 if ((b1 != b2) || (b2 < 0)) return false; 668 } 669 } 670 671 675 private SQLException handleMyExceptions(Throwable t) 676 throws SQLException 677 { 678 if (t instanceof StandardException) 679 { 680 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 693 protected void finalize() 694 { 695 if (!isBytes) 696 ((Resetable)myStream).closeStream(); 697 } 698 699 706 707 713 725 public int setBytes(long pos, 726 byte[] bytes) 727 throws SQLException 728 { 729 throw Util.notImplemented(); 730 } 731 732 750 public int setBytes(long pos, 751 byte[] bytes, int offset, 752 int len) 753 throws SQLException 754 { 755 throw Util.notImplemented(); 756 } 757 758 768 public java.io.OutputStream setBinaryStream(long pos) 769 throws SQLException 770 { 771 throw Util.notImplemented(); 772 } 773 774 784 public void truncate(long len) 785 throws SQLException 786 { 787 throw Util.notImplemented(); 788 } 789 790 804 public void free() 805 throws SQLException { 806 if (!isValid) return; 808 809 isValid = false; 812 813 myLength = -1; 815 816 if (!isBytes) 820 ((Resetable)myStream).closeStream(); 821 else 822 myBytes = null; 823 } 824 825 839 public InputStream getBinaryStream(long pos, long length) 840 throws SQLException { 841 throw Util.notImplemented(); 842 } 843 844 851 private void checkValidity() throws SQLException { 852 if(!isValid) 853 throw newSQLException(SQLState.LOB_OBJECT_INVALID); 854 } 855 } 856 | Popular Tags |