1 25 package com.lutris.appserver.server.sql.standard; 26 27 import com.lutris.appserver.server.sql.*; 28 import java.sql.*; 29 30 import com.lutris.logging.Logger; 31 import java.util.Enumeration ; 32 import java.util.Hashtable ; 33 import org.enhydra.dods.Common; 34 import org.enhydra.dods.DODS; 35 36 45 public class StandardDBConnection implements ExtendedDBConnection { 46 47 48 protected Connection connection; 49 50 51 protected String url; 52 53 54 protected String user; 55 56 57 protected String password; 58 protected int id; 60 protected static int nextId = 0; 62 protected Hashtable preparedStmtCache; 64 protected Statement currentStmt = null; 66 protected ConnectionAllocator connectionAllocator; 68 protected boolean logging; 70 protected int generation; 72 protected boolean closed = false; 74 protected boolean dropConnection = false; 76 protected boolean dropped = false; 78 protected boolean reset = true; 80 protected boolean allocated = false; 82 protected int maxPreparedStmts; 84 protected int connectionUsageCounter=0; 86 protected long connectionEnterPoolTime = -1; 88 91 93 108 public StandardDBConnection(ConnectionAllocator connectionAllocatorObj, 109 String url, String user, String password, int maxPreparedStatements, 110 boolean logging, int generation) 111 throws SQLException { 112 id = nextId++; 113 this.preparedStmtCache = new Hashtable (); 114 this.connectionAllocator = connectionAllocatorObj; 115 this.url = url; 116 this.user = user; 117 this.password = password; 118 this.logging = logging; 119 this.generation = generation; 120 connection = DriverManager.getConnection(url, user, password); 121 currentStmt = connection.createStatement(); 122 if (maxPreparedStatements < 0) { 123 this.maxPreparedStmts = connection.getMetaData().getMaxStatements() 125 - 1; 126 if (this.maxPreparedStmts == 0) { 127 this.maxPreparedStmts = 1; 131 } 132 if (this.maxPreparedStmts < 0) { 133 this.maxPreparedStmts = 256; 137 } 138 } else { 139 this.maxPreparedStmts = maxPreparedStatements; 140 } 141 logDebug("DBConnection[" + id + "]: " + url 142 + "\nNew connection allocated.\n"); 143 connectionEnterPoolTime = System.currentTimeMillis(); 144 } 145 146 153 public synchronized void allocate() throws SQLException { 154 logDebug("allocate"); 155 try { 156 closedCheck(); 157 reset(); 158 } catch (SQLException e) { 159 handleException(e); 160 if (dropConnection) { 165 drop(); 166 } else { 167 release(); 168 } 169 throw e; 170 } 171 reset = false; 172 allocated = true; 173 } 174 175 184 protected void resetCheck() throws SQLException { 185 logDebug("resetCheck()"); 186 if (!reset) { 187 throw new java.sql.SQLException ("DBConnection.reset() was not called after the previous " 188 + "operation completed"); 189 } 190 } 191 192 199 protected void allocatedCheck() throws SQLException { 200 logDebug("allocatedCheck()"); 201 if (!allocated) { 202 throw new java.sql.SQLException ("attempt to access connection which was released."); 203 } 204 } 205 206 213 protected void closedCheck() throws SQLException { 214 logDebug("closedCheck()"); 215 if (closed || getConnection().isClosed()) { 216 throw new java.sql.SQLException ("attempt to access a closed connection."); 217 } 218 } 219 220 227 public void validate() throws SQLException { 228 logDebug("validate()"); 229 allocatedCheck(); 230 closedCheck(); 231 } 232 233 238 public synchronized void reset() throws SQLException { 239 SQLException saveExcept = null; 241 242 if (reset) { 243 return; 244 } 245 logDebug("reset"); 246 try { 247 connection.clearWarnings(); 248 } catch (SQLException except) { 249 if (saveExcept == null) { 250 saveExcept = except; 251 } 252 } 253 try { 254 connection.setAutoCommit(false); 255 } catch (SQLException except) { 256 if (saveExcept == null) { 257 saveExcept = except; 258 } 259 } 260 reset = true; 261 if (saveExcept != null) { 265 throw saveExcept; 266 } 267 } 268 269 280 public synchronized PreparedStatement prepareStatement(String sql) 281 throws SQLException { 282 return _prepareStatement(sql, -100, -100, false); 283 } 284 285 private synchronized PreparedStatement _prepareStatement(String sql, int iResultSetType, int iResultSetConcurrency, boolean tuned) 286 throws SQLException { 287 PreparedStatement preparedStmt = null; 288 String mapKey = sql+"=+=+"+iResultSetType+"=+=+"+iResultSetConcurrency+"=+=+"; 289 if (tuned){ 290 mapKey=mapKey+"tuned"; 291 } 292 logDebug("Prepare statement: " + sql); 293 validate(); 294 boolean selectQuery = sql.trim().toLowerCase().startsWith("select"); 295 if(maxPreparedStmts>0 && !selectQuery){ 296 preparedStmt = (PreparedStatement) preparedStmtCache.get(mapKey); 297 if ((preparedStmt != null) && (!preparedStmt.getConnection().isClosed())) { 298 preparedStmt.clearParameters(); 299 } else { 300 if (preparedStmtCache.size() >= maxPreparedStmts) { 301 String key = (String ) preparedStmtCache.keys().nextElement(); 302 ((PreparedStatement) preparedStmtCache.remove(key)).close(); 303 } 304 preparedStmt = getNewPrepStatemet(sql, iResultSetType, iResultSetConcurrency, tuned); 305 preparedStmtCache.put(mapKey, preparedStmt); 306 } 307 }else{ 308 preparedStmt = getNewPrepStatemet(sql, iResultSetType, iResultSetConcurrency, tuned); 309 } 310 return preparedStmt; 311 } 312 313 314 315 323 private PreparedStatement getNewPrepStatemet(String sql, int iResultSetType, int iResultSetConcurrency, boolean tuned) throws SQLException { 324 PreparedStatement preparedStmt; 325 if(!tuned){ 326 if(getResultSetType()==StandardLogicalDatabase.DEFAULT_RESULT_SET_TYPE || 327 getResultSetConcurrency()==StandardLogicalDatabase.DEFAULT_RESULT_SET_CONCURRENCY){ 328 preparedStmt = connection.prepareStatement(sql); 329 } 330 else { 331 preparedStmt = connection.prepareStatement(sql,getResultSetType(),getResultSetConcurrency()); 332 } 333 }else{ 334 preparedStmt = connection.prepareStatement(sql,iResultSetType,iResultSetConcurrency); 335 } 336 return preparedStmt; 337 } 338 339 352 public synchronized PreparedStatement prepareStatement(String sql, int iResultSetType, int iResultSetConcurrency) 353 throws SQLException { 354 return _prepareStatement(sql, iResultSetType, iResultSetConcurrency, true); 355 } 356 357 358 protected int getResultSetType(){ 359 360 int resultSetType; 361 try { 362 resultSetType =((StandardLogicalDatabase) DODS 363 .getDatabaseManager() 364 .findLogicalDatabase(getDatabaseName())) 365 .getResultSetType(); 366 } catch (DatabaseManagerException e) { 367 DODS.getLogChannel().write(Logger.DEBUG,"Error unknown logical database. Using default value for 'resultSetType' parameter"); 368 resultSetType = StandardLogicalDatabase.DEFAULT_RESULT_SET_TYPE; 369 } 370 return resultSetType; 371 } 372 373 protected int getResultSetConcurrency(){ 374 375 int resultSetConcurrency; 376 try { 377 resultSetConcurrency =((StandardLogicalDatabase) DODS 378 .getDatabaseManager() 379 .findLogicalDatabase(getDatabaseName())) 380 .getResultSetConcurrency(); 381 } catch (DatabaseManagerException e) { 382 DODS.getLogChannel().write(Logger.DEBUG,"Error unknown logical database. Using default value for 'resultSetConcurrency' parameter"); 383 resultSetConcurrency = StandardLogicalDatabase.DEFAULT_RESULT_SET_CONCURRENCY; 384 } 385 return resultSetConcurrency; 386 } 387 388 389 399 public synchronized CallableStatement prepareCall(String sql) throws SQLException { 400 return connection.prepareCall(sql); 401 } 402 403 413 public synchronized ResultSet executeQuery(PreparedStatement preparedStmt, String msg) 414 throws SQLException { 415 logDebug("Execute prepared statement: " + msg, preparedStmt); 416 validate(); 417 return preparedStmt.executeQuery(); 418 } 419 420 429 public synchronized ResultSet executeQuery(String sql) throws SQLException { 430 logDebug(sql); 431 validate(); 432 return currentStmt.executeQuery(sql); 433 } 434 435 447 public synchronized int executeUpdate(String sql) throws SQLException { 448 logDebug(sql); 449 validate(); 450 return currentStmt.executeUpdate(sql); 451 } 452 453 464 public int executeUpdate(PreparedStatement preparedStmt, String msg) throws SQLException { 465 logDebug("Execute prepared statement: " + msg, preparedStmt); 466 validate(); 467 return preparedStmt.executeUpdate(); 468 } 469 470 481 public synchronized boolean execute(String sql) throws SQLException { 482 logDebug("execute: " + sql); 483 validate(); 484 return currentStmt.execute(sql); 485 } 486 487 494 public void warningCheck(ResultSet resultSet) throws SQLException { 495 logDebug("warningCheck()"); 496 SQLWarning warning = resultSet.getWarnings(); 497 498 if (warning != null) { 499 throw warning; 500 } 501 } 502 503 507 public synchronized void release() { 508 if (allocated) { 509 logDebug("release"); 510 allocated = false; 511 if (dropConnection) { 512 drop(); 513 } 514 if (!dropped){ 515 connectionAllocator.release(this); 516 } 517 } 518 } 519 520 523 protected synchronized void drop() { 524 if (!dropped) { 525 close(); 526 logDebug("drop"); 527 connectionAllocator.drop(this); 528 dropped = true; 529 logDebug("DBConnection[" + id + "]: " + url 530 + "Connection has been dropped from the connection allocator."); 531 } 532 } 533 534 546 public synchronized boolean handleException(SQLException sqlExcept) { 547 String sqlState = sqlExcept.getSQLState(); 548 549 logDebug("handleException: " + sqlExcept.getMessage()); 550 if (sqlExcept.getErrorCode() != 11111111) { 564 if (!dropConnection) { 565 logDebug("DBConnection[" + id + "]: " + url 566 + "\nScheduled to be dropped from connection allocator." 567 + "\nUnable to handle exception: \"" 568 + sqlExcept.toString() + " \nErrorCode : " 569 + sqlExcept.getErrorCode() + " \nSQLState : " 570 + sqlExcept.getSQLState() + "\"\n"); 571 dropConnection = true; 580 } 581 return false; 582 } else { 583 return true; 584 } 585 } 586 587 592 public int getGeneration() { 593 return generation; 594 } 595 596 600 public synchronized void close() { 601 if (!closed) { 602 logDebug("close"); 603 604 615 boolean closeStmts = true; 616 620 Enumeration e = preparedStmtCache.keys(); 621 622 while (e.hasMoreElements() && closeStmts) { 623 String key = (String ) e.nextElement(); 624 625 try { 626 ((PreparedStatement) preparedStmtCache.remove(key)).close(); 627 } catch (SQLException except) { 628 closeStmts = false; 630 logDebug("DBConnection[" + id + "]: " + url 631 + "\nUnable to close statements. Continuing....\n"); 632 } 633 } 634 635 if (closeStmts) { 636 try { 637 if (currentStmt != null) { 638 currentStmt.close(); 639 } 640 } catch (Exception except) { 641 closeStmts = false; 643 } 644 currentStmt=null; 645 } 646 try { 647 if(!connection.isClosed()){ 648 connection.close(); 649 } 650 } catch (Exception except) { } 652 logDebug("DBConnection[" + id + "]: " + url 653 + "\nConnection has been closed.\n"); 654 } 655 closed = true; 656 connection = null; 657 } 658 659 665 public void setAutoCommit(boolean on) throws SQLException { 666 validate(); 667 if(Common.isChangeAutocommitEnabled(getDatabaseName())){ 668 logDebug("set autocommit: " + on); 669 connection.setAutoCommit(on); 670 }else{ 671 logDebug("set autocommit is disabled, can't change to value :" + on); 672 } 673 } 674 675 680 public void commit() throws SQLException { 681 validate(); 682 logDebug("commit"); 683 connection.commit(); 684 } 685 686 693 public void rollback() throws SQLException { 694 validate(); 695 logDebug("rollback"); 696 connection.rollback(); 697 } 698 699 705 protected void logDebug(String str) { 706 if (logging) { 707 DODS.getLogChannel().write(Logger.DEBUG, 708 "\nDBConnection[" + id + "]:" + str + "\n"); 709 } 710 } 711 712 720 protected void logDebug(String str, Statement stmt) { 721 if (logging) { 722 DODS.getLogChannel().write(Logger.DEBUG, 723 "\nDBConnection[" + id + "]:" + str + "\n" + "SQL: " 724 + stmt.toString()); 725 } 726 } 727 728 732 public void incrRequestCount() { 733 ((ExtendedConnectionAllocator) connectionAllocator).IncrementRequesteCount(); 734 } 735 736 740 public String getUrl() { 741 return url; 742 } 743 744 748 public String getUser() { 749 return user; 750 } 751 752 757 public Connection getConnection() { 758 return connection; 759 } 760 761 765 public boolean isMarkedForDrop() { 766 return dropConnection; 767 } 768 769 773 public String getDatabaseName() { 774 return connectionAllocator.getDatabaseName(); 775 } 776 779 public int getConnectionUsageCounter() { 780 return connectionUsageCounter; 781 } 782 783 786 public void setConnectionUsageCounter(int i) { 787 connectionUsageCounter = i; 788 } 789 792 public boolean isDroped() { 793 return dropped; 794 } 795 798 public boolean isClosed() { 799 return closed; 800 } 801 802 805 public void setConnectionEnterPoolTime(long i) { 806 connectionEnterPoolTime=i; 807 808 } 809 810 813 public long getConnectionEnterPoolTime() { 814 return connectionEnterPoolTime; 815 } 816 817 820 public int getMaxPreparedStmts() { 821 return maxPreparedStmts; 822 } 823 824 public long curtime=0; 825 } 826 | Popular Tags |