1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.dbcp;
19
20 import java.sql.CallableStatement;
21 import java.sql.Connection;
22 import java.sql.PreparedStatement;
23 import java.sql.SQLException;
24
25 import java.util.NoSuchElementException;
26
27 import org.apache.commons.pool.KeyedObjectPool;
28 import org.apache.commons.pool.KeyedPoolableObjectFactory;
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45 public class PoolingConnection extends DelegatingConnection implements Connection, KeyedPoolableObjectFactory {
46
47 protected KeyedObjectPool _pstmtPool = null;
48
49
50 private static final byte STATEMENT_PREPAREDSTMT = 0;
51
52
53 private static final byte STATEMENT_CALLABLESTMT = 1;
54
55
56
57
58
59
60 public PoolingConnection(Connection c) {
61 super(c);
62 }
63
64
65
66
67
68
69 public PoolingConnection(Connection c, KeyedObjectPool pool) {
70 super(c);
71 _pstmtPool = pool;
72 }
73
74
75
76
77
78
79 public synchronized void close() throws SQLException {
80 if(null != _pstmtPool) {
81 KeyedObjectPool oldpool = _pstmtPool;
82 _pstmtPool = null;
83 try {
84 oldpool.close();
85 } catch(RuntimeException e) {
86 throw e;
87 } catch(SQLException e) {
88 throw e;
89 } catch(Exception e) {
90 throw (SQLException) new SQLException("Cannot close connection").initCause(e);
91 }
92 }
93 getInnermostDelegate().close();
94 }
95
96
97
98
99
100 public PreparedStatement prepareStatement(String sql) throws SQLException {
101 if (null == _pstmtPool) {
102 throw new SQLException(
103 "Statement pool is null - closed or invalid PoolingConnection.");
104 }
105 try {
106 return(PreparedStatement)(_pstmtPool.borrowObject(createKey(sql)));
107 } catch(NoSuchElementException e) {
108 throw (SQLException) new SQLException("MaxOpenPreparedStatements limit reached").initCause(e);
109 } catch(RuntimeException e) {
110 throw e;
111 } catch(Exception e) {
112 throw new SQLNestedException("Borrow prepareStatement from pool failed", e);
113 }
114 }
115
116
117
118
119
120 public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
121 if (null == _pstmtPool) {
122 throw new SQLException(
123 "Statement pool is null - closed or invalid PoolingConnection.");
124 }
125 try {
126 return(PreparedStatement)(_pstmtPool.borrowObject(createKey(sql,resultSetType,resultSetConcurrency)));
127 } catch(NoSuchElementException e) {
128 throw (SQLException) new SQLException("MaxOpenPreparedStatements limit reached").initCause(e);
129 } catch(RuntimeException e) {
130 throw e;
131 } catch(Exception e) {
132 throw (SQLException) new SQLException("Borrow prepareStatement from pool failed").initCause(e);
133 }
134 }
135
136
137
138
139
140
141
142
143
144 public CallableStatement prepareCall(String sql) throws SQLException {
145 try {
146 return (CallableStatement) (_pstmtPool.borrowObject(createKey(sql, STATEMENT_CALLABLESTMT)));
147 } catch (NoSuchElementException e) {
148 throw new SQLNestedException("MaxOpenCallableStatements limit reached", e);
149 } catch (RuntimeException e) {
150 throw e;
151 } catch (Exception e) {
152 throw new SQLNestedException("Borrow callableStatement from pool failed", e);
153 }
154 }
155
156
157
158
159
160
161
162
163
164 public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
165 try {
166 return (CallableStatement) (_pstmtPool.borrowObject(createKey(sql, resultSetType,
167 resultSetConcurrency, STATEMENT_CALLABLESTMT)));
168 } catch (NoSuchElementException e) {
169 throw new SQLNestedException("MaxOpenCallableStatements limit reached", e);
170 } catch (RuntimeException e) {
171 throw e;
172 } catch (Exception e) {
173 throw new SQLNestedException("Borrow callableStatement from pool failed", e);
174 }
175 }
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214 protected Object createKey(String sql, int resultSetType, int resultSetConcurrency) {
215 String catalog = null;
216 try {
217 catalog = getCatalog();
218 } catch (SQLException e) {}
219 return new PStmtKey(normalizeSQL(sql), catalog, resultSetType, resultSetConcurrency);
220 }
221
222
223
224
225 protected Object createKey(String sql, int resultSetType, int resultSetConcurrency, byte stmtType) {
226 String catalog = null;
227 try {
228 catalog = getCatalog();
229 } catch (Exception e) {}
230 return new PStmtKey(normalizeSQL(sql), catalog, resultSetType, resultSetConcurrency, stmtType);
231 }
232
233
234
235
236 protected Object createKey(String sql) {
237 String catalog = null;
238 try {
239 catalog = getCatalog();
240 } catch (SQLException e) {}
241 return new PStmtKey(normalizeSQL(sql), catalog);
242 }
243
244
245
246
247 protected Object createKey(String sql, byte stmtType) {
248 String catalog = null;
249 try {
250 catalog = getCatalog();
251 } catch (Exception e) {}
252 return new PStmtKey(normalizeSQL(sql), catalog, stmtType);
253 }
254
255
256
257
258
259 protected String normalizeSQL(String sql) {
260 return sql.trim();
261 }
262
263
264
265
266
267
268
269
270
271 public Object makeObject(Object obj) throws Exception {
272 if(null == obj || !(obj instanceof PStmtKey)) {
273 throw new IllegalArgumentException("Prepared statement key is null or invalid.");
274 } else {
275 PStmtKey key = (PStmtKey)obj;
276 if( null == key._resultSetType && null == key._resultSetConcurrency ) {
277 return key._stmtType == STATEMENT_PREPAREDSTMT ?
278 new PoolablePreparedStatement(getDelegate().prepareStatement( key._sql), key, _pstmtPool, this) :
279 new PoolableCallableStatement(getDelegate().prepareCall( key._sql ), key, _pstmtPool, this);
280
281 }else {
282 return key._stmtType == STATEMENT_PREPAREDSTMT ?
283 new PoolablePreparedStatement(getDelegate().prepareStatement(
284 key._sql, key._resultSetType.intValue(),key._resultSetConcurrency.intValue()), key, _pstmtPool, this) :
285 new PoolableCallableStatement( getDelegate().prepareCall(
286 key._sql,key._resultSetType.intValue(), key._resultSetConcurrency.intValue() ), key, _pstmtPool, this);
287 }
288 }
289 }
290
291
292
293
294
295
296
297
298
299 public void destroyObject(Object key, Object obj) throws Exception {
300 if(obj instanceof DelegatingPreparedStatement) {
301 ((DelegatingPreparedStatement)obj).getInnermostDelegate().close();
302 } else {
303 ((PreparedStatement)obj).close();
304 }
305 }
306
307
308
309
310
311
312
313
314
315 public boolean validateObject(Object key, Object obj) {
316 return true;
317 }
318
319
320
321
322
323
324
325
326 public void activateObject(Object key, Object obj) throws Exception {
327 ((DelegatingPreparedStatement)obj).activate();
328 }
329
330
331
332
333
334
335
336
337
338 public void passivateObject(Object key, Object obj) throws Exception {
339 ((PreparedStatement)obj).clearParameters();
340 ((DelegatingPreparedStatement)obj).passivate();
341 }
342
343 public String toString() {
344 if (_pstmtPool != null ) {
345 return "PoolingConnection: " + _pstmtPool.toString();
346 } else {
347 return "PoolingConnection: null";
348 }
349 }
350
351
352
353
354 static class PStmtKey {
355
356
357 protected String _sql = null;
358
359
360 protected Integer _resultSetType = null;
361
362
363 protected Integer _resultSetConcurrency = null;
364
365
366 protected String _catalog = null;
367
368
369
370
371
372 protected byte _stmtType = STATEMENT_PREPAREDSTMT;
373
374 PStmtKey(String sql) {
375 _sql = sql;
376 }
377
378 PStmtKey(String sql, String catalog) {
379 _sql = sql;
380 _catalog = catalog;
381 }
382
383 PStmtKey(String sql, String catalog, byte stmtType) {
384 _sql = sql;
385 _catalog = catalog;
386 _stmtType = stmtType;
387 }
388
389 PStmtKey(String sql, int resultSetType, int resultSetConcurrency) {
390 _sql = sql;
391 _resultSetType = new Integer(resultSetType);
392 _resultSetConcurrency = new Integer(resultSetConcurrency);
393 }
394
395 PStmtKey(String sql, String catalog, int resultSetType, int resultSetConcurrency) {
396 _sql = sql;
397 _catalog = catalog;
398 _resultSetType = new Integer(resultSetType);
399 _resultSetConcurrency = new Integer(resultSetConcurrency);
400 }
401
402 PStmtKey(String sql, String catalog, int resultSetType, int resultSetConcurrency, byte stmtType) {
403 _sql = sql;
404 _catalog = catalog;
405 _resultSetType = new Integer(resultSetType);
406 _resultSetConcurrency = new Integer(resultSetConcurrency);
407 _stmtType = stmtType;
408 }
409
410 public boolean equals(Object that) {
411 try {
412 PStmtKey key = (PStmtKey)that;
413 return( ((null == _sql && null == key._sql) || _sql.equals(key._sql)) &&
414 ((null == _catalog && null == key._catalog) || _catalog.equals(key._catalog)) &&
415 ((null == _resultSetType && null == key._resultSetType) || _resultSetType.equals(key._resultSetType)) &&
416 ((null == _resultSetConcurrency && null == key._resultSetConcurrency) || _resultSetConcurrency.equals(key._resultSetConcurrency)) &&
417 (_stmtType == key._stmtType)
418 );
419 } catch(ClassCastException e) {
420 return false;
421 } catch(NullPointerException e) {
422 return false;
423 }
424 }
425
426 public int hashCode() {
427 if (_catalog==null)
428 return(null == _sql ? 0 : _sql.hashCode());
429 else
430 return(null == _sql ? _catalog.hashCode() : (_catalog + _sql).hashCode());
431 }
432
433 public String toString() {
434 StringBuffer buf = new StringBuffer();
435 buf.append("PStmtKey: sql=");
436 buf.append(_sql);
437 buf.append(", catalog=");
438 buf.append(_catalog);
439 buf.append(", resultSetType=");
440 buf.append(_resultSetType);
441 buf.append(", resultSetConcurrency=");
442 buf.append(_resultSetConcurrency);
443 buf.append(", statmentType=");
444 buf.append(_stmtType);
445 return buf.toString();
446 }
447 }
448 }