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 SimpleDBConnection 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 SimpleDBConnection(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 synchronized (connectionAllocator) { 515 connectionAllocator.release(this); 517 allocated = false; 518 if (dropConnection) { 519 drop(); 520 } 521 } 522 } 523 } 524 525 528 protected synchronized void drop() { 529 if (!dropped) { 530 close(); 531 logDebug("drop"); 532 connectionAllocator.drop(this); 533 dropped = true; 534 logDebug("DBConnection[" + id + "]: " + url 535 + "Connection has been dropped from the connection allocator."); 536 } 537 } 538 539 551 public synchronized boolean handleException(SQLException sqlExcept) { 552 String sqlState = sqlExcept.getSQLState(); 553 554 logDebug("handleException: " + sqlExcept.getMessage()); 555 if (sqlExcept.getErrorCode() != 11111111) { 569 if (!dropConnection) { 570 logDebug("DBConnection[" + id + "]: " + url 571 + "\nScheduled to be dropped from connection allocator." 572 + "\nUnable to handle exception: \"" 573 + sqlExcept.toString() + " \nErrorCode : " 574 + sqlExcept.getErrorCode() + " \nSQLState : " 575 + sqlExcept.getSQLState() + "\"\n"); 576 dropConnection = true; 585 } 586 return false; 587 } else { 588 return true; 589 } 590 } 591 592 597 public int getGeneration() { 598 return generation; 599 } 600 601 605 public synchronized void close() { 606 if (!closed) { 607 logDebug("close"); 608 609 620 boolean closeStmts = true; 621 625 Enumeration e = preparedStmtCache.keys(); 626 627 while (e.hasMoreElements() && closeStmts) { 628 String key = (String ) e.nextElement(); 629 630 try { 631 ((PreparedStatement) preparedStmtCache.remove(key)).close(); 632 } catch (SQLException except) { 633 closeStmts = false; 635 logDebug("DBConnection[" + id + "]: " + url 636 + "\nUnable to close statements. Continuing....\n"); 637 } 638 } 639 640 if (closeStmts) { 641 try { 642 if (currentStmt != null) { 643 currentStmt.close(); 644 } 645 } catch (Exception except) { 646 closeStmts = false; 648 } 649 currentStmt=null; 650 } 651 try { 652 if(!connection.isClosed()){ 653 connection.close(); 654 } 655 } catch (Exception except) { } 657 logDebug("DBConnection[" + id + "]: " + url 658 + "\nConnection has been closed.\n"); 659 } 660 closed = true; 661 connection = null; 662 } 663 664 670 public void setAutoCommit(boolean on) throws SQLException { 671 validate(); 672 if(Common.isChangeAutocommitEnabled(getDatabaseName())){ 673 logDebug("set autocommit: " + on); 674 connection.setAutoCommit(on); 675 }else{ 676 logDebug("set autocommit is disabled, can't change to value :" + on); 677 } 678 } 679 680 685 public void commit() throws SQLException { 686 validate(); 687 logDebug("commit"); 688 connection.commit(); 689 } 690 691 698 public void rollback() throws SQLException { 699 validate(); 700 logDebug("rollback"); 701 connection.rollback(); 702 } 703 704 710 protected void logDebug(String str) { 711 if (logging) { 712 DODS.getLogChannel().write(Logger.DEBUG, 713 "\nDBConnection[" + id + "]:" + str + "\n"); 714 } 715 } 716 717 725 protected void logDebug(String str, Statement stmt) { 726 if (logging) { 727 DODS.getLogChannel().write(Logger.DEBUG, 728 "\nDBConnection[" + id + "]:" + str + "\n" + "SQL: " 729 + stmt.toString()); 730 } 731 } 732 733 737 public void incrRequestCount() { 738 ((ExtendedConnectionAllocator) connectionAllocator).IncrementRequesteCount(); 739 } 740 741 745 public String getUrl() { 746 return url; 747 } 748 749 753 public String getUser() { 754 return user; 755 } 756 757 762 public Connection getConnection() { 763 return connection; 764 } 765 766 770 public boolean isMarkedForDrop() { 771 return dropConnection; 772 } 773 774 778 public String getDatabaseName() { 779 return connectionAllocator.getDatabaseName(); 780 } 781 784 public int getConnectionUsageCounter() { 785 return connectionUsageCounter; 786 } 787 788 791 public void setConnectionUsageCounter(int i) { 792 connectionUsageCounter = i; 793 } 794 797 public boolean isDroped() { 798 return dropped; 799 } 800 803 public boolean isClosed() { 804 return closed; 805 } 806 807 810 public void setConnectionEnterPoolTime(long i) { 811 connectionEnterPoolTime=i; 812 813 } 814 815 818 public long getConnectionEnterPoolTime() { 819 return connectionEnterPoolTime; 820 } 821 822 825 public int getMaxPreparedStmts() { 826 return maxPreparedStmts; 827 } 828 } 829 | Popular Tags |