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.impl.jdbc.UTF8Reader; 34 import org.apache.derby.impl.jdbc.ReaderToAscii; 35 36 import java.io.InputStream ; 37 import java.io.InputStreamReader ; 38 import java.io.StringReader ; 39 import java.io.Reader ; 40 import java.io.IOException ; 41 import java.io.EOFException ; 42 import java.sql.SQLException ; 43 import java.sql.Clob ; 44 45 72 final class EmbedClob extends ConnectionChild implements Clob 73 { 74 private boolean isString; 76 private InputStream myStream; 77 private String myString; 78 79 private boolean isValid = true; 82 83 93 94 EmbedClob(String clobString,EmbedConnection con) { 95 super(con); 96 myString = clobString; 97 isString = true; 98 } 99 100 103 protected EmbedClob(DataValueDescriptor dvd, EmbedConnection con) 104 throws StandardException 105 { 106 super(con); 107 if (SanityManager.DEBUG) 110 SanityManager.ASSERT(!dvd.isNull(), "clob is created on top of a null column"); 111 112 myStream = dvd.getStream(); 113 if (myStream == null) 114 { 115 isString = true; 116 myString = dvd.getString(); 117 if (SanityManager.DEBUG) 118 SanityManager.ASSERT(myString != null,"clob has a null value underneath"); 119 } 120 else 121 { 122 135 if (SanityManager.DEBUG) 136 SanityManager.ASSERT(myStream instanceof Resetable); 137 138 try { 139 ((Resetable) myStream).initStream(); 140 } catch (StandardException se) { 141 if (se.getMessageId().equals(SQLState.DATA_CONTAINER_CLOSED)) { 142 throw StandardException 143 .newException(SQLState.BLOB_ACCESSED_AFTER_COMMIT); 144 } 145 } 146 } 147 } 148 149 150 158 159 public long length() throws SQLException 160 { 161 checkValidity(); 164 if (isString) 166 return myString.length(); 167 168 169 Object synchronization = getConnectionSynchronization(); 170 synchronized (synchronization) 171 { 172 Reader clobReader = null; 173 setupContextStack(); 174 try { 175 176 clobReader = getCharacterStream(); 177 long clobLength = 0; 178 for (;;) 179 { 180 long size = clobReader.skip(32 * 1024); 181 if (size == -1) 182 break; 183 clobLength += size; 184 } 185 clobReader.close(); 186 clobReader = null; 187 188 return clobLength; 189 } 190 catch (Throwable t) 191 { 192 throw noStateChangeLOB(t); 193 } 194 finally 195 { 196 if (clobReader != null) { 197 try { 198 clobReader.close(); 199 } catch (IOException ioe) { 200 } 201 } 202 restoreContextStack(); 203 } 204 } 205 } 206 207 229 public String getSubString(long pos, int length) throws SQLException 230 { 231 checkValidity(); 234 235 if (pos < 1) 236 throw Util.generateCsSQLException( 237 SQLState.BLOB_BAD_POSITION, new Long (pos)); 238 if (length < 0) 239 throw Util.generateCsSQLException( 240 SQLState.BLOB_NONPOSITIVE_LENGTH, new Integer (length)); 241 242 if (isString) 244 { 245 int sLength = myString.length(); 246 if (sLength + 1 < pos) 247 throw Util.generateCsSQLException( 248 SQLState.BLOB_POSITION_TOO_LARGE, new Long (pos)); 249 int endIndex = ((int) pos) + length - 1; 250 return myString.substring(((int) pos) - 1, (sLength > endIndex ? endIndex : sLength)); 252 } 253 254 Object synchronization = getConnectionSynchronization(); 255 synchronized (synchronization) 256 { 257 setupContextStack(); 258 259 UTF8Reader clobReader = null; 260 try { 261 262 clobReader = getCharacterStreamAtPos(pos, synchronization); 263 if (clobReader == null) 264 throw StandardException.newException(SQLState.BLOB_POSITION_TOO_LARGE, new Long (pos)); 265 266 StringBuffer sb = new StringBuffer (length); 267 int remainToRead = length; 268 while (remainToRead > 0) { 269 270 int read = clobReader.readInto(sb, remainToRead); 271 if (read == -1) 272 break; 273 274 remainToRead -= read; 275 } 276 clobReader.close(); 277 clobReader = null; 278 279 return sb.toString(); 280 } 281 catch (Throwable t) 282 { 283 throw noStateChangeLOB(t); 284 } 285 finally 286 { 287 if (clobReader != null) 288 clobReader.close(); 289 restoreContextStack(); 290 } 291 } 292 } 293 294 295 301 302 public java.io.Reader getCharacterStream() throws SQLException 303 { 304 checkValidity(); 307 308 if (isString) 310 { 311 return new StringReader (myString); 312 } 313 314 315 Object synchronization = getConnectionSynchronization(); 316 synchronized (synchronization) 317 { 318 setupContextStack(); 319 320 try { 321 return getCharacterStreamAtPos(1, synchronization); 322 } 323 catch (Throwable t) 324 { 325 throw noStateChangeLOB(t); 326 } 327 finally 328 { 329 restoreContextStack(); 330 } 331 } 332 } 333 334 335 342 343 public java.io.InputStream getAsciiStream() throws SQLException 344 { 345 checkValidity(); 348 return new ReaderToAscii(getCharacterStream()); 349 } 350 351 private UTF8Reader getCharacterStreamAtPos(long position, Object synchronization) 352 throws IOException , StandardException 353 { 354 ((Resetable)myStream).resetStream(); 355 UTF8Reader clobReader = new UTF8Reader(myStream, 0, this, synchronization); 356 357 long remainToSkip = position - 1; 359 while (remainToSkip > 0) { 360 long skipBy = clobReader.skip(remainToSkip); 361 if (skipBy == -1) 362 return null; 363 364 remainToSkip -= skipBy; 365 } 366 367 return clobReader; 368 } 369 370 371 383 public long position(String searchStr, long start) 384 throws SQLException 385 { 386 checkValidity(); 389 390 boolean pushStack = false; 391 try 392 { 393 if (start < 1) 394 throw StandardException.newException( 395 SQLState.BLOB_BAD_POSITION, new Long (start)); 396 if (searchStr == null) 397 throw StandardException.newException(SQLState.BLOB_NULL_PATTERN_OR_SEARCH_STR); 398 if (searchStr == "") 399 return start; 401 if (isString) 403 { 404 if (start > myString.length()) 406 return -1; 407 408 int result = myString.indexOf(searchStr, (int) start-1); 409 return result < 0 ? -1 : result + 1; 410 } 411 else { 413 Object synchronization = getConnectionSynchronization(); 414 synchronized (synchronization) 415 { 416 pushStack = !getEmbedConnection().isClosed(); 417 if (pushStack) 418 setupContextStack(); 419 420 char[] tmpClob = new char[256]; 421 int patternLength = searchStr.length(); 422 423 restartPattern: 424 for (;;) { 425 426 UTF8Reader clobReader = getCharacterStreamAtPos(start, synchronization); 428 if (clobReader == null) 429 return -1; 430 431 432 433 435 int patternIndex = 0; 436 char[] tmpPattern = null; 437 boolean needPattern = true; 438 439 int matchCount = 0; 441 442 long currentPosition = start; 443 int clobOffset = -1; 444 int read = -1; 445 446 long matchPosition = -1; 448 449 450 long nextBestMatchPosition = -1; 452 454 455 search: 456 for (;;) 457 { 458 if (needPattern) { 460 461 String tmpPatternS; 462 if ((patternLength - patternIndex) > 256) 463 tmpPatternS = searchStr.substring(patternIndex, 256); 464 else 465 tmpPatternS = searchStr; 466 467 tmpPattern = tmpPatternS.toCharArray(); 468 needPattern = false; 469 matchCount = 0; 470 471 } 472 473 if (clobOffset == -1) { 474 475 read = clobReader.read(tmpClob, 0, tmpClob.length); 476 if (read == -1) 478 return -1; 479 480 if (read == 0) 481 continue search; 482 483 clobOffset = 0; 484 } 485 486 487 compareArrays: 489 for (; clobOffset < read; clobOffset++) { 490 491 493 char clobC = tmpClob[clobOffset]; 494 495 496 if (clobC == tmpPattern[matchCount]) 497 { 498 if (matchPosition == -1) { 499 matchPosition = currentPosition + clobOffset; 500 } 501 502 matchCount++; 503 504 if (matchCount == tmpPattern.length) 506 { 507 patternIndex += tmpPattern.length; 509 if (patternIndex == patternLength) { 510 clobReader.close(); 512 return matchPosition; 514 } 515 516 needPattern = true; 517 continue search; 518 519 } 520 521 if (clobC == tmpPattern[0]) { 522 523 525 if (patternIndex == 0) { 527 528 if (matchCount != 1) { 530 531 533 if (nextBestMatchPosition == -1) { 534 nextBestMatchPosition = currentPosition + clobOffset; 535 } 536 537 } 538 539 } 540 } 541 542 continue compareArrays; 543 } 544 else 545 { 546 if (matchPosition != -1) { 550 matchPosition = -1; 552 553 if (nextBestMatchPosition == -1) 555 { 556 558 if (patternIndex != 0) { 559 needPattern = true; 560 continue search; 561 } 562 } 563 else if (nextBestMatchPosition >= currentPosition) 564 { 565 clobOffset = (int) (nextBestMatchPosition - currentPosition); 567 nextBestMatchPosition = -1; 568 569 if (patternIndex != 0) { 570 needPattern = true; 571 continue search; 572 } 573 } 574 else 575 { 576 clobReader.close(); 577 start = nextBestMatchPosition; 578 continue restartPattern; 579 } 580 581 clobOffset--; matchCount = 0; 583 continue compareArrays; 584 } 585 586 } 588 } 589 590 currentPosition += read; 591 592 clobOffset = -1; 594 } 595 } 596 } 597 } 598 } 599 catch (Throwable t) 600 { 601 throw noStateChangeLOB(t); 602 } 603 finally 604 { 605 if (pushStack) 606 restoreContextStack(); 607 } 608 609 } 610 611 612 625 626 public long position(Clob searchClob, long start) 627 throws SQLException 628 { 629 checkValidity(); 632 633 boolean pushStack = false; 634 try 635 { 636 if (start < 1) 637 throw StandardException.newException( 638 SQLState.BLOB_BAD_POSITION, new Long (start)); 639 if (searchClob == null) 640 throw StandardException.newException(SQLState.BLOB_NULL_PATTERN_OR_SEARCH_STR); 641 642 synchronized (getConnectionSynchronization()) 643 { 644 char[] subPatternChar = new char[256]; 645 646 boolean seenOneCharacter = false; 647 648 650 restartScan: 651 for (;;) { 652 653 long firstPosition = -1; 654 655 Reader patternReader = searchClob.getCharacterStream(); 656 657 659 try { 660 661 for (;;) { 662 663 int read = patternReader.read(subPatternChar, 0, subPatternChar.length); 664 if (read == -1) { 665 if (!seenOneCharacter) 667 return start; 669 return firstPosition; 670 } 671 if (read == 0) { 672 continue; 674 } 675 676 seenOneCharacter = true; 677 678 String subPattern = new String (subPatternChar, 0, read); 679 long position = position(subPattern, start); 681 if (position == -1) { 683 if (firstPosition == -1) 685 return -1; 686 687 start = firstPosition + 1; 688 continue restartScan; 689 } 690 691 if (firstPosition == -1) 692 firstPosition = position; 693 else if (position != start) { 694 start = firstPosition + 1; 696 continue restartScan; 697 } 698 699 start = position + read; 701 } 702 } finally { 703 patternReader.close(); 704 } 705 } 706 } 707 } 708 catch (Throwable t) 709 { 710 throw noStateChangeLOB(t); 711 } 712 finally 713 { 714 if (pushStack) 715 restoreContextStack(); 716 } 717 718 } 719 720 721 724 protected void finalize() 725 { 726 if (!isString) 728 ((Resetable)myStream).closeStream(); 729 } 730 731 732 739 740 746 757 public int setString(long pos, String parameterName) 758 throws SQLException 759 { 760 throw Util.notImplemented(); 761 } 762 763 776 public int setString(long pos, String str, int offset, int len) 777 throws SQLException 778 { 779 throw Util.notImplemented(); 780 } 781 782 792 public java.io.OutputStream setAsciiStream(long pos) 793 throws SQLException 794 { 795 throw Util.notImplemented(); 796 } 797 798 808 public java.io.Writer setCharacterStream(long pos) 809 throws SQLException 810 { 811 throw Util.notImplemented(); 812 } 813 814 823 public void truncate(long len) 824 throws SQLException 825 { 826 throw Util.notImplemented(); 827 } 828 829 843 public void free() 844 throws SQLException { 845 if (!isValid) return; 847 848 isValid = false; 851 852 if (!isString) 853 ((Resetable)myStream).closeStream(); 854 else 855 myString = null; 856 } 857 858 public java.io.Reader getCharacterStream(long pos, long length) 859 throws SQLException { 860 throw Util.notImplemented(); 861 } 862 863 866 867 static SQLException noStateChangeLOB(Throwable t) { 868 if (t instanceof StandardException) 869 { 870 if (((StandardException) t).getMessageId().equals(SQLState.DATA_CONTAINER_CLOSED)) 872 { 873 t = StandardException.newException(SQLState.BLOB_ACCESSED_AFTER_COMMIT); 874 } 875 } 876 return org.apache.derby.impl.jdbc.EmbedResultSet.noStateChangeException(t); 877 } 878 879 886 private void checkValidity() throws SQLException { 887 if(!isValid) 888 throw newSQLException(SQLState.LOB_OBJECT_INVALID); 889 } 890 } 891 | Popular Tags |