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 javax.sql.DataSource ; 36 import java.util.Enumeration ; 37 import java.util.Hashtable ; 38 import org.enhydra.dods.DODS; 39 import com.lutris.appserver.server.sql.standard.*; 40 import org.enhydra.dods.Common; 41 import com.lutris.logging.Logger; 42 import com.lutris.appserver.server.sql.ConnectionAllocator; 43 import com.lutris.appserver.server.sql.DBConnection; 44 import com.lutris.appserver.server.sql.ExtendedDBConnection; 45 import com.lutris.appserver.server.sql.DatabaseManagerException; 46 import com.lutris.appserver.server.sql.ExtendedConnectionAllocator; 47 48 57 public class DataSourceDBConnection implements ExtendedDBConnection { 58 59 60 protected Connection connection; 61 62 63 protected String url; 64 65 66 protected String user; 67 68 protected DataSource ds; 69 70 71 protected String password; 72 protected int id; 74 protected static int nextId = 0; 76 protected Hashtable preparedStmtCache; 78 protected Statement currentStmt = null; 80 protected ConnectionAllocator connectionAllocator; 82 protected boolean logging; 84 protected int generation; 86 protected boolean closed = false; 88 protected boolean dropConnection = false; 90 protected boolean dropped = false; 92 protected boolean reset = true; 94 protected boolean allocated = false; 96 protected int maxPreparedStmts; 98 protected int connectionUsageCounter=0; 100 protected long connectionEnterPoolTime = -1; 102 105 107 122 public DataSourceDBConnection(ConnectionAllocator connectionAllocatorObj, 123 String url, String user, String password, int maxPreparedStatements, 124 boolean logging, int generation) 125 throws SQLException { 126 id = nextId++; 127 this.preparedStmtCache = new Hashtable (); 128 this.connectionAllocator = connectionAllocatorObj; 129 this.url = url; 130 this.user = user; 131 this.password = password; 132 this.logging = logging; 133 this.generation = generation; 134 connection = DriverManager.getConnection(url, user, password); 135 136 currentStmt = connection.createStatement(); 137 if (maxPreparedStatements < 0) { 138 this.maxPreparedStmts = connection.getMetaData().getMaxStatements() 140 - 1; 141 if (this.maxPreparedStmts == 0) { 142 this.maxPreparedStmts = 1; 146 } 147 if (this.maxPreparedStmts < 0) { 148 this.maxPreparedStmts = 256; 152 } 153 } else { 154 this.maxPreparedStmts = maxPreparedStatements; 155 } 156 logDebug("DBConnection[" + id + "]: " + url 157 + "\nNew connection allocated.\n"); 158 connectionEnterPoolTime = System.currentTimeMillis(); 159 } 160 174 public DataSourceDBConnection(ConnectionAllocator connectionAllocatorObj, 175 DataSource dataSource, int maxPreparedStatements, 176 boolean logging, int generation) 177 throws SQLException { 178 id = nextId++; 179 this.preparedStmtCache = new Hashtable (); 180 this.connectionAllocator = connectionAllocatorObj; 181 this.ds = dataSource; 182 this.logging = logging; 183 this.generation = generation; 184 185 connection = ds.getConnection(); 186 187 currentStmt = connection.createStatement(); 188 if (maxPreparedStatements < 0) { 189 this.maxPreparedStmts = connection.getMetaData().getMaxStatements() 191 - 1; 192 if (this.maxPreparedStmts == 0) { 193 this.maxPreparedStmts = 1; 197 } 198 if (this.maxPreparedStmts < 0) { 199 this.maxPreparedStmts = 256; 203 } 204 } else { 205 this.maxPreparedStmts = maxPreparedStatements; 206 } 207 logDebug("DBConnection[" + id + "]: " 208 + "\nNew connection allocated.\n"); 209 connectionEnterPoolTime = System.currentTimeMillis(); 210 } 211 212 219 public synchronized void allocate() throws SQLException { 220 logDebug("allocate"); 221 try { 222 closedCheck(); 223 reset(); 224 } catch (SQLException e) { 225 handleException(e); 226 if (dropConnection) { 231 drop(); 232 } else { 233 release(); 234 } 235 throw e; 236 } 237 reset = false; 238 allocated = true; 239 } 240 241 250 protected void resetCheck() throws SQLException { 251 logDebug("resetCheck()"); 252 if (!reset) { 253 throw new java.sql.SQLException ("DBConnection.reset() was not called after the previous " 254 + "operation completed"); 255 } 256 } 257 258 265 protected void allocatedCheck() throws SQLException { 266 logDebug("allocatedCheck()"); 267 if (!allocated) { 268 throw new java.sql.SQLException ("attempt to access connection which was released."); 269 } 270 } 271 272 279 protected void closedCheck() throws SQLException { 280 logDebug("closedCheck()"); 281 if (closed || getConnection().isClosed()) { 282 throw new java.sql.SQLException ("attempt to access a closed connection."); 283 } 284 } 285 286 293 public void validate() throws SQLException { 294 logDebug("validate()"); 295 allocatedCheck(); 296 closedCheck(); 297 } 298 299 304 public synchronized void reset() throws SQLException { 305 SQLException saveExcept = null; 307 308 if (reset) { 309 return; 310 } 311 logDebug("reset"); 312 try { 313 connection.clearWarnings(); 314 } catch (SQLException except) { 315 if (saveExcept == null) { 316 saveExcept = except; 317 } 318 } 319 try { 320 connection.setAutoCommit(false); 321 } catch (SQLException except) { 322 if (saveExcept == null) { 323 saveExcept = except; 324 } 325 } 326 reset = true; 327 if (saveExcept != null) { 331 throw saveExcept; 332 } 333 } 334 335 346 public synchronized PreparedStatement prepareStatement(String sql) 347 throws SQLException { 348 return _prepareStatement(sql, -100, -100, false); 349 } 350 351 private synchronized PreparedStatement _prepareStatement(String sql, int iResultSetType, int iResultSetConcurrency, boolean tuned) 352 throws SQLException { 353 PreparedStatement preparedStmt = null; 354 String mapKey = sql+"=+=+"+iResultSetType+"=+=+"+iResultSetConcurrency+"=+=+"; 355 if (tuned){ 356 mapKey=mapKey+"tuned"; 357 } 358 logDebug("Prepare statement: " + sql); 359 validate(); 360 boolean selectQuery = sql.trim().toLowerCase().startsWith("select"); 361 if(maxPreparedStmts>0 && !selectQuery){ 362 preparedStmt = (PreparedStatement ) preparedStmtCache.get(mapKey); 363 if ((preparedStmt != null) && (!preparedStmt.getConnection().isClosed())) { 364 preparedStmt.clearParameters(); 365 } else { 366 if (preparedStmtCache.size() >= maxPreparedStmts) { 367 String key = (String ) preparedStmtCache.keys().nextElement(); 368 ((PreparedStatement ) preparedStmtCache.remove(key)).close(); 369 } 370 preparedStmt = getNewPrepStatemet(sql, iResultSetType, iResultSetConcurrency, tuned); 371 preparedStmtCache.put(mapKey, preparedStmt); 372 } 373 }else{ 374 preparedStmt = getNewPrepStatemet(sql, iResultSetType, iResultSetConcurrency, tuned); 375 } 376 return preparedStmt; 377 } 378 379 380 388 private PreparedStatement getNewPrepStatemet(String sql, int iResultSetType, int iResultSetConcurrency, boolean tuned) throws SQLException { 389 PreparedStatement preparedStmt; 390 if(!tuned){ 391 if(getResultSetType()==StandardLogicalDatabase.DEFAULT_RESULT_SET_TYPE || 392 getResultSetConcurrency()==StandardLogicalDatabase.DEFAULT_RESULT_SET_CONCURRENCY){ 393 preparedStmt = connection.prepareStatement(sql); 394 } 395 else { 396 preparedStmt = connection.prepareStatement(sql,getResultSetType(),getResultSetConcurrency()); 397 } 398 }else{ 399 preparedStmt = connection.prepareStatement(sql,iResultSetType,iResultSetConcurrency); 400 } 401 return preparedStmt; 402 } 403 404 417 public synchronized PreparedStatement prepareStatement(String sql, int iResultSetType, int iResultSetConcurrency) 418 throws SQLException { 419 return _prepareStatement(sql, iResultSetType, iResultSetConcurrency, true); 420 } 421 422 protected int getResultSetType(){ 423 424 int resultSetType; 425 try { 426 resultSetType =((StandardLogicalDatabase) DODS 427 .getDatabaseManager() 428 .findLogicalDatabase(getDatabaseName())) 429 .getResultSetType(); 430 } catch (DatabaseManagerException e) { 431 DODS.getLogChannel().write(Logger.DEBUG,"Error unknown logical database. Using default value for 'resultSetType' parameter"); 432 resultSetType = StandardLogicalDatabase.DEFAULT_RESULT_SET_TYPE; 433 } 434 return resultSetType; 435 } 436 437 protected int getResultSetConcurrency(){ 438 439 int resultSetConcurrency; 440 try { 441 resultSetConcurrency =((StandardLogicalDatabase) DODS 442 .getDatabaseManager() 443 .findLogicalDatabase(getDatabaseName())) 444 .getResultSetConcurrency(); 445 } catch (DatabaseManagerException e) { 446 DODS.getLogChannel().write(Logger.DEBUG,"Error unknown logical database. Using default value for 'resultSetConcurrency' parameter"); 447 resultSetConcurrency = StandardLogicalDatabase.DEFAULT_RESULT_SET_CONCURRENCY; 448 } 449 return resultSetConcurrency; 450 } 451 452 453 463 public synchronized CallableStatement prepareCall(String sql) throws SQLException { 464 return connection.prepareCall(sql); 465 } 466 467 477 public synchronized ResultSet executeQuery(PreparedStatement preparedStmt, String msg) 478 throws SQLException { 479 logDebug("Execute prepared statement: " + msg, preparedStmt); 480 validate(); 481 return preparedStmt.executeQuery(); 482 } 483 484 493 public synchronized ResultSet executeQuery(String sql) throws SQLException { 494 logDebug(sql); 495 validate(); 496 return currentStmt.executeQuery(sql); 497 } 498 499 511 public synchronized int executeUpdate(String sql) throws SQLException { 512 logDebug(sql); 513 validate(); 514 return currentStmt.executeUpdate(sql); 515 } 516 517 528 public int executeUpdate(PreparedStatement preparedStmt, String msg) throws SQLException { 529 logDebug("Execute prepared statement: " + msg, preparedStmt); 530 validate(); 531 return preparedStmt.executeUpdate(); 532 } 533 534 545 public synchronized boolean execute(String sql) throws SQLException { 546 logDebug("execute: " + sql); 547 validate(); 548 return currentStmt.execute(sql); 549 } 550 551 558 public void warningCheck(ResultSet resultSet) throws SQLException { 559 logDebug("warningCheck()"); 560 SQLWarning warning = resultSet.getWarnings(); 561 562 if (warning != null) { 563 throw warning; 564 } 565 } 566 567 571 public synchronized void release() { 572 if (allocated) { 573 logDebug("release"); 574 allocated = false; 575 if (dropConnection) { 576 drop(); 577 } 578 if (!dropped){ 579 connectionAllocator.release(this); 580 } 581 } 582 } 583 584 587 protected synchronized void drop() { 588 if (!dropped) { 589 close(); 590 logDebug("drop"); 591 connectionAllocator.drop(this); 592 dropped = true; 593 logDebug("DBConnection[" + id + "]: " + url 594 + "Connection has been dropped from the connection allocator."); 595 } 596 } 597 598 610 public synchronized boolean handleException(SQLException sqlExcept) { 611 String sqlState = sqlExcept.getSQLState(); 612 613 logDebug("handleException: " + sqlExcept.getMessage()); 614 if (sqlExcept.getErrorCode() != 11111111) { 628 if (!dropConnection) { 629 logDebug("DBConnection[" + id + "]: " + url 630 + "\nScheduled to be dropped from connection allocator." 631 + "\nUnable to handle exception: \"" 632 + sqlExcept.toString() + " \nErrorCode : " 633 + sqlExcept.getErrorCode() + " \nSQLState : " 634 + sqlExcept.getSQLState() + "\"\n"); 635 dropConnection = true; 644 } 645 return false; 646 } else { 647 return true; 648 } 649 } 650 651 656 public int getGeneration() { 657 return generation; 658 } 659 660 664 public synchronized void close() { 665 if (!closed) { 666 logDebug("close"); 667 668 679 boolean closeStmts = true; 680 684 Enumeration e = preparedStmtCache.keys(); 685 686 while (e.hasMoreElements() && closeStmts) { 687 String key = (String ) e.nextElement(); 688 689 try { 690 ((PreparedStatement ) preparedStmtCache.remove(key)).close(); 691 } catch (SQLException except) { 692 closeStmts = false; 694 logDebug("DBConnection[" + id + "]: " + url 695 + "\nUnable to close statements. Continuing....\n"); 696 } 697 } 698 699 if (closeStmts) { 700 try { 701 if (currentStmt != null) { 702 currentStmt.close(); 703 } 704 } catch (Exception except) { 705 closeStmts = false; 707 } 708 currentStmt=null; 709 } 710 try { 711 if(!connection.isClosed()){ 712 connection.close(); 713 } 714 } catch (Exception except) { } 716 logDebug("DBConnection[" + id + "]: " + url 717 + "\nConnection has been closed.\n"); 718 } 719 closed = true; 720 connection = null; 721 } 722 723 729 public void setAutoCommit(boolean on) throws SQLException { 730 validate(); 731 if(Common.isChangeAutocommitEnabled(getDatabaseName())){ 732 logDebug("set autocommit: " + on); 733 connection.setAutoCommit(on); 734 }else{ 735 logDebug("set autocommit is disabled, can't change to value :" + on); 736 } 737 } 738 739 744 public void commit() throws SQLException { 745 validate(); 746 logDebug("commit"); 747 connection.commit(); 748 } 749 750 757 public void rollback() throws SQLException { 758 validate(); 759 logDebug("rollback"); 760 connection.rollback(); 761 } 762 763 769 protected void logDebug(String str) { 770 if (logging) { 771 DODS.getLogChannel().write(Logger.DEBUG, 772 "\nDBConnection[" + id + "]:" + str + "\n"); 773 } 774 } 775 776 784 protected void logDebug(String str, Statement stmt) { 785 if (logging) { 786 DODS.getLogChannel().write(Logger.DEBUG, 787 "\nDBConnection[" + id + "]:" + str + "\n" + "SQL: " 788 + stmt.toString()); 789 } 790 } 791 792 796 public void incrRequestCount() { 797 ((ExtendedConnectionAllocator) connectionAllocator).IncrementRequesteCount(); 798 } 799 800 804 public String getUrl() { 805 return url; 806 } 807 808 812 public String getUser() { 813 return user; 814 } 815 816 821 public Connection getConnection() { 822 return connection; 823 } 824 825 829 public boolean isMarkedForDrop() { 830 return dropConnection; 831 } 832 833 837 public String getDatabaseName() { 838 return connectionAllocator.getDatabaseName(); 839 } 840 843 public int getConnectionUsageCounter() { 844 return connectionUsageCounter; 845 } 846 847 850 public void setConnectionUsageCounter(int i) { 851 connectionUsageCounter = i; 852 } 853 856 public boolean isDroped() { 857 return dropped; 858 } 859 862 public boolean isClosed() { 863 return closed; 864 } 865 866 869 public void setConnectionEnterPoolTime(long i) { 870 connectionEnterPoolTime=i; 871 872 } 873 874 877 public long getConnectionEnterPoolTime() { 878 return connectionEnterPoolTime; 879 } 880 881 884 public int getMaxPreparedStmts() { 885 return maxPreparedStmts; 886 } 887 888 889 public long curtime=0; 890 891 892 } 893 | Popular Tags |