| 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
|