1 25 package com.lutris.appserver.server.sql.datasource; 26 27 import java.sql.CallableStatement ; 28 import java.sql.Connection ; 29 import java.sql.DriverManager ; 30 import java.sql.PreparedStatement ; 31 import java.sql.ResultSet ; 32 import java.sql.SQLException ; 33 import java.sql.SQLWarning ; 34 import java.sql.Statement ; 35 import java.util.Enumeration ; 36 import java.util.Hashtable ; 37 38 import javax.sql.DataSource ; 39 40 import org.enhydra.dods.Common; 41 import org.enhydra.dods.DODS; 42 43 import com.lutris.appserver.server.sql.ConnectionAllocator; 44 import com.lutris.appserver.server.sql.DBConnection; 45 import com.lutris.appserver.server.sql.DatabaseManagerException; 46 import com.lutris.appserver.server.sql.ExtendedConnectionAllocator; 47 import com.lutris.appserver.server.sql.ExtendedDBConnection; 48 import com.lutris.appserver.server.sql.standard.StandardLogicalDatabase; 49 import com.lutris.logging.Logger; 50 51 60 public class SimpleDataSourceDBConnection implements ExtendedDBConnection { 61 62 63 protected Connection connection; 64 65 66 protected String url; 67 68 69 protected String user; 70 71 protected DataSource ds; 72 73 74 protected String password; 75 protected int id; 77 protected static int nextId = 0; 79 protected Hashtable preparedStmtCache; 81 protected Statement currentStmt = null; 83 protected ConnectionAllocator connectionAllocator; 85 protected boolean logging; 87 protected int generation; 89 protected boolean closed = false; 91 protected boolean dropConnection = false; 93 protected boolean dropped = false; 95 protected boolean reset = true; 97 protected boolean allocated = false; 99 protected int maxPreparedStmts; 101 protected int connectionUsageCounter=0; 103 protected long connectionEnterPoolTime = -1; 105 108 110 125 public SimpleDataSourceDBConnection(ConnectionAllocator connectionAllocatorObj, 126 String url, String user, String password, int maxPreparedStatements, 127 boolean logging, int generation) 128 throws SQLException { 129 id = nextId++; 130 this.preparedStmtCache = new Hashtable (); 131 this.connectionAllocator = connectionAllocatorObj; 132 this.url = url; 133 this.user = user; 134 this.password = password; 135 this.logging = logging; 136 this.generation = generation; 137 connection = DriverManager.getConnection(url, user, password); 138 139 currentStmt = connection.createStatement(); 140 if (maxPreparedStatements < 0) { 141 this.maxPreparedStmts = connection.getMetaData().getMaxStatements() 143 - 1; 144 if (this.maxPreparedStmts == 0) { 145 this.maxPreparedStmts = 1; 149 } 150 if (this.maxPreparedStmts < 0) { 151 this.maxPreparedStmts = 256; 155 } 156 } else { 157 this.maxPreparedStmts = maxPreparedStatements; 158 } 159 logDebug("DBConnection[" + id + "]: " + url 160 + "\nNew connection allocated.\n"); 161 connectionEnterPoolTime = System.currentTimeMillis(); 162 } 163 177 protected SimpleDataSourceDBConnection(ConnectionAllocator connectionAllocatorObj, 178 DataSource dataSource, int maxPreparedStatements, 179 boolean logging, int generation) 180 throws SQLException { 181 id = nextId++; 182 this.preparedStmtCache = new Hashtable (); 183 this.connectionAllocator = connectionAllocatorObj; 184 this.ds = dataSource; 185 this.logging = logging; 186 this.generation = generation; 187 188 connection = ds.getConnection(); 189 190 currentStmt = connection.createStatement(); 191 if (maxPreparedStatements < 0) { 192 this.maxPreparedStmts = connection.getMetaData().getMaxStatements() 194 - 1; 195 if (this.maxPreparedStmts == 0) { 196 this.maxPreparedStmts = 1; 200 } 201 if (this.maxPreparedStmts < 0) { 202 this.maxPreparedStmts = 256; 206 } 207 } else { 208 this.maxPreparedStmts = maxPreparedStatements; 209 } 210 logDebug("DBConnection[" + id + "]: " 211 + "\nNew connection allocated.\n"); 212 connectionEnterPoolTime = System.currentTimeMillis(); 213 } 214 215 222 public synchronized void allocate() throws SQLException { 223 logDebug("allocate"); 224 try { 225 closedCheck(); 226 reset(); 227 } catch (SQLException e) { 228 handleException(e); 229 if (dropConnection) { 234 drop(); 235 } else { 236 release(); 237 } 238 throw e; 239 } 240 reset = false; 241 allocated = true; 242 } 243 244 253 protected void resetCheck() throws SQLException { 254 logDebug("resetCheck()"); 255 if (!reset) { 256 throw new java.sql.SQLException ("DBConnection.reset() was not called after the previous " 257 + "operation completed"); 258 } 259 } 260 261 268 protected void allocatedCheck() throws SQLException { 269 logDebug("allocatedCheck()"); 270 if (!allocated) { 271 throw new java.sql.SQLException ("attempt to access connection which was released."); 272 } 273 } 274 275 282 protected void closedCheck() throws SQLException { 283 logDebug("closedCheck()"); 284 if (closed || getConnection().isClosed()) { 285 throw new java.sql.SQLException ("attempt to access a closed connection."); 286 } 287 } 288 289 296 public void validate() throws SQLException { 297 logDebug("validate()"); 298 allocatedCheck(); 299 closedCheck(); 300 } 301 302 307 public synchronized void reset() throws SQLException { 308 SQLException saveExcept = null; 310 311 if (reset) { 312 return; 313 } 314 logDebug("reset"); 315 try { 316 connection.clearWarnings(); 317 } catch (SQLException except) { 318 if (saveExcept == null) { 319 saveExcept = except; 320 } 321 } 322 try { 323 connection.setAutoCommit(false); 324 } catch (SQLException except) { 325 if (saveExcept == null) { 326 saveExcept = except; 327 } 328 } 329 reset = true; 330 if (saveExcept != null) { 334 throw saveExcept; 335 } 336 } 337 338 349 public synchronized PreparedStatement prepareStatement(String sql) 350 throws SQLException { 351 return _prepareStatement(sql, -100, -100, false); 352 } 353 354 private synchronized PreparedStatement _prepareStatement(String sql, int iResultSetType, int iResultSetConcurrency, boolean tuned) 355 throws SQLException { 356 PreparedStatement preparedStmt = null; 357 String mapKey = sql+"=+=+"+iResultSetType+"=+=+"+iResultSetConcurrency+"=+=+"; 358 if (tuned){ 359 mapKey=mapKey+"tuned"; 360 } 361 logDebug("Prepare statement: " + sql); 362 validate(); 363 boolean selectQuery = sql.trim().toLowerCase().startsWith("select"); 364 if(maxPreparedStmts>0 && !selectQuery){ 365 preparedStmt = (PreparedStatement ) preparedStmtCache.get(mapKey); 366 if ((preparedStmt != null) && (!preparedStmt.getConnection().isClosed())) { 367 preparedStmt.clearParameters(); 368 } else { 369 if (preparedStmtCache.size() >= maxPreparedStmts) { 370 String key = (String ) preparedStmtCache.keys().nextElement(); 371 ((PreparedStatement ) preparedStmtCache.remove(key)).close(); 372 } 373 preparedStmt = getNewPrepStatemet(sql, iResultSetType, iResultSetConcurrency, tuned); 374 preparedStmtCache.put(mapKey, preparedStmt); 375 } 376 }else{ 377 preparedStmt = getNewPrepStatemet(sql, iResultSetType, iResultSetConcurrency, tuned); 378 } 379 return preparedStmt; 380 } 381 382 383 391 private PreparedStatement getNewPrepStatemet(String sql, int iResultSetType, int iResultSetConcurrency, boolean tuned) throws SQLException { 392 PreparedStatement preparedStmt; 393 if(!tuned){ 394 if(getResultSetType()==StandardLogicalDatabase.DEFAULT_RESULT_SET_TYPE || 395 getResultSetConcurrency()==StandardLogicalDatabase.DEFAULT_RESULT_SET_CONCURRENCY){ 396 preparedStmt = connection.prepareStatement(sql); 397 } 398 else { 399 preparedStmt = connection.prepareStatement(sql,getResultSetType(),getResultSetConcurrency()); 400 } 401 }else{ 402 preparedStmt = connection.prepareStatement(sql,iResultSetType,iResultSetConcurrency); 403 } 404 return preparedStmt; 405 } 406 407 420 public synchronized PreparedStatement prepareStatement(String sql, int iResultSetType, int iResultSetConcurrency) 421 throws SQLException { 422 return _prepareStatement(sql, iResultSetType, iResultSetConcurrency, true); 423 } 424 425 protected int getResultSetType(){ 426 427 int resultSetType; 428 try { 429 resultSetType =((StandardLogicalDatabase) DODS 430 .getDatabaseManager() 431 .findLogicalDatabase(getDatabaseName())) 432 .getResultSetType(); 433 } catch (DatabaseManagerException e) { 434 DODS.getLogChannel().write(Logger.DEBUG,"Error unknown logical database. Using default value for 'resultSetType' parameter"); 435 resultSetType = StandardLogicalDatabase.DEFAULT_RESULT_SET_TYPE; 436 } 437 return resultSetType; 438 } 439 440 protected int getResultSetConcurrency(){ 441 442 int resultSetConcurrency; 443 try { 444 resultSetConcurrency =((StandardLogicalDatabase) DODS 445 .getDatabaseManager() 446 .findLogicalDatabase(getDatabaseName())) 447 .getResultSetConcurrency(); 448 } catch (DatabaseManagerException e) { 449 DODS.getLogChannel().write(Logger.DEBUG,"Error unknown logical database. Using default value for 'resultSetConcurrency' parameter"); 450 resultSetConcurrency = StandardLogicalDatabase.DEFAULT_RESULT_SET_CONCURRENCY; 451 } 452 return resultSetConcurrency; 453 } 454 455 456 466 public synchronized CallableStatement prepareCall(String sql) throws SQLException { 467 return connection.prepareCall(sql); 468 } 469 470 480 public synchronized ResultSet executeQuery(PreparedStatement preparedStmt, String msg) 481 throws SQLException { 482 logDebug("Execute prepared statement: " + msg, preparedStmt); 483 validate(); 484 return preparedStmt.executeQuery(); 485 } 486 487 496 public synchronized ResultSet executeQuery(String sql) throws SQLException { 497 logDebug(sql); 498 validate(); 499 return currentStmt.executeQuery(sql); 500 } 501 502 514 public synchronized int executeUpdate(String sql) throws SQLException { 515 logDebug(sql); 516 validate(); 517 return currentStmt.executeUpdate(sql); 518 } 519 520 531 public int executeUpdate(PreparedStatement preparedStmt, String msg) throws SQLException { 532 logDebug("Execute prepared statement: " + msg, preparedStmt); 533 validate(); 534 return preparedStmt.executeUpdate(); 535 } 536 537 548 public synchronized boolean execute(String sql) throws SQLException { 549 logDebug("execute: " + sql); 550 validate(); 551 return currentStmt.execute(sql); 552 } 553 554 561 public void warningCheck(ResultSet resultSet) throws SQLException { 562 logDebug("warningCheck()"); 563 SQLWarning warning = resultSet.getWarnings(); 564 565 if (warning != null) { 566 throw warning; 567 } 568 } 569 570 574 public synchronized void release() { 575 if (allocated) { 576 logDebug("release"); 577 synchronized (connectionAllocator) { 582 connectionAllocator.release(this); 584 allocated = false; 585 if (dropConnection) { 586 drop(); 587 } 588 } 589 } 590 } 591 592 595 protected synchronized void drop() { 596 if (!dropped) { 597 close(); 598 logDebug("drop"); 599 connectionAllocator.drop(this); 600 dropped = true; 601 logDebug("DBConnection[" + id + "]: " + url 602 + "Connection has been dropped from the connection allocator."); 603 } 604 } 605 606 618 public synchronized boolean handleException(SQLException sqlExcept) { 619 String sqlState = sqlExcept.getSQLState(); 620 621 logDebug("handleException: " + sqlExcept.getMessage()); 622 if (sqlExcept.getErrorCode() != 11111111) { 636 if (!dropConnection) { 637 logDebug("DBConnection[" + id + "]: " + url 638 + "\nScheduled to be dropped from connection allocator." 639 + "\nUnable to handle exception: \"" 640 + sqlExcept.toString() + " \nErrorCode : " 641 + sqlExcept.getErrorCode() + " \nSQLState : " 642 + sqlExcept.getSQLState() + "\"\n"); 643 dropConnection = true; 652 } 653 return false; 654 } else { 655 return true; 656 } 657 } 658 659 664 public int getGeneration() { 665 return generation; 666 } 667 668 672 public synchronized void close() { 673 if (!closed) { 674 logDebug("close"); 675 676 687 boolean closeStmts = true; 688 692 Enumeration e = preparedStmtCache.keys(); 693 694 while (e.hasMoreElements() && closeStmts) { 695 String key = (String ) e.nextElement(); 696 697 try { 698 ((PreparedStatement ) preparedStmtCache.remove(key)).close(); 699 } catch (SQLException except) { 700 closeStmts = false; 702 logDebug("DBConnection[" + id + "]: " + url 703 + "\nUnable to close statements. Continuing....\n"); 704 } 705 } 706 707 if (closeStmts) { 708 try { 709 if (currentStmt != null) { 710 currentStmt.close(); 711 } 712 } catch (Exception except) { 713 closeStmts = false; 715 } 716 currentStmt=null; 717 } 718 try { 719 if(!connection.isClosed()){ 720 connection.close(); 721 } 722 } catch (Exception except) { } 724 logDebug("DBConnection[" + id + "]: " + url 725 + "\nConnection has been closed.\n"); 726 } 727 closed = true; 728 connection = null; 729 } 730 731 737 public void setAutoCommit(boolean on) throws SQLException { 738 validate(); 739 if(Common.isChangeAutocommitEnabled(getDatabaseName())){ 740 logDebug("set autocommit: " + on); 741 connection.setAutoCommit(on); 742 }else{ 743 logDebug("set autocommit is disabled, can't change to value :" + on); 744 } 745 } 746 747 752 public void commit() throws SQLException { 753 validate(); 754 logDebug("commit"); 755 connection.commit(); 756 } 757 758 765 public void rollback() throws SQLException { 766 validate(); 767 logDebug("rollback"); 768 connection.rollback(); 769 } 770 771 777 protected void logDebug(String str) { 778 if (logging) { 779 DODS.getLogChannel().write(Logger.DEBUG, 780 "\nDBConnection[" + id + "]:" + str + "\n"); 781 } 782 } 783 784 792 protected void logDebug(String str, Statement stmt) { 793 if (logging) { 794 DODS.getLogChannel().write(Logger.DEBUG, 795 "\nDBConnection[" + id + "]:" + str + "\n" + "SQL: " 796 + stmt.toString()); 797 } 798 } 799 800 804 public void incrRequestCount() { 805 ((ExtendedConnectionAllocator) connectionAllocator).IncrementRequesteCount(); 806 } 807 808 812 public String getUrl() { 813 return url; 814 } 815 816 820 public String getUser() { 821 return user; 822 } 823 824 829 public Connection getConnection() { 830 return connection; 831 } 832 833 837 public boolean isMarkedForDrop() { 838 return dropConnection; 839 } 840 841 845 public String getDatabaseName() { 846 return connectionAllocator.getDatabaseName(); 847 } 848 851 public int getConnectionUsageCounter() { 852 return connectionUsageCounter; 853 } 854 855 858 public void setConnectionUsageCounter(int i) { 859 connectionUsageCounter = i; 860 } 861 864 public boolean isDroped() { 865 return dropped; 866 } 867 870 public boolean isClosed() { 871 return closed; 872 } 873 874 877 public void setConnectionEnterPoolTime(long i) { 878 connectionEnterPoolTime=i; 879 880 } 881 882 885 public long getConnectionEnterPoolTime() { 886 return connectionEnterPoolTime; 887 } 888 889 892 public int getMaxPreparedStmts() { 893 return maxPreparedStmts; 894 } 895 } 896 | Popular Tags |