1 4 5 6 package org.smartlib.pool.core; 7 8 import org.apache.log4j.Logger; 9 10 import java.util.*; 11 import java.sql.*; 12 13 14 18 19 public class ConnectionPool implements Pool , PoolMonitor { 20 21 private PoolConfig config; 22 private final String name; 23 private final Debugger debug; 24 private int currentPoolSize = 0; 25 private int usedConnections = 0; 26 private Vector connectionList; 27 private Vector connectionListenerList; 28 private Thread pollerThread; 29 private ConnectionProvider connProvider = null; 30 private String validatorQuery = null; 31 private volatile boolean shutDown = false; 32 private Hashtable connectionHash = new Hashtable(); 33 34 Logger logger = Logger.getLogger(ConnectionPool.class); 35 36 39 private Connection loadConnection() throws ConnectionPoolException { 40 41 42 try { 43 Class.forName(config.getDriver()); 44 } 45 catch(ClassNotFoundException classNotFound) { 46 throw new ConnectionPoolException("Could not load Driver", 47 classNotFound); 48 } 49 Connection con = null; 50 try { 51 con = DriverManager.getConnection(config.getConnectionStringByName(name).getConnectString(), 52 config.getUserName(), config.getPassword()); 53 } 54 catch (Exception e ) { 55 throw new ConnectionPoolException("Could not obtain Connection", 56 e); 57 } 58 currentPoolSize++; 59 return con; 60 61 } 62 63 66 public Vector getConnectionsInUse() { 67 68 return connectionList; 69 70 } 71 72 75 public Vector getConnectionLeakListeners() { 76 77 return connectionListenerList; 78 79 } 80 81 84 public int getNoOfFreeConnections() { 85 86 return (currentPoolSize - usedConnections); 87 88 } 89 90 95 public ConfigMonitor getConfigMonitor() { 96 97 return (ConfigMonitor)config; 98 99 } 100 101 public String getName() { 102 return name; 103 } 104 105 108 private void initialiseConnections() throws ConnectionPoolException { 109 110 try { 111 int minConnections = config.getMinConnections(); 112 for (int i = 0 ; i<minConnections ; i++) { 113 connectionHash.put(loadConnection(), Boolean.TRUE); 114 } 115 } 116 catch (Exception e) { 117 throw new ConnectionPoolException("Could not load initial connection" , e); 118 } 119 120 121 } 122 123 127 private void returnConnectionToOtherPool(Connection conn) 128 throws Exception { 129 130 connProvider.returnConnection(conn); 131 132 } 133 134 135 139 ConnectionPool(PoolConfig config, String name) throws ConnectionPoolException { 140 141 this.name = name; 142 this.config = config; 143 try { 144 if (config.getConnectionLoaderClass() != null) 145 connProvider = (ConnectionProvider)getClass().getClassLoader() 146 .loadClass(config.getConnectionLoaderClassByName(name).getConnectionLoaderClass()).newInstance(); 147 } 148 catch (Exception exp) { 149 throw new ConnectionPoolException("Error loading Connection Loader Class",exp); 150 } 151 if (connProvider == null) 152 initialiseConnections(); 153 154 debug = new Debugger(name, true); 155 connectionList = new Vector(config.getMinConnections() , config.getIncrement()); 156 connectionListenerList = new Vector(); 157 try { 158 if ( config.getDefaultListener() != null ) { 159 String defaultListener = config.getDefaultListener(); 160 addConnectionLeakListener((ConnectionLeakListener)getClass().getClassLoader().loadClass(defaultListener).newInstance()); 161 } 162 } 163 catch (Exception e ) { 164 throw new ConnectionPoolException("Could not load class " 165 + config.getDefaultListener() , e); 166 } 167 if (config.isDetectLeaks()) { 168 pollerThread = new Thread (new ConnectionLeakPollThread( 169 connectionList , connectionListenerList , 170 name, config.getPollThreadTime() , 171 config.getLeakTimeOut(), this)); 172 pollerThread.start(); 173 } 174 175 validatorQuery = config.getValidatorQuery(); 176 177 } 178 179 183 public int getCurrentPoolSize() { 184 185 return currentPoolSize; 186 187 } 188 189 204 public Connection getConnection() throws ConnectionPoolException { 205 206 if (config.isAllowAnonymousConnections()) 207 return getConnection("N/A"); 208 else 209 throw new ConnectionPoolException ("You are not allowed to take anonumous connections, please provide an owner name"); 210 211 } 212 213 private boolean checkIfValid(Connection conn) { 215 216 try { 217 debug.print(" Checking Connection for '" + validatorQuery + "'"); 218 if (validatorQuery != null && !validatorQuery.trim().equals("")) { 219 Statement stmt = conn.createStatement(); 220 boolean bool = stmt.execute(validatorQuery); 221 stmt.close(); 222 return bool; 223 } 224 else { 225 return true; 226 } 227 } 228 catch (SQLException exp) { 229 if (logger.isDebugEnabled()) { 230 logger.debug("Exception occurred while trying to test connection validity", exp); 231 } 232 return false; 233 } 234 235 } 236 237 241 private Connection getConnectionFromOtherPool(String owner) 242 throws ConnectionPoolException { 243 244 try { 245 synchronized (this) { 246 if (config.getMaxConnections() == usedConnections) { 247 try { 248 debug.print("Hey the value is " 249 + config.getConnectionWaitTimeOut()); 250 wait(config.getConnectionWaitTimeOut()); 251 if (config.getMaxConnections() == usedConnections) { 252 throw new TimeOutException("Timed-out while " 253 + "waiting for free connection"); 254 } 255 } 256 catch (InterruptedException ie) { 257 } 258 } 259 260 Connection conn = connProvider.getConnection(); 261 usedConnections++; 262 currentPoolSize++; 263 if (checkIfValid(conn)) { 266 SmartConnection smt = new SmartConnection(conn, 267 this,owner, config.isAutoClose()); 268 connectionList.add(smt); 269 return smt; 270 } 271 else { 272 boolean valid = false; 273 int i=1; 274 while (!valid) { 275 conn = connProvider.getConnection(); 276 valid = checkIfValid(conn); 277 i++; 278 if (i == 3 && !valid) 279 throw new ConnectionPoolException("Three consecutive cnnections failes the Validator Query org.smartlib.pool.test"); 280 } 281 SmartConnection smt = new SmartConnection(conn, 282 this,owner, config.isAutoClose()); 283 connectionList.add(smt); 284 return smt; 285 } 286 } 287 } 288 catch (ConnectionPoolException cpe) { 289 throw cpe; 290 } 291 catch (Exception exp) { 292 throw new ConnectionPoolException("Error while getting connections from the Connection Loader Class", exp); 293 } 294 295 } 296 297 298 299 316 public Connection getConnection(String owner) 317 throws ConnectionPoolException { 318 319 320 if (connProvider != null ) 322 return getConnectionFromOtherPool(owner); 323 324 325 Enumeration cons = connectionHash.keys(); 326 synchronized (connectionHash) { 328 if (config.getMaxConnections() == usedConnections) { 330 try { 331 debug.print("Hey the value is " + config.getConnectionWaitTimeOut()); 333 connectionHash.wait(config.getConnectionWaitTimeOut()); 334 if (config.getMaxConnections() == usedConnections) { 335 throw new TimeOutException("Timed-out while " 336 + "waiting for free connection"); 337 } 338 339 } 340 catch (InterruptedException ie) { 341 } 342 } 343 344 while (cons.hasMoreElements()) { 347 Connection con = (Connection)cons.nextElement(); 349 Boolean b = (Boolean )connectionHash.get(con); 350 if ( b == Boolean.TRUE ) { 351 connectionHash.put(con , Boolean.FALSE); 353 usedConnections++; 354 debug.print("Hey After Incrementing conn " +usedConnections); 355 if (checkIfValid(con)) { 359 SmartConnection smt = new SmartConnection(con, 360 this,owner, config.isAutoClose()); 361 connectionList.add(smt); 362 return smt; 363 } 364 else { 365 boolean valid = false; 366 int failCounter = 1; 367 while (!valid) { 368 connectionHash.remove(con); 369 con = loadConnection(); 370 connectionHash.put(con , Boolean.FALSE); 371 failCounter++; 372 valid = checkIfValid(con); 373 if (failCounter == 3 && !valid) 374 throw new ConnectionPoolException("Three consecutive connections failed the Validator Query org.smartlib.pool.test"); 375 } 376 SmartConnection smt = new SmartConnection(con, 377 this,owner, config.isAutoClose()); 378 connectionList.add(smt); 379 return smt; 380 } 381 } 382 } 383 384 int increment = config.getIncrement(); 386 Connection c = null; 387 SmartConnection smt = null; 388 for (int i = 0 ; i < increment 389 && i + currentPoolSize <= config.getMaxConnections(); i++){ 390 c = loadConnection(); 391 boolean valid = checkIfValid(c); 392 int failCounter = 1; 393 while (!valid) { 394 c= loadConnection(); 395 failCounter++; 396 valid = checkIfValid(c); 397 if (failCounter == 3 && !valid) 398 throw new ConnectionPoolException("Three consecutive connections failed the Validator Query org.smartlib.pool.test"); 399 } 400 if (i==0) { 401 smt = new SmartConnection(c , this , 402 owner , config.isAutoClose()); 403 connectionHash.put(c , Boolean.FALSE); 404 } 405 else 406 connectionHash.put(c , Boolean.TRUE); 407 } 408 409 usedConnections++; 412 connectionList.add(smt); 413 return smt; 414 415 } 416 417 } 418 419 423 public void returnConnection (Connection ret) { 424 425 if (connProvider != null ) { 426 try { 427 synchronized (this) { 428 Connection conn = ((SmartConnection)ret).returnConnection(); 429 returnConnectionToOtherPool(conn); 430 usedConnections--; 431 currentPoolSize--; 432 debug.print("Removed value is " + connectionList.removeElement(ret)); 433 notifyAll(); 434 } 435 } 436 catch (Exception exp) { 437 debug.print("Error " + exp); 439 } 440 return; 441 } 442 443 Object tempRef = ret; 444 SmartConnection smt = (SmartConnection)ret; 445 ret = smt.returnConnection(); 446 Connection con; 447 Enumeration cons = connectionHash.keys(); 448 synchronized(connectionHash) { 449 while (cons.hasMoreElements()) { 450 con = (Connection)cons.nextElement(); 451 if (con == ret) { 452 connectionHash.put(con, Boolean.TRUE); 453 break; 454 } 455 } 456 debug.print("Connection Released " + usedConnections); 457 usedConnections--; 458 debug.print("Connection contains list " + connectionList.contains(tempRef)); 459 debug.print("Removed value is " + connectionList.removeElement(tempRef)); 460 461 connectionHash.notifyAll(); 462 } 463 464 } 465 466 475 public void addConnectionLeakListener(ConnectionLeakListener cle ) 476 throws ConnectionPoolException { 477 478 if (cle == null) 479 throw new IllegalArgumentException ("ConnectionLeakListener cannot be null"); 480 debug.print("Added is " + cle); 481 connectionListenerList.add(cle); 482 483 } 484 485 493 public void removeConnectionLeakListener(ConnectionLeakListener cle) 494 throws ConnectionPoolException { 495 496 if (cle == null ) 497 throw new IllegalArgumentException ("ConnectionLeakListener cannot be null"); 498 debug.print("Trying to remove " + cle); 499 boolean found = connectionListenerList.remove(cle); 500 if (!found) 501 throw new ConnectionPoolException("No Such Listener"); 502 503 } 504 505 509 public void releaseConnections() { 510 511 512 if (config.getMaxConnectionsForRelease() == -1) 513 return ; 514 if (config.getMaxConnectionsForRelease() 515 < getNoOfFreeConnections()) { 516 int i = config.getIncrement(); 517 synchronized (connectionHash) { 518 Enumeration cons = connectionHash.keys(); 519 while (cons.hasMoreElements() && i > 0) { 520 Connection con = (Connection)cons.nextElement(); 521 Boolean b = (Boolean )connectionHash.get(con); 522 if (b == Boolean.TRUE) { 523 connectionHash.remove(con); 524 try { 525 con.close(); 526 i--; 527 currentPoolSize = connectionHash.size(); 528 debug.print("Releasing conn" + con); 529 } 530 catch (SQLException e) { 531 debug.print("Error in closing connection" + e ); 532 } 533 } 534 } 535 } 536 } 537 538 } 539 540 public void shutDown() { 541 if (logger.isDebugEnabled()) { 542 logger.debug("Shutting down connections for pool:" + name); 543 } 544 shutDown = true; 545 Enumeration cons = connectionHash.keys(); 546 while (cons.hasMoreElements()) { 547 Connection con = (Connection)cons.nextElement(); 548 try { 549 con.close(); 550 } 551 catch (Exception e) { 552 logger.warn("Exception occurred during connections close", e); 553 } 554 } 555 556 } 557 558 559 560 561 562 } 563 | Popular Tags |