1 16 17 package org.apache.commons.dbcp.cpdsadapter; 18 19 import java.sql.Connection ; 20 import java.sql.PreparedStatement ; 21 import java.sql.SQLException ; 22 import java.util.Iterator ; 23 import java.util.Vector ; 24 25 import javax.sql.ConnectionEvent ; 26 import javax.sql.ConnectionEventListener ; 27 import javax.sql.PooledConnection ; 28 29 import org.apache.commons.dbcp.DelegatingConnection; 30 import org.apache.commons.dbcp.DelegatingPreparedStatement; 31 import org.apache.commons.dbcp.SQLNestedException; 32 import org.apache.commons.pool.KeyedObjectPool; 33 import org.apache.commons.pool.KeyedPoolableObjectFactory; 34 35 42 class PooledConnectionImpl 43 implements PooledConnection , KeyedPoolableObjectFactory { 44 private static final String CLOSED 45 = "Attempted to use PooledConnection after closed() was called."; 46 47 50 private Connection connection = null; 51 52 55 private DelegatingConnection delegatingConnection = null; 56 57 60 private Connection logicalConnection = null; 61 62 65 private Vector eventListeners; 66 67 70 boolean isClosed; 71 72 73 protected KeyedObjectPool pstmtPool = null; 74 75 76 79 PooledConnectionImpl(Connection connection, KeyedObjectPool pool) { 80 this.connection = connection; 81 if (connection instanceof DelegatingConnection) { 82 this.delegatingConnection = (DelegatingConnection) connection; 83 } else { 84 this.delegatingConnection = new DelegatingConnection(connection); 85 } 86 eventListeners = new Vector (); 87 isClosed = false; 88 if (pool != null) { 89 pstmtPool = pool; 90 pstmtPool.setFactory(this); 91 } 92 } 93 94 97 public void addConnectionEventListener(ConnectionEventListener listener) { 98 if (!eventListeners.contains(listener)) { 99 eventListeners.add(listener); 100 } 101 } 102 103 110 public void close() throws SQLException { 111 assertOpen(); 112 isClosed = true; 113 try { 114 if (pstmtPool != null) { 115 try { 116 pstmtPool.close(); 117 } finally { 118 pstmtPool = null; 119 } 120 } 121 } catch (RuntimeException e) { 122 throw e; 123 } catch (Exception e) { 124 throw new SQLNestedException("Cannot close connection (return to pool failed)", e); 125 } finally { 126 try { 127 connection.close(); 128 } finally { 129 connection = null; 130 } 131 } 132 } 133 134 137 private void assertOpen() throws SQLException { 138 if (isClosed) { 139 throw new SQLException (CLOSED); 140 } 141 } 142 143 148 public Connection getConnection() throws SQLException { 149 assertOpen(); 150 if (logicalConnection != null && !logicalConnection.isClosed()) { 152 throw new SQLException ("PooledConnection was reused, without" 155 + "its previous Connection being closed."); 156 } 157 158 logicalConnection = new ConnectionImpl(this, connection); 160 return logicalConnection; 161 } 162 163 166 public void removeConnectionEventListener( 167 ConnectionEventListener listener) { 168 eventListeners.remove(listener); 169 } 170 171 175 protected void finalize() throws Throwable { 176 try { 179 connection.close(); 180 } catch (Exception ignored) { 181 } 182 183 if (logicalConnection != null && !logicalConnection.isClosed()) { 185 throw new SQLException ("PooledConnection was gc'ed, without" 186 + "its last Connection being closed."); 187 } 188 } 189 190 193 void notifyListeners() { 194 ConnectionEvent event = new ConnectionEvent (this); 195 Iterator i = eventListeners.iterator(); 196 while (i.hasNext()) { 197 ((ConnectionEventListener ) i.next()).connectionClosed(event); 198 } 199 } 200 201 204 208 PreparedStatement prepareStatement(String sql) throws SQLException { 209 if (pstmtPool == null) { 210 return connection.prepareStatement(sql); 211 } else { 212 try { 213 return (PreparedStatement ) 214 pstmtPool.borrowObject(createKey(sql)); 215 } catch (RuntimeException e) { 216 throw e; 217 } catch (Exception e) { 218 throw new SQLNestedException("Borrow prepareStatement from pool failed", e); 219 } 220 } 221 } 222 223 227 PreparedStatement prepareStatement(String sql, int resultSetType, 228 int resultSetConcurrency) 229 throws SQLException { 230 if (pstmtPool == null) { 231 return connection.prepareStatement(sql, resultSetType, resultSetConcurrency); 232 } else { 233 try { 234 return (PreparedStatement ) pstmtPool.borrowObject( 235 createKey(sql,resultSetType,resultSetConcurrency)); 236 } catch (RuntimeException e) { 237 throw e; 238 } catch (Exception e) { 239 throw new SQLNestedException("Borrow prepareStatement from pool failed", e); 240 } 241 } 242 } 243 244 247 protected Object createKey(String sql, int resultSetType, 248 int resultSetConcurrency) { 249 return new PStmtKey(normalizeSQL(sql), resultSetType, 250 resultSetConcurrency); 251 } 252 253 256 protected Object createKey(String sql) { 257 return new PStmtKey(normalizeSQL(sql)); 258 } 259 260 264 protected String normalizeSQL(String sql) { 265 return sql.trim(); 266 } 267 268 273 public Object makeObject(Object obj) throws Exception { 274 if (null == obj || !(obj instanceof PStmtKey)) { 275 throw new IllegalArgumentException (); 276 } else { 277 PStmtKey key = (PStmtKey)obj; 279 if (null == key._resultSetType 280 && null == key._resultSetConcurrency) { 281 return new PoolablePreparedStatementStub( 282 connection.prepareStatement(key._sql), 283 key, pstmtPool, delegatingConnection); 284 } else { 285 return new PoolablePreparedStatementStub( 286 connection.prepareStatement(key._sql, 287 key._resultSetType.intValue(), 288 key._resultSetConcurrency.intValue()), 289 key, pstmtPool, delegatingConnection); 290 } 291 } 292 } 293 294 300 public void destroyObject(Object key, Object obj) throws Exception { 301 if (obj instanceof DelegatingPreparedStatement) { 303 ((DelegatingPreparedStatement) obj).getInnermostDelegate().close(); 304 } else { 305 ((PreparedStatement ) obj).close(); 306 } 307 } 308 309 316 public boolean validateObject(Object key, Object obj) { 317 return true; 318 } 319 320 326 public void activateObject(Object key, Object obj) throws Exception { 327 ((PoolablePreparedStatementStub) obj).activate(); 328 } 329 330 336 public void passivateObject(Object key, Object obj) throws Exception { 337 ((PreparedStatement ) obj).clearParameters(); 338 ((PoolablePreparedStatementStub) obj).passivate(); 339 } 340 341 344 class PStmtKey { 345 protected String _sql = null; 346 protected Integer _resultSetType = null; 347 protected Integer _resultSetConcurrency = null; 348 349 PStmtKey(String sql) { 350 _sql = sql; 351 } 352 353 PStmtKey(String sql, int resultSetType, int resultSetConcurrency) { 354 _sql = sql; 355 _resultSetType = new Integer (resultSetType); 356 _resultSetConcurrency = new Integer (resultSetConcurrency); 357 } 358 359 public boolean equals(Object that) { 360 try { 361 PStmtKey key = (PStmtKey) that; 362 return(((null == _sql && null == key._sql) || _sql.equals(key._sql)) && 363 ((null == _resultSetType && null == key._resultSetType) || _resultSetType.equals(key._resultSetType)) && 364 ((null == _resultSetConcurrency && null == key._resultSetConcurrency) || _resultSetConcurrency.equals(key._resultSetConcurrency)) 365 ); 366 } catch (ClassCastException e) { 367 return false; 368 } catch (NullPointerException e) { 369 return false; 370 } 371 } 372 373 public int hashCode() { 374 return(null == _sql ? 0 : _sql.hashCode()); 375 } 376 377 public String toString() { 378 StringBuffer buf = new StringBuffer (); 379 buf.append("PStmtKey: sql="); 380 buf.append(_sql); 381 buf.append(", resultSetType="); 382 buf.append(_resultSetType); 383 buf.append(", resultSetConcurrency="); 384 buf.append(_resultSetConcurrency); 385 return buf.toString(); 386 } 387 } 388 } 389 | Popular Tags |