1 64 package com.jcorporate.expresso.core.dataobjects.jdbc; 65 66 import com.jcorporate.expresso.core.dataobjects.DataException; 67 import com.jcorporate.expresso.core.dataobjects.DataFieldMetaData; 68 import com.jcorporate.expresso.core.db.DBConnection; 69 import com.jcorporate.expresso.core.db.DBConnectionPool; 70 import com.jcorporate.expresso.core.db.DBException; 71 import com.jcorporate.expresso.core.db.TypeMapper; 72 import com.jcorporate.expresso.kernel.util.FastStringBuffer; 73 import org.apache.log4j.Logger; 74 75 import java.io.IOException ; 76 import java.io.InputStream ; 77 import java.io.OutputStream ; 78 import java.io.StringReader ; 79 import java.io.Writer ; 80 import java.lang.reflect.InvocationTargetException ; 81 import java.lang.reflect.Method ; 82 import java.sql.Blob ; 83 import java.sql.Clob ; 84 import java.sql.PreparedStatement ; 85 import java.sql.ResultSet ; 86 import java.sql.SQLException ; 87 88 111 112 public class LobField { 113 114 117 protected JDBCDataObject criteria = null; 118 119 122 private Logger log = Logger.getLogger(LobField.class); 123 124 boolean alreadyInTransaction = false; 125 126 protected DBConnection myConnection = null; 127 128 131 public LobField() { 132 133 } 134 135 144 public void setCriteria(JDBCDataObject newCriteria) throws DataException { 145 if (newCriteria == null) { 146 throw new IllegalArgumentException ("Criteria cannot be null"); 147 } 148 149 criteria = newCriteria; 150 if (newCriteria.getLocalConnection() != null) { 151 myConnection = newCriteria.getLocalConnection(); 152 } 153 } 154 155 156 161 protected JDBCDataObject getCriteria() { 162 return criteria; 163 } 164 165 166 176 public Blob getBlob(String fieldName) throws DataException { 177 if (getCriteria() == null) { 178 throw new IllegalArgumentException ("Criteria must be set before calling getBLob"); 179 } 180 181 try { 182 if (myConnection == null) { 183 myConnection = DBConnectionPool.getInstance(getCriteria() 184 .getMappedDataContext()).getConnection("LOB Field Connection"); 185 } 186 } catch (DBException ex) { 187 throw new DataException("Error getting Database" + 188 " Connection for BLOB Retrieval", ex); 189 } 190 191 return getBLOB(getCriteria(), fieldName, myConnection); 192 } 193 194 204 public Clob getClob(String fieldName) throws DataException { 205 if (getCriteria() == null) { 206 throw new IllegalArgumentException ("Criteria must be set before calling getClob"); 207 } 208 209 try { 210 if (myConnection == null) { 211 myConnection = DBConnectionPool.getInstance(getCriteria() 212 .getMappedDataContext()).getConnection("LOB Field Connection"); 213 } 214 } catch (DBException ex) { 215 throw new DataException("Error getting Database" + 216 " Connection for CLOB Retrieval", ex); 217 } 218 219 return getCLOB(getCriteria(), fieldName, myConnection); 220 } 221 222 223 230 public InputStream getBlobStream(String fieldName) throws DataException { 231 if (getCriteria() == null) { 232 throw new IllegalArgumentException ("Criteria must be set before calling getBLob"); 233 } 234 235 try { 236 if (myConnection == null) { 237 myConnection = DBConnectionPool.getInstance(getCriteria() 238 .getMappedDataContext()).getConnection("LOB Field Connection"); 239 } 240 } catch (DBException ex) { 241 throw new DataException("Error getting Database" + 242 " Connection for BLOB Retrieval", ex); 243 } 244 245 try { 246 prepSelectResultSet(getCriteria(), fieldName, myConnection); 247 if (myConnection.next()) { 248 return myConnection.getBinaryStream(1); 249 } else { 250 return null; 251 } 252 } catch (DBException ex) { 253 throw new DataException("Error getting binary stream", ex); 254 } 255 256 } 257 258 265 public java.io.Reader getClobStream(String fieldName) throws DataException { 266 if (getCriteria() == null) { 267 throw new IllegalArgumentException ("Criteria must be set before calling getBLob"); 268 } 269 270 try { 271 if (myConnection == null) { 272 myConnection = DBConnectionPool.getInstance(getCriteria() 273 .getMappedDataContext()).getConnection("LOB Field Connection"); 274 } 275 } catch (DBException ex) { 276 throw new DataException("Error getting Database" + 277 " Connection for BLOB Retrieval", ex); 278 } 279 280 return this.getCLOBReader(getCriteria(), fieldName, myConnection); 281 } 282 283 296 public String getClobString(String fieldName) throws DataException { 297 java.io.Reader is = this.getClobStream(fieldName); 298 if (is == null) { 299 return null; 300 } 301 302 FastStringBuffer fsb = FastStringBuffer.getInstance(); 303 try { 304 305 char[] buf = new char[1024]; int bytesRead; 307 308 while ((bytesRead = is.read(buf)) != -1) { 309 fsb.append(buf, 0, bytesRead); 310 } 311 312 return fsb.toString(); 313 } catch (java.io.IOException ex) { 314 throw new DataException("I/O Exception reading Character Stream"); 315 } finally { 316 fsb.release(); 317 } 318 319 } 320 321 328 public InputStream getClobAsciiStream(String fieldName) throws DataException { 329 try { 330 Clob theClob = getClob(fieldName); 331 return theClob.getAsciiStream(); 332 } catch (SQLException ex) { 333 throw new DataException("Error getting clob ascii stream: " + fieldName, ex); 334 } 335 } 336 337 338 349 public void saveBlob(String fieldName, InputStream data, int dataSize) throws DataException { 350 try { 351 if (myConnection == null) { 352 myConnection = DBConnectionPool.getInstance(getCriteria() 353 .getMappedDataContext()).getConnection("LOB Field Connection"); 354 355 if ("org.hsqldb.jdbcDriver".equals(myConnection.getDBDriver())) { 356 if (dataSize > 1024 * 200) { 359 throw new DataException("HSQLDB can only store maxium of 200K files"); 360 } 361 } 362 } 363 } catch (DBException ex) { 364 throw new DataException("Error getting Database" + 365 " Connection for BLOB Retrieval", ex); 366 } 367 368 try { 369 alreadyInTransaction = !(myConnection.getAutoCommit()); 370 } catch (DBException ex) { 371 throw new DataException("Error getting Database" + 372 " Connection transaction parameter for BLOB Retrieval", ex); 373 } 374 375 if ("oracle.jdbc.driver.OracleDriver".equals(myConnection.getDBDriver())) { 378 oracleSaveBlob(fieldName, data, dataSize); 379 return; 380 } 381 382 383 PreparedStatement preparedStatement = prepUpdate(getCriteria(), fieldName, myConnection); 384 385 try { 386 if (data == null) { 387 DataFieldMetaData metaData = getCriteria().getFieldMetaData(fieldName); 388 int typeCode = TypeMapper.getInstance(getCriteria().getMappedDataContext()) 389 .getJavaSQLType(metaData.getTypeString()); 390 preparedStatement.setNull(1, typeCode); 391 } else { 392 preparedStatement.setBinaryStream(1, data, dataSize); 393 } 394 } catch (SQLException ex) { 395 throw new DataException("Unable to set CharacterStream to CLOB object.", ex); 396 } catch (DBException ex) { 397 throw new DataException("Unable to get Type Mapping information for Clob field", ex); 398 } 399 400 finalizeUpdate(myConnection); 401 402 } 403 404 414 public void saveBlob(String fieldName, Blob data) throws DataException { 415 try { 416 if (myConnection == null) { 417 myConnection = DBConnectionPool.getInstance(getCriteria() 418 .getMappedDataContext()).getConnection("LOB Field Connection"); 419 } 420 } catch (DBException ex) { 421 throw new DataException("Error getting Database" + 422 " Connection for BLOB Retrieval", ex); 423 } 424 425 try { 426 alreadyInTransaction = !(myConnection.getAutoCommit()); 427 } catch (DBException ex) { 428 throw new DataException("Error getting Database" + 429 " Connection transaction parameter for BLOB Retrieval", ex); 430 } 431 PreparedStatement preparedStatement = prepUpdate(getCriteria(), fieldName, myConnection); 432 433 try { 434 if (data == null) { 435 DataFieldMetaData metaData = getCriteria().getFieldMetaData(fieldName); 436 int typeCode = TypeMapper.getInstance(getCriteria().getMappedDataContext()) 437 .getJavaSQLType(metaData.getTypeString()); 438 preparedStatement.setNull(1, typeCode); 439 } else { 440 preparedStatement.setBlob(1, data); 441 } 442 } catch (SQLException ex) { 443 throw new DataException("Unable to set CharacterStream to CLOB object.", ex); 444 } catch (DBException ex) { 445 throw new DataException("Unable to get type mapping information", ex); 446 } 447 448 finalizeUpdate(myConnection); 449 450 } 451 452 463 public void saveClob(String fieldName, InputStream data, int length) throws DataException { 464 465 try { 466 if (myConnection == null) { 467 myConnection = DBConnectionPool.getInstance(getCriteria() 468 .getMappedDataContext()).getConnection("LOB Field Connection"); 469 } 470 } catch (DBException ex) { 471 throw new DataException("Error getting Database" + 472 " Connection for BLOB Retrieval", ex); 473 } 474 475 try { 476 alreadyInTransaction = !(myConnection.getAutoCommit()); 477 } catch (DBException ex) { 478 throw new DataException("Error getting Database" + 479 " Connection transaction parameter for BLOB Retrieval", ex); 480 } 481 482 if ("oracle.jdbc.driver.OracleDriver".equals(myConnection.getDBDriver())) { 485 oracleSaveClob(fieldName, data, length); 486 return; 487 } 488 489 PreparedStatement preparedStatement = prepUpdate(getCriteria(), fieldName, myConnection); 490 491 try { 492 if (data == null) { 493 DataFieldMetaData metaData = getCriteria().getFieldMetaData(fieldName); 494 int typeCode = TypeMapper.getInstance(getCriteria().getMappedDataContext()) 495 .getJavaSQLType(metaData.getTypeString()); 496 preparedStatement.setNull(1, typeCode); 497 } else { 498 preparedStatement.setAsciiStream(1, data, length); 499 } 500 } catch (SQLException ex) { 501 throw new DataException("Unable to set CharacterStream to CLOB object.", ex); 502 } catch (DBException ex) { 503 throw new DataException("Unable to get type mapping information for CLOB object", ex); 504 } 505 506 finalizeUpdate(myConnection); 507 508 } 509 510 521 public void saveClob(String fieldName, java.io.Reader data, int length) throws DataException { 522 523 try { 524 if (myConnection == null) { 525 myConnection = DBConnectionPool.getInstance(getCriteria() 526 .getMappedDataContext()).getConnection("LOB Field Connection"); 527 } 528 } catch (DBException ex) { 529 throw new DataException("Error getting Database" + 530 " Connection for BLOB Retrieval", ex); 531 } 532 533 try { 534 alreadyInTransaction = !(myConnection.getAutoCommit()); 535 } catch (DBException ex) { 536 throw new DataException("Error getting Database" + 537 " Connection transaction parameter for BLOB Retrieval", ex); 538 } 539 540 if ("interbase.interclient.Driver".equals(myConnection.getDBDriver())) { 541 throw new DataException("InterBase Interclient 2 cannot support unicode data. " + 542 " Must use saveClob(String, InputStream, length)" + 543 "instead"); 544 } 545 546 if ("oracle.jdbc.driver.OracleDriver".equals(myConnection.getDBDriver())) { 549 if (data == null) { 550 oracleSaveClob(fieldName, (StringReader ) null, 0); 551 } else { 552 oracleSaveClob(fieldName, data, length); 553 } 554 return; 555 } 556 557 PreparedStatement preparedStatement = prepUpdate(getCriteria(), fieldName, myConnection); 558 559 try { 560 if (data == null) { 561 DataFieldMetaData metaData = getCriteria().getFieldMetaData(fieldName); 562 int typeCode = TypeMapper.getInstance(getCriteria().getMappedDataContext()) 563 .getJavaSQLType(metaData.getTypeString()); 564 preparedStatement.setNull(1, typeCode); 565 } else { 566 preparedStatement.setCharacterStream(1, data, length); 567 } 568 } catch (SQLException ex) { 569 throw new DataException("Unable to set CharacterStream to CLOB object.", ex); 570 } catch (DBException ex) { 571 throw new DataException("Unable to get type mapping information for CLOB field", ex); 572 } 573 574 finalizeUpdate(myConnection); 575 } 576 577 584 public void saveClob(String fieldName, String data) throws DataException { 585 try { 586 if (myConnection == null) { 587 myConnection = DBConnectionPool.getInstance(getCriteria() 588 .getMappedDataContext()).getConnection("LOB Field Connection"); 589 } 590 } catch (DBException ex) { 591 throw new DataException("Error getting Database" + 592 " Connection for BLOB Retrieval", ex); 593 } 594 595 try { 596 alreadyInTransaction = !(myConnection.getAutoCommit()); 597 } catch (DBException ex) { 598 throw new DataException("Error getting Database" + 599 " Connection transaction parameter for BLOB Retrieval", ex); 600 } 601 602 if ("oracle.jdbc.driver.OracleDriver".equals(myConnection.getDBDriver())) { 605 if (data == null) { 606 oracleSaveClob(fieldName, (StringReader ) null, 0); 607 } else { 608 oracleSaveClob(fieldName, new StringReader (data), data.length()); 609 } 610 return; 611 } 612 613 PreparedStatement preparedStatement = prepUpdate(getCriteria(), fieldName, myConnection); 614 615 try { 616 if (data == null) { 617 DataFieldMetaData metaData = getCriteria().getFieldMetaData(fieldName); 618 int typeCode = TypeMapper.getInstance(getCriteria().getMappedDataContext()) 619 .getJavaSQLType(metaData.getTypeString()); 620 preparedStatement.setNull(1, typeCode); 621 } else { 622 if ("interbase.interclient.Driver".equals(myConnection.getDBDriver())) { 623 byte[] dataArray = data.getBytes(); 627 java.io.ByteArrayInputStream bis = new java.io.ByteArrayInputStream (dataArray); 628 preparedStatement.setAsciiStream(1, bis, dataArray.length); 629 } else { 630 java.io.Reader r = new java.io.StringReader (data); 631 preparedStatement.setCharacterStream(1, r, data.length()); 632 } 633 } 634 } catch (SQLException ex) { 635 throw new DataException("Unable to set CharacterStream to CLOB object.", ex); 636 } catch (DBException ex) { 637 throw new DataException("Unable to get type information for CLOB field", ex); 638 } 639 640 finalizeUpdate(myConnection); 641 642 } 643 644 654 public void saveClob(String fieldName, Clob data) throws DataException { 655 656 try { 657 if (myConnection == null) { 658 myConnection = DBConnectionPool.getInstance(getCriteria() 659 .getMappedDataContext()).getConnection("LOB Field Connection"); 660 } 661 } catch (DBException ex) { 662 throw new DataException("Error getting Database" + 663 " Connection for BLOB Retrieval", ex); 664 } 665 666 try { 667 alreadyInTransaction = !(myConnection.getAutoCommit()); 668 } catch (DBException ex) { 669 throw new DataException("Error getting Database" + 670 " Connection transaction parameter for BLOB Retrieval", ex); 671 } 672 673 PreparedStatement preparedStatement = prepUpdate(getCriteria(), fieldName, myConnection); 674 675 try { 676 if (data == null) { 677 DataFieldMetaData metaData = getCriteria().getFieldMetaData(fieldName); 678 int typeCode = TypeMapper.getInstance(getCriteria().getMappedDataContext()) 679 .getJavaSQLType(metaData.getTypeString()); 680 preparedStatement.setNull(1, typeCode); 681 } else { 682 preparedStatement.setClob(1, data); 683 } 684 } catch (SQLException ex) { 685 throw new DataException("Unable to set CharacterStream to CLOB object.", ex); 686 } catch (DBException ex) { 687 throw new DataException("Unable to get type mapping information for CLOB field", ex); 688 } 689 690 finalizeUpdate(myConnection); 691 } 692 693 694 699 public void close() { 700 if (myConnection != null) { 701 if (log.isDebugEnabled()) { 702 log.debug("Closing and releasing LOB connection"); 703 } 704 try { 705 if (!alreadyInTransaction && myConnection.supportsTransactions()) { 706 myConnection.release(); 707 } 708 } catch (DBException ex) { 709 } 712 myConnection = null; 713 } 714 } 715 716 721 protected void finalize() throws java.lang.Throwable { 722 if (myConnection != null) { 723 log.warn("LobField was not closed before Garbage Collection!"); 724 close(); 725 } 726 super.finalize(); 727 } 728 729 730 742 private Clob getCLOB(JDBCDataObject baseObject, 743 String fieldName, 744 DBConnection theConnection) throws DataException { 745 prepSelectResultSet(baseObject, fieldName, theConnection); 746 747 try { 748 if (theConnection.next()) { 749 return theConnection.getClob(fieldName); 750 } 751 } catch (DBException ex) { 752 throw new DataException("Error getting CLOB object from connection", ex); 753 } 754 755 return null; 756 } 757 758 770 private java.io.Reader getCLOBReader(JDBCDataObject baseObject, 771 String fieldName, 772 DBConnection theConnection) throws DataException { 773 prepSelectResultSet(baseObject, fieldName, theConnection); 774 ResultSet rs = theConnection.getResultSet(); 775 try { 776 if (rs.next()) { 777 try { 778 return rs.getCharacterStream(1); 779 } catch (SQLException ex) { 780 return new java.io.StringReader (rs.getString(1)); 781 } 782 } 783 } catch (java.sql.SQLException ex) { 784 throw new DataException("Error getting CLOB object from connection", ex); 785 } 786 787 return null; 788 } 789 790 803 private Blob getBLOB(JDBCDataObject baseObject, 804 String fieldName, 805 DBConnection theConnection) throws DataException { 806 807 try { 808 prepSelectResultSet(baseObject, fieldName, theConnection); 809 if (theConnection.next()) { 810 return theConnection.getBlob(1); 811 } else { 812 return null; 813 } 814 } catch (DBException ex) { 815 throw new DataException("Error getting Blob Field", ex); 816 } 817 818 } 819 820 833 protected void prepSelectResultSet(JDBCDataObject baseObject, 834 String fieldName, 835 DBConnection theConnection) throws DataException { 836 try { 837 FastStringBuffer prepStatement = FastStringBuffer.getInstance(); 838 prepStatement.append("SELECT "); 839 prepStatement.append(fieldName); 840 prepStatement.append(" from "); 841 prepStatement.append(baseObject.getJDBCMetaData().getTargetSQLTable(baseObject.getDataContext())); 842 String whereClause = JDBCUtil.getInstance().buildWhereClause(baseObject, false); 843 prepStatement.append(whereClause); 844 String thePrepString = prepStatement.toString(); 845 prepStatement.release(); 846 847 if (log.isDebugEnabled()) { 848 log.debug("Preparing prepared statement: " + thePrepString); 849 } 850 851 PreparedStatement prep = theConnection.createPreparedStatement(thePrepString); 852 if (prep == null) { 853 throw new DataException("Unable to create prepared statement for CLOB retrieval." + 854 " Check DBConnection log for details"); 855 } 856 theConnection.execute(); 857 858 if (log.isDebugEnabled()) { 859 log.debug("Succesfully executed prepared statement"); 860 } 861 } catch (DBException ex) { 862 throw new DataException("Error prepping SELECT ResultSet", ex); 863 } 864 } 865 866 876 protected PreparedStatement prepUpdate(JDBCDataObject baseObject, 877 String fieldName, 878 DBConnection theConnection) throws DataException { 879 try { 880 String whereClause = JDBCUtil.getInstance().buildWhereClause(baseObject, false); 881 882 FastStringBuffer prepStatement = FastStringBuffer.getInstance(); 883 String theSQL = null; 884 try { 885 prepStatement.append("UPDATE "); 886 prepStatement.append(baseObject.getJDBCMetaData().getTargetSQLTable(baseObject.getDataContext())); 887 prepStatement.append(" SET "); 888 prepStatement.append(fieldName); 889 prepStatement.append(" = ? "); 890 prepStatement.append(whereClause); 891 theSQL = prepStatement.toString(); 892 } finally { 893 prepStatement.release(); 894 prepStatement = null; 895 } 896 897 return theConnection.createPreparedStatement(theSQL); 898 } catch (DBException ex) { 899 throw new DataException("Error prepping LOB update", ex); 900 } 901 } 902 903 protected void finalizeUpdate(DBConnection theConnection) throws DataException { 904 905 try { 906 boolean success = false; 907 908 if (!alreadyInTransaction && theConnection.supportsTransactions()) { 914 if (log.isDebugEnabled()) { 915 log.debug("Turning off auto-commit"); 916 } 917 theConnection.setAutoCommit(false); 918 } 919 920 try { 921 theConnection.executeUpdate(null); 922 success = true; 923 } finally { 924 if (success == false) { 925 if (!alreadyInTransaction && theConnection.supportsTransactions()) { 926 if (log.isDebugEnabled()) { 927 log.debug("rolling back"); 928 } 929 theConnection.rollback(); 930 } 931 } 932 if (!alreadyInTransaction && theConnection.supportsTransactions()) { 933 if (log.isDebugEnabled()) { 934 log.debug("Finishing commit and turning auto-commit back to true"); 935 } 936 theConnection.commit(); 937 theConnection.setAutoCommit(true); 938 } 939 } 940 } catch (DBException ex) { 941 throw new DataException("Error finalizing LOB update", ex); 942 } 943 944 } 945 946 957 private void setBLOB(JDBCDataObject baseObject, 958 String fieldName, 959 InputStream theData, 960 int dataLength, 961 DBConnection theConnection) throws DBException { 962 PreparedStatement preparedStatement = prepUpdate(baseObject, fieldName, theConnection); 963 964 965 try { 966 967 preparedStatement.setBinaryStream(1, theData, dataLength); 968 } catch (SQLException ex) { 969 throw new DBException("Error setting BLOB object", ex); 970 } 971 972 973 finalizeUpdate(theConnection); 974 } 975 976 986 private void setCLOB(JDBCDataObject baseObject, 987 String fieldName, 988 String theData, 989 DBConnection theConnection) throws DBException { 990 991 PreparedStatement preparedStatement = prepUpdate(baseObject, fieldName, theConnection); 992 993 try { 994 if ("interbase.interclient.Driver".equals(theConnection.getDBDriver())) { 995 byte[] data = theData.getBytes(); 999 java.io.ByteArrayInputStream bis = new java.io.ByteArrayInputStream (data); 1000 preparedStatement.setAsciiStream(1, bis, data.length); 1001 } else { 1002 java.io.Reader r = new java.io.StringReader (theData); 1003 preparedStatement.setCharacterStream(1, r, theData.length()); 1004 } 1005 } catch (SQLException ex) { 1006 throw new DBException("Unable to set CharacterStream to CLOB object.", ex); 1007 } 1008 1009 finalizeUpdate(theConnection); 1010 } 1011 1012 1013 1027 private void oracleSaveBlob(String fieldName, InputStream data, int dataSize) throws DataException { 1028 try { 1029 if (myConnection == null) { 1030 myConnection = DBConnectionPool.getInstance(getCriteria() 1031 .getMappedDataContext()).getConnection("LOB Field Connection"); 1032 } 1033 } catch (DBException ex) { 1034 throw new DataException("Error getting Database" + 1035 " Connection for BLOB Retrieval", ex); 1036 } 1037 1038 oraclePrepUpdateEmptyLob(getCriteria(), fieldName, myConnection); 1041 1042 try { 1043 if (data != null) { 1044 oraclePrepSelectForUpdate(getCriteria(), fieldName, myConnection); 1045 if (myConnection.next()) { 1046 Class oracleResultSetClass = Class.forName("oracle.jdbc.driver.OracleResultSet"); 1051 Class [] parameterTypes = new Class []{int.class}; 1052 Object [] arguments = new Object []{new Integer (1)}; 1053 Method getBlobMethod = oracleResultSetClass.getMethod("getBlob", parameterTypes); 1054 Object blob = getBlobMethod.invoke((Object ) myConnection.getResultSet(), arguments); 1055 1056 parameterTypes = new Class []{}; 1057 arguments = new Object []{}; 1058 Class oracleBlobClass = Class.forName("oracle.sql.BLOB"); 1059 Method getBinaryOutputStreamMethod = oracleBlobClass.getMethod("getBinaryOutputStream", 1060 parameterTypes); 1061 OutputStream oBlob = (OutputStream ) getBinaryOutputStreamMethod.invoke(blob, arguments); 1062 1063 Method getChunkSizeMethod = oracleBlobClass.getMethod("getChunkSize", parameterTypes); 1064 byte[] chunk = new byte[((Integer ) getChunkSizeMethod.invoke(blob, arguments)).intValue()]; 1065 1066 1067 int i = -1; 1068 while ((i = data.read(chunk)) != -1) { 1069 oBlob.write(chunk, 0, i); 1070 } 1071 1072 oBlob.close(); 1073 data.close(); 1074 if (!alreadyInTransaction && myConnection.supportsTransactions()) { 1076 myConnection.commit(); 1077 } 1078 } else { 1079 throw new DataException("Error SELECTing record for update."); 1080 } 1081 } 1082 } catch (DBException ex) { 1083 throw new DataException("Error SELECTing record for update.", ex); 1084 } catch (NoSuchMethodException ex) { 1085 throw new DataException("Reflection error on oracle classes.", ex); 1086 } catch (IllegalAccessException ex) { 1087 throw new DataException("Reflection error on oracle classes.", ex); 1088 } catch (InvocationTargetException ex) { 1089 throw new DataException("Reflection error on oracle classes.", ex); 1090 } catch (ClassNotFoundException ex) { 1091 throw new DataException("Reflection error on oracle classes.", ex); 1092 } catch (IOException ex) { 1093 throw new DataException("Error reading from InputStream.", ex); 1094 } 1095 } 1096 1097 1111 private void oracleSaveClob(String fieldName, InputStream data, int length) throws DataException { 1112 1113 try { 1114 if (myConnection == null) { 1115 myConnection = DBConnectionPool.getInstance(getCriteria() 1116 .getMappedDataContext()).getConnection("LOB Field Connection"); 1117 } 1118 } catch (DBException ex) { 1119 throw new DataException("Error getting Database" + 1120 " Connection for CLOB Retrieval", ex); 1121 } 1122 1123 if (data == null) { 1124 oraclePrepUpdateNullClob(getCriteria(), fieldName, myConnection); 1125 return; 1126 } 1127 1128 oraclePrepUpdateEmptyLob(getCriteria(), fieldName, myConnection); 1131 1132 try { 1133 oraclePrepSelectForUpdate(getCriteria(), fieldName, myConnection); 1134 if (myConnection.next()) { 1135 Class oracleResultSetClass = Class.forName("oracle.jdbc.driver.OracleResultSet"); 1140 Class [] parameterTypes = new Class []{int.class}; 1141 Object [] arguments = new Object []{new Integer (1)}; 1142 Method getClobMethod = oracleResultSetClass.getMethod("getClob", parameterTypes); 1143 Object clob = getClobMethod.invoke((Object ) myConnection.getResultSet(), arguments); 1144 1145 parameterTypes = new Class []{}; 1146 arguments = new Object []{}; 1147 Class oracleClobClass = Class.forName("oracle.sql.CLOB"); 1148 Method getAsciiOutputStreamMethod = oracleClobClass.getMethod("getAsciiOutputStreamMethod", 1149 parameterTypes); 1150 OutputStream oClob = (OutputStream ) getAsciiOutputStreamMethod.invoke(clob, arguments); 1151 1152 Method getChunkSizeMethod = oracleClobClass.getMethod("getChunkSize", parameterTypes); 1153 byte[] chunk = new byte[((Integer ) getChunkSizeMethod.invoke(clob, arguments)).intValue()]; 1154 1155 1156 int i = -1; 1157 while ((i = data.read(chunk)) != -1) { 1158 oClob.write(chunk, 0, i); 1159 } 1160 1161 oClob.close(); 1162 data.close(); 1163 if (!alreadyInTransaction && myConnection.supportsTransactions()) { 1165 myConnection.commit(); 1166 } 1167 } else { 1168 throw new DataException("Error SELECTing record for update."); 1169 } 1170 } catch (DBException ex) { 1171 throw new DataException("Error SELECTing record for update.", ex); 1172 } catch (NoSuchMethodException ex) { 1173 throw new DataException("Reflection error on oracle classes.", ex); 1174 } catch (IllegalAccessException ex) { 1175 throw new DataException("Reflection error on oracle classes.", ex); 1176 } catch (InvocationTargetException ex) { 1177 throw new DataException("Reflection error on oracle classes.", ex); 1178 } catch (ClassNotFoundException ex) { 1179 throw new DataException("Reflection error on oracle classes.", ex); 1180 } catch (IOException ex) { 1181 throw new DataException("Error reading from InputStream.", ex); 1182 } 1183 } 1184 1185 1200 private void oracleSaveClob(String fieldName, java.io.Reader data, int length) throws DataException { 1201 try { 1202 if (myConnection == null) { 1203 myConnection = DBConnectionPool.getInstance(getCriteria() 1204 .getMappedDataContext()).getConnection("LOB Field Connection"); 1205 } 1206 } catch (DBException ex) { 1207 throw new DataException("Error getting Database" + 1208 " Connection for CLOB Retrieval", ex); 1209 } 1210 1211 if (data == null) { 1212 oraclePrepUpdateNullClob(getCriteria(), fieldName, myConnection); 1213 return; 1214 } 1215 1216 oraclePrepUpdateEmptyLob(getCriteria(), fieldName, myConnection); 1219 1220 try { 1221 oraclePrepSelectForUpdate(getCriteria(), fieldName, myConnection); 1222 if (myConnection.next()) { 1223 Class oracleResultSetClass = Class.forName("oracle.jdbc.driver.OracleResultSet"); 1228 Class [] parameterTypes = new Class []{int.class}; 1229 Object [] arguments = new Object []{new Integer (1)}; 1230 Method getClobMethod = oracleResultSetClass.getMethod("getClob", parameterTypes); 1231 Object clob = getClobMethod.invoke((Object ) myConnection.getResultSet(), arguments); 1232 1233 parameterTypes = new Class []{}; 1234 arguments = new Object []{}; 1235 Class oracleClobClass = Class.forName("oracle.sql.CLOB"); 1236 Method getCharacterOutputStream = oracleClobClass.getMethod("getCharacterOutputStream", parameterTypes); 1237 Writer oClob = (Writer ) getCharacterOutputStream.invoke(clob, arguments); 1238 1239 Method getChunkSizeMethod = oracleClobClass.getMethod("getChunkSize", parameterTypes); 1240 char[] chunk = new char[((Integer ) getChunkSizeMethod.invoke(clob, arguments)).intValue()]; 1241 1242 1243 int i = -1; 1244 while ((i = data.read(chunk)) != -1) { 1245 oClob.write(chunk, 0, i); 1246 } 1247 1248 oClob.close(); 1249 data.close(); 1250 if (!alreadyInTransaction && myConnection.supportsTransactions()) { 1252 myConnection.commit(); 1253 } 1254 } else { 1255 throw new DataException("Error SELECTing record for update."); 1256 } 1257 } catch (DBException ex) { 1258 throw new DataException("Error SELECTing record for update.", ex); 1259 } catch (NoSuchMethodException ex) { 1260 throw new DataException("Reflection error on oracle classes.", ex); 1261 } catch (IllegalAccessException ex) { 1262 throw new DataException("Reflection error on oracle classes.", ex); 1263 } catch (InvocationTargetException ex) { 1264 throw new DataException("Reflection error on oracle classes.", ex); 1265 } catch (ClassNotFoundException ex) { 1266 throw new DataException("Reflection error on oracle classes.", ex); 1267 } catch (IOException ex) { 1268 throw new DataException("Error reading from InputStream.", ex); 1269 } 1270 } 1271 1272 1284 private void oraclePrepUpdateEmptyLob(JDBCDataObject baseObject, 1285 String fieldName, 1286 DBConnection theConnection) throws DataException { 1287 try { 1288 String whereClause = JDBCUtil.getInstance().buildWhereClause(baseObject, false); 1289 1290 FastStringBuffer prepStatement = FastStringBuffer.getInstance(); 1291 String theSQL = null; 1292 try { 1293 prepStatement.append("UPDATE "); 1294 prepStatement.append(baseObject.getJDBCMetaData().getTargetSQLTable(baseObject.getDataContext())); 1295 prepStatement.append(" SET "); 1296 prepStatement.append(fieldName); 1297 if (baseObject.getDataField(fieldName).getFieldMetaData().isCharacterLongObjectType()) { 1298 prepStatement.append(" = empty_clob() "); 1299 } else { 1300 prepStatement.append(" = empty_blob() "); 1301 } 1302 prepStatement.append(whereClause); 1303 theSQL = prepStatement.toString(); 1304 } finally { 1305 prepStatement.release(); 1306 prepStatement = null; 1307 } 1308 1309 theConnection.createPreparedStatement(theSQL); 1310 finalizeUpdate(theConnection); 1311 } catch (DBException ex) { 1312 throw new DataException("Error prepping LOB update", ex); 1313 } 1314 } 1315 1316 1328 private void oraclePrepUpdateNullClob(JDBCDataObject baseObject, 1329 String fieldName, 1330 DBConnection theConnection) throws DataException { 1331 try { 1332 String whereClause = JDBCUtil.getInstance().buildWhereClause(baseObject, false); 1333 1334 FastStringBuffer prepStatement = FastStringBuffer.getInstance(); 1335 String theSQL = null; 1336 try { 1337 prepStatement.append("UPDATE "); 1338 prepStatement.append(baseObject.getJDBCMetaData().getTargetSQLTable(baseObject.getDataContext())); 1339 prepStatement.append(" SET "); 1340 prepStatement.append(fieldName); 1341 prepStatement.append(" = null "); 1342 prepStatement.append(whereClause); 1343 theSQL = prepStatement.toString(); 1344 } finally { 1345 prepStatement.release(); 1346 prepStatement = null; 1347 } 1348 1349 theConnection.createPreparedStatement(theSQL); 1350 finalizeUpdate(theConnection); 1351 } catch (DBException ex) { 1352 throw new DataException("Error prepping CLOB update", ex); 1353 } 1354 } 1355 1356 1368 protected void oraclePrepSelectForUpdate(JDBCDataObject baseObject, 1369 String fieldName, 1370 DBConnection theConnection) throws DataException { 1371 try { 1372 FastStringBuffer prepStatement = FastStringBuffer.getInstance(); 1373 prepStatement.append("SELECT "); 1374 prepStatement.append(fieldName); 1375 prepStatement.append(" from "); 1376 prepStatement.append(baseObject.getJDBCMetaData().getTargetSQLTable(baseObject.getDataContext())); 1377 String whereClause = JDBCUtil.getInstance().buildWhereClause(baseObject, false); 1378 prepStatement.append(whereClause); 1379 prepStatement.append(" FOR UPDATE"); 1380 String thePrepString = prepStatement.toString(); 1381 prepStatement.release(); 1382 1383 if (log.isDebugEnabled()) { 1384 log.debug("Preparing prepared statement: " + thePrepString); 1385 } 1386 1387 PreparedStatement prep = theConnection.createPreparedStatement(thePrepString); 1388 if (prep == null) { 1389 throw new DataException("Unable to create prepared statement for CLOB retrieval." + 1390 " Check DBConnection log for details"); 1391 } 1392 if (!alreadyInTransaction && theConnection.supportsTransactions()) { 1393 theConnection.setAutoCommit(false); 1394 } 1395 theConnection.execute(); 1396 1397 if (log.isDebugEnabled()) { 1398 log.debug("Succesfully executed prepared statement"); 1399 } 1400 } catch (DBException ex) { 1401 throw new DataException("Error prepping SELECT ResultSet", ex); 1402 } 1403 } 1404 1405} 1406 | Popular Tags |