1 29 30 package com.caucho.quercus.lib.db; 31 32 import com.caucho.quercus.annotation.NotNull; 33 import com.caucho.quercus.annotation.Optional; 34 import com.caucho.quercus.annotation.ReturnNullAsFalse; 35 import com.caucho.quercus.env.BinaryBuilderValue; 36 import com.caucho.quercus.env.Env; 37 import com.caucho.quercus.env.LongValue; 38 import com.caucho.quercus.env.StringBuilderValue; 39 import com.caucho.util.L10N; 40 import com.caucho.vfs.Path; 41 import com.caucho.vfs.ReadStream; 42 import com.caucho.vfs.WriteStream; 43 44 import java.io.InputStream ; 45 import java.io.OutputStream ; 46 import java.io.Reader ; 47 import java.io.Writer ; 48 import java.lang.reflect.Method ; 49 import java.sql.Blob ; 50 import java.sql.Clob ; 51 import java.sql.Connection ; 52 import java.util.logging.Level ; 53 import java.util.logging.Logger ; 54 55 56 59 public class OracleOciLob { 60 private static final Logger log = Logger.getLogger(OracleOciLob.class.getName()); 61 private static final L10N L = new L10N(OracleOciLob.class); 62 63 private Object _lob; 65 66 private Oracle _conn; 68 69 private long _currentPointer; 71 72 private int _type; 74 75 private OutputStream _outputStream; 77 private Writer _writer; 78 79 private static Class classOracleBLOB; 81 private static Class classOracleCLOB; 82 private static Method createTemporaryBLOB; 83 private static Method createTemporaryCLOB; 84 private static int BLOB_DURATION_CALL; 85 private static int BLOB_DURATION_SESSION; 86 private static int CLOB_DURATION_CALL; 87 private static int CLOB_DURATION_SESSION; 88 89 static { 90 try { 91 classOracleBLOB = Class.forName("oracle.sql.BLOB"); 92 classOracleCLOB = Class.forName("oracle.sql.CLOB"); 93 createTemporaryBLOB = classOracleBLOB.getDeclaredMethod("createTemporary", 94 new Class [] {Connection .class, 95 Boolean.TYPE, 96 Integer.TYPE}); 97 createTemporaryCLOB = classOracleCLOB.getDeclaredMethod("createTemporary", 98 new Class [] {Connection .class, 99 Boolean.TYPE, 100 Integer.TYPE}); 101 BLOB_DURATION_CALL = classOracleBLOB.getDeclaredField("DURATION_CALL").getInt(null); 102 BLOB_DURATION_SESSION = classOracleBLOB.getDeclaredField("DURATION_SESSION").getInt(null); 103 CLOB_DURATION_CALL = classOracleCLOB.getDeclaredField("DURATION_CALL").getInt(null); 104 CLOB_DURATION_SESSION = classOracleCLOB.getDeclaredField("DURATION_SESSION").getInt(null); 105 } catch (Exception e) { 106 L.l("Unable to load LOB classes or methods for oracle.sql.BLOB and oracle.sql.CLOB."); 107 } 108 } 109 110 111 122 OracleOciLob(Oracle conn, int type) 123 { 124 _conn = conn; 125 _lob = null; 126 _currentPointer = 0; 127 _type = type; 128 _outputStream = null; 129 _writer = null; 130 } 131 132 135 public boolean append(Env env, 136 OracleOciLob lobFrom) 137 { 138 try { 139 140 switch (_type) { 141 case OracleModule.OCI_D_FILE: 142 break; 143 case OracleModule.OCI_D_LOB: 144 if (_lob instanceof Blob ) { 145 Blob blob = (Blob ) _lob; 146 return appendInternalBlob(env, lobFrom); 147 } else if (_lob instanceof Clob ) { 148 Clob clob = (Clob ) _lob; 149 return appendInternalClob(env, lobFrom); 150 } 151 break; 152 case OracleModule.OCI_D_ROWID: 153 break; 154 } 155 156 return true; 157 158 } catch (Exception ex) { 159 log.log(Level.FINE, ex.toString(), ex); 160 return false; 161 } 162 } 163 164 167 public boolean close(Env env) 168 { 169 try { 170 171 _currentPointer = 0; 172 173 if (_outputStream != null) { 174 _outputStream.close(); 175 _outputStream = null; 176 } 177 178 if (_writer != null) { 179 _writer.close(); 180 _writer = null; 181 } 182 183 return true; 184 185 } catch (Exception ex) { 186 log.log(Level.FINE, ex.toString(), ex); 187 return false; 188 } 189 } 190 191 194 public boolean eof(Env env) 195 { 196 try { 197 198 long length = -1; 199 200 switch (_type) { 201 case OracleModule.OCI_D_FILE: 202 break; 203 case OracleModule.OCI_D_LOB: 204 if (_lob instanceof Blob ) { 205 Blob blob = (Blob ) _lob; 206 length = blob.length(); 207 } else if (_lob instanceof Clob ) { 208 Clob clob = (Clob ) _lob; 209 length = clob.length(); 210 } 211 break; 212 case OracleModule.OCI_D_ROWID: 213 break; 214 } 215 216 if (_currentPointer == length) { 217 return true; 218 } 219 220 } catch (Exception ex) { 221 log.log(Level.FINE, ex.toString(), ex); 222 } 223 224 return false; 225 } 226 227 233 @ReturnNullAsFalse 234 public LongValue erase(Env env, 235 @Optional("0") long offset, 236 @Optional("-1") long length) 237 { 238 try { 239 240 if (offset < 0) { 241 offset = 0; 242 } 243 244 switch (_type) { 245 case OracleModule.OCI_D_FILE: 246 break; 247 case OracleModule.OCI_D_LOB: 248 if (_lob instanceof Blob ) { 249 Blob blob = (Blob ) _lob; 250 if (_outputStream != null) { 251 _outputStream.close(); 252 } 253 _outputStream = blob.setBinaryStream(offset); 254 long blobLength = blob.length(); 255 if ((length < 0) || (offset + length > blobLength)) { 256 length = blobLength - offset; 257 } 258 long remaining = length; 259 byte zeroBuffer[] = new byte[128]; 260 while (remaining >= 128) { 261 _outputStream.write(zeroBuffer, 0, 128); 262 remaining -= 128; 263 } 264 if (remaining > 0) { 265 _outputStream.write(zeroBuffer, 0, (int) remaining); 266 } 267 } else if (_lob instanceof Clob ) { 268 Clob clob = (Clob ) _lob; 269 if (_writer != null) { 270 _writer.close(); 271 } 272 _writer = clob.setCharacterStream(offset); 273 long clobLength = clob.length(); 274 if ((length < 0) || (offset + length > clobLength)) { 275 length = clobLength - offset; 276 } 277 long remaining = length; 278 char spaceBuffer[] = new char[128]; 279 while (remaining >= 128) { 280 _writer.write(spaceBuffer, 0, 128); 281 remaining -= 128; 282 } 283 if (remaining > 0) { 284 _writer.write(spaceBuffer, 0, (int) remaining); 285 } 286 } 287 _currentPointer = offset + length; 288 break; 289 case OracleModule.OCI_D_ROWID: 290 break; 291 } 292 293 if (length > 0) { 294 return LongValue.create(length); 295 } 296 297 } catch (Exception ex) { 298 log.log(Level.FINE, ex.toString(), ex); 299 } 300 301 return null; 302 } 303 304 307 public boolean export(Env env, 308 Path file, 309 @Optional("0") long start, 310 @Optional("-1") long length) 311 { 312 try { 313 314 WriteStream writeStream = file.openWrite(); 315 316 if (_lob instanceof Blob ) { 317 Blob blob = (Blob ) _lob; 318 InputStream is = blob.getBinaryStream(); 319 is.skip(start); 320 writeStream.writeStream(is); 321 is.close(); 322 } else if (_lob instanceof Clob ) { 323 Clob clob = (Clob ) _lob; 324 Reader reader = clob.getCharacterStream(); 325 reader.skip(start); 326 writeStream.writeStream(reader); 327 reader.close(); 328 } else { 329 writeStream.close(); 330 return false; 331 } 332 333 writeStream.close(); 334 return true; 335 336 } catch (Exception ex) { 337 log.log(Level.FINE, ex.toString(), ex); 338 return false; 339 } 340 } 341 342 345 public boolean flush(Env env, 346 @Optional("-1") int flag) 347 { 348 try { 349 350 if (_outputStream != null) { 351 _outputStream.flush(); 352 } 353 354 if (_writer != null) { 355 _writer.flush(); 356 } 357 358 if (flag == OracleModule.OCI_LOB_BUFFER_FREE) { 359 close(env); 360 } 361 362 return true; 363 364 } catch (Exception ex) { 365 log.log(Level.FINE, ex.toString(), ex); 366 return false; 367 } 368 } 369 370 371 374 public boolean free(Env env) 375 { 376 try { 377 378 _lob = null; 379 380 return true; 381 382 } catch (Exception ex) { 383 log.log(Level.FINE, ex.toString(), ex); 384 return false; 385 } 386 } 387 388 391 public boolean getBuffering(Env env) 392 { 393 return true; 395 } 396 397 400 public boolean quercus_import(Env env, 401 Path file) 402 { 403 try { 404 405 ReadStream readStream = file.openRead(); 406 407 if (_lob instanceof Blob ) { 408 Blob blob = (Blob ) _lob; 409 blob.truncate(0); 410 if (_outputStream != null) { 411 _outputStream.close(); 412 } 413 _outputStream = blob.setBinaryStream(0); 414 long nbytes; 415 byte buffer[] = new byte[128]; 416 while ((nbytes = readStream.read(buffer, 0, 128)) > 0) { 417 _outputStream.write(buffer, 0, (int) nbytes); 418 _currentPointer += nbytes; 419 } 420 } else if (_lob instanceof Clob ) { 421 Clob clob = (Clob ) _lob; 422 clob.truncate(0); 423 if (_writer != null) { 424 _writer.close(); 425 } 426 _writer = clob.setCharacterStream(0); 427 long nchars; 428 char buffer[] = new char[128]; 429 while ((nchars = readStream.read(buffer, 0, 128)) > 0) { 430 _writer.write(buffer, 0, (int) nchars); 431 _currentPointer += nchars; 432 } 433 } else { 434 readStream.close(); 435 return false; 436 } 437 438 readStream.close(); 439 return true; 440 441 } catch (Exception ex) { 442 log.log(Level.FINE, ex.toString(), ex); 443 return false; 444 } 445 } 446 447 450 @ReturnNullAsFalse 451 public Object load(Env env) 452 { 453 try { 454 switch (_type) { 455 case OracleModule.OCI_D_FILE: 456 break; 457 case OracleModule.OCI_D_LOB: 458 if (_lob instanceof Blob ) { 459 return readInternalBlob(env, -1); 460 } else if (_lob instanceof Clob ) { 461 return readInternalClob(env, -1); 462 } 463 break; 464 case OracleModule.OCI_D_ROWID: 465 break; 466 } 467 468 } catch (Exception ex) { 469 log.log(Level.FINE, ex.toString(), ex); 470 } 471 472 return null; 473 } 474 475 478 @ReturnNullAsFalse 479 public Object read(Env env, 480 long length) 481 { 482 try { 483 484 switch (_type) { 485 case OracleModule.OCI_D_FILE: 486 break; 487 case OracleModule.OCI_D_LOB: 488 if (_lob instanceof Blob ) { 489 return readInternalBlob(env, length); 490 } else if (_lob instanceof Clob ) { 491 return readInternalClob(env, length); 492 } 493 break; 494 case OracleModule.OCI_D_ROWID: 495 break; 496 } 497 498 } catch (Exception ex) { 499 log.log(Level.FINE, ex.toString(), ex); 500 } 501 502 return null; 503 } 504 505 508 public boolean rewind(Env env) 509 { 510 return seek(env, 0, OracleModule.OCI_SEEK_SET); 511 } 512 513 514 517 public boolean save(Env env, 518 @NotNull String data, 519 @Optional("0") long offset) 520 { 521 try { 522 523 switch (_type) { 524 case OracleModule.OCI_D_FILE: 525 break; 526 case OracleModule.OCI_D_LOB: 527 if (_lob instanceof Blob ) { 528 Blob blob = (Blob ) _lob; 529 if (_outputStream != null) { 530 _outputStream.close(); 531 } 532 _outputStream = blob.setBinaryStream(offset); 533 _outputStream.write(data.getBytes()); 534 } else if (_lob instanceof Clob ) { 535 Clob clob = (Clob ) _lob; 536 if (_writer != null) { 537 _writer.close(); 538 } 539 _writer = clob.setCharacterStream(offset); 540 _writer.write(data); 541 } 542 _currentPointer = offset + data.length(); 543 break; 544 case OracleModule.OCI_D_ROWID: 545 break; 546 } 547 548 return true; 549 550 } catch (Exception ex) { 551 log.log(Level.FINE, ex.toString(), ex); 552 return false; 553 } 554 } 555 556 559 public boolean saveFile(Env env, 560 Path file) 561 { 562 return quercus_import(env, file); 563 } 564 565 568 public boolean seek(Env env, 569 long offset, 570 @Optional("-1") int whence) 571 { 572 try { 573 574 switch (whence) { 575 case OracleModule.OCI_SEEK_SET: 576 _currentPointer = offset; 577 break; 578 case OracleModule.OCI_SEEK_END: 579 long length = 0; 580 if (_lob instanceof Blob ) { 581 length = ((Blob ) _lob).length(); 582 } else if (_lob instanceof Clob ) { 583 length = ((Clob ) _lob).length(); 584 } else { 585 L.l("Unable to determine large object's length trying to seek with OCI_SEEK_END"); 586 return false; 587 } 588 _currentPointer = length + offset; 589 break; 590 default: _currentPointer += offset; 592 } 593 594 return true; 595 596 } catch (Exception ex) { 597 log.log(Level.FINE, ex.toString(), ex); 598 return false; 599 } 600 } 601 602 605 public boolean setBuffering(Env env, 606 boolean onOff) 607 { 608 return true; 610 } 611 612 613 616 protected void setLob(Object lob) { 617 _lob = lob; 618 } 619 620 623 @ReturnNullAsFalse 624 public LongValue size(Env env) 625 { 626 try { 627 628 switch (_type) { 629 case OracleModule.OCI_D_FILE: 630 break; 631 case OracleModule.OCI_D_LOB: 632 if (_lob instanceof Blob ) { 633 Blob blob = (Blob ) _lob; 634 return LongValue.create(blob.length()); 635 } else if (_lob instanceof Clob ) { 636 Clob clob = (Clob ) _lob; 637 return LongValue.create(clob.length()); 638 } 639 break; 640 case OracleModule.OCI_D_ROWID: 641 break; 642 } 643 644 } catch (Exception ex) { 645 log.log(Level.FINE, ex.toString(), ex); 646 } 647 648 return null; 649 } 650 651 654 @ReturnNullAsFalse 655 public LongValue tell(Env env) 656 { 657 try { 658 659 return LongValue.create(_currentPointer); 660 661 } catch (Exception ex) { 662 log.log(Level.FINE, ex.toString(), ex); 663 return null; 664 } 665 } 666 667 public String toString() { 668 669 String typeName = "UNKNOWN"; 670 671 switch (_type) { 672 case OracleModule.OCI_D_FILE: 673 typeName = "OCI_D_FILE"; 674 break; 675 case OracleModule.OCI_D_LOB: 676 typeName = "OCI_D_LOB"; 677 break; 678 case OracleModule.OCI_D_ROWID: 679 typeName = "OCI_D_ROWID"; 680 break; 681 } 682 683 return "OracleOciLob("+typeName+")"; 684 } 685 686 689 public boolean truncate(Env env, 690 @Optional("0") long length) 691 { 692 try { 693 694 switch (_type) { 695 case OracleModule.OCI_D_FILE: 696 break; 697 case OracleModule.OCI_D_LOB: 698 if (_lob instanceof Blob ) { 699 Blob blob = (Blob ) _lob; 700 blob.truncate(length); 701 } else if (_lob instanceof Clob ) { 702 Clob clob = (Clob ) _lob; 703 clob.truncate(length); 704 } 705 break; 706 case OracleModule.OCI_D_ROWID: 707 break; 708 } 709 710 return true; 711 712 } catch (Exception ex) { 713 log.log(Level.FINE, ex.toString(), ex); 714 return false; 715 } 716 } 717 718 721 @ReturnNullAsFalse 722 public LongValue write(Env env, 723 String data, 724 @Optional("-1") long length) 725 { 726 try { 727 728 long dataLength = data.length(); 729 730 if ((length < 0) || (length > dataLength)) { 731 length = dataLength; 732 } 733 734 switch (_type) { 735 case OracleModule.OCI_D_FILE: 736 break; 737 case OracleModule.OCI_D_LOB: 738 long written = 0; 739 if (_lob instanceof Blob ) { 740 Blob blob = (Blob ) _lob; 741 if (_outputStream == null) { 742 _outputStream = blob.setBinaryStream(0); 743 } 744 _outputStream.write(data.getBytes()); 745 } else if (_lob instanceof Clob ) { 746 Clob clob = (Clob ) _lob; 747 if (_writer == null) { 748 _writer = clob.setCharacterStream(0); 749 } 750 _writer.write(data); 751 } 752 _currentPointer += length; 753 break; 754 case OracleModule.OCI_D_ROWID: 755 break; 756 } 757 758 } catch (Exception ex) { 759 log.log(Level.FINE, ex.toString(), ex); 760 } 761 762 return null; 763 } 764 765 768 public boolean writeTemporary(Env env, 769 String data, 770 @Optional("-1") int lobType) 771 { 772 try { 773 774 if (_type != OracleModule.OCI_D_LOB) { 775 L.l("Unable to write a temporary LOB into a non-lob object"); 776 return false; 777 } 778 779 if (lobType == OracleModule.OCI_TEMP_BLOB) { 780 _lob = createTemporaryBLOB.invoke(classOracleBLOB, 781 new Object [] {_conn, 782 true, 783 BLOB_DURATION_SESSION}); 784 } else { 785 _lob = createTemporaryCLOB.invoke(classOracleCLOB, 786 new Object [] {_conn, 787 true, 788 CLOB_DURATION_SESSION}); 789 } 790 791 return true; 792 793 } catch (Exception ex) { 794 log.log(Level.FINE, ex.toString(), ex); 795 return false; 796 } 797 } 798 799 802 public boolean writeToFile(Env env, 803 Path file, 804 @Optional("0") long start, 805 @Optional("-1") long length) 806 { 807 return export(env, file, start, length); 808 } 809 810 private boolean appendInternalBlob(Env env, 811 OracleOciLob lobFrom) 812 { 813 try { 814 815 Blob blob = (Blob ) _lob; 816 long blobLength = blob.length(); 817 if (_currentPointer != blobLength) { 818 if (_outputStream != null) { 819 _outputStream.close(); 820 } 821 _outputStream = blob.setBinaryStream(blobLength); 822 _currentPointer = blobLength; 823 } 824 825 Blob blobFrom = (Blob ) lobFrom; 826 InputStream is = blobFrom.getBinaryStream(); 827 828 long nbytes; 829 byte buffer[] = new byte[128]; 830 while ((nbytes = is.read(buffer)) > 0) { 831 _outputStream.write(buffer, 0, (int) nbytes); 832 _currentPointer += nbytes; 833 } 834 835 is.close(); 836 838 return true; 839 840 } catch (Exception ex) { 841 log.log(Level.FINE, ex.toString(), ex); 842 return false; 843 } 844 } 845 846 private boolean appendInternalClob(Env env, 847 OracleOciLob lobFrom) 848 { 849 try { 850 851 Clob clob = (Clob ) _lob; 852 long clobLength = clob.length(); 853 if (_currentPointer != clobLength) { 854 if (_writer != null) { 855 _writer.close(); 856 } 857 _writer = clob.setCharacterStream(clobLength); 858 _currentPointer = clobLength; 859 } 860 861 Clob clobFrom = (Clob ) lobFrom; 862 Reader reader = clobFrom.getCharacterStream(); 863 864 long nchars; 865 char buffer[] = new char[128]; 866 while ((nchars = reader.read(buffer)) > 0) { 867 _writer.write(buffer, 0, (int) nchars); 868 _currentPointer += nchars; 869 } 870 871 reader.close(); 872 874 return true; 875 876 } catch (Exception ex) { 877 log.log(Level.FINE, ex.toString(), ex); 878 return false; 879 } 880 } 881 882 private BinaryBuilderValue readInternalBlob(Env env, 883 long length) 884 { 885 try { 886 887 BinaryBuilderValue contents = new BinaryBuilderValue(); 888 889 Blob blob = (Blob ) _lob; 890 InputStream is = blob.getBinaryStream(); 891 is.skip(_currentPointer); 892 893 long remaining = length < 0 ? Integer.MAX_VALUE : length; 894 895 long nbytes; 896 byte buffer[] = new byte[128]; 897 while ( (remaining > 0) && 898 ((nbytes = is.read(buffer)) > 0) ) { 899 if (nbytes > remaining) 900 nbytes = remaining; 901 contents.append(buffer, 0, (int) nbytes); 902 remaining -= nbytes; 903 } 904 905 is.close(); 906 907 return contents; 908 909 } catch (Exception ex) { 910 log.log(Level.FINE, ex.toString(), ex); 911 return null; 912 } 913 } 914 915 private StringBuilderValue readInternalClob(Env env, 916 long length) 917 { 918 try { 919 920 StringBuilderValue contents = new StringBuilderValue(); 921 922 Clob clob = (Clob ) _lob; 923 Reader reader = clob.getCharacterStream(); 924 reader.skip(_currentPointer); 925 926 long remaining = length < 0 ? Integer.MAX_VALUE : length; 927 928 long nchars; 929 char buffer[] = new char[128]; 930 while ( (remaining > 0) && 931 ((nchars = reader.read(buffer)) > 0) ) { 932 if (nchars > remaining) 933 nchars = remaining; 934 contents.append(buffer, 0, (int) nchars); 935 remaining -= nchars; 936 } 937 938 reader.close(); 939 940 return contents; 941 942 } catch (Exception ex) { 943 log.log(Level.FINE, ex.toString(), ex); 944 return null; 945 } 946 } 947 } 948 | Popular Tags |