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
101 public PreparedStatement prepareStatement(String sql) throws SQLException {
102 if (null == _pstmtPool) {
103 throw new SQLException(
104 "Statement pool is null - closed or invalid PoolingConnection.");
105 }
106 try {
107 return(PreparedStatement)(_pstmtPool.borrowObject(createKey(sql)));
108 } catch(NoSuchElementException e) {
109 throw (SQLException) new SQLException("MaxOpenPreparedStatements limit reached").initCause(e);
110 } catch(RuntimeException e) {
111 throw e;
112 } catch(Exception e) {
113 throw new SQLNestedException("Borrow prepareStatement from pool failed", e);
114 }
115 }
116
117
118
119
120
121
122
123
124 public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
125 if (null == _pstmtPool) {
126 throw new SQLException(
127 "Statement pool is null - closed or invalid PoolingConnection.");
128 }
129 try {
130 return(PreparedStatement)(_pstmtPool.borrowObject(createKey(sql,resultSetType,resultSetConcurrency)));
131 } catch(NoSuchElementException e) {
132 throw (SQLException) new SQLException("MaxOpenPreparedStatements limit reached").initCause(e);
133 } catch(RuntimeException e) {
134 throw e;
135 } catch(Exception e) {
136 throw (SQLException) new SQLException("Borrow prepareStatement from pool failed").initCause(e);
137 }
138 }
139
140
141
142
143
144
145
146
147 public CallableStatement prepareCall(String sql) throws SQLException {
148 try {
149 return (CallableStatement) (_pstmtPool.borrowObject(createKey(sql, STATEMENT_CALLABLESTMT)));
150 } catch (NoSuchElementException e) {
151 throw new SQLNestedException("MaxOpenCallableStatements limit reached", e);
152 } catch (RuntimeException e) {
153 throw e;
154 } catch (Exception e) {
155 throw new SQLNestedException("Borrow callableStatement from pool failed", e);
156 }
157 }
158
159
160
161
162
163
164
165
166
167
168 public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
169 try {
170 return (CallableStatement) (_pstmtPool.borrowObject(createKey(sql, resultSetType,
171 resultSetConcurrency, STATEMENT_CALLABLESTMT)));
172 } catch (NoSuchElementException e) {
173 throw new SQLNestedException("MaxOpenCallableStatements limit reached", e);
174 } catch (RuntimeException e) {
175 throw e;
176 } catch (Exception e) {
177 throw new SQLNestedException("Borrow callableStatement from pool failed", e);
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 protected Object createKey(String sql, int resultSetType, int resultSetConcurrency) {
214 String catalog = null;
215 try {
216 catalog = getCatalog();
217 } catch (SQLException e) {}
218 return new PStmtKey(normalizeSQL(sql), catalog, resultSetType, resultSetConcurrency);
219 }
220
221
222
223
224
225
226
227
228 protected Object createKey(String sql, int resultSetType, int resultSetConcurrency, byte stmtType) {
229 String catalog = null;
230 try {
231 catalog = getCatalog();
232 } catch (SQLException e) {}
233 return new PStmtKey(normalizeSQL(sql), catalog, resultSetType, resultSetConcurrency, stmtType);
234 }
235
236
237
238
239
240 protected Object createKey(String sql) {
241 String catalog = null;
242 try {
243 catalog = getCatalog();
244 } catch (SQLException e) {}
245 return new PStmtKey(normalizeSQL(sql), catalog);
246 }
247
248
249
250
251
252
253 protected Object createKey(String sql, byte stmtType) {
254 String catalog = null;
255 try {
256 catalog = getCatalog();
257 } catch (SQLException e) {}
258 return new PStmtKey(normalizeSQL(sql), catalog, stmtType);
259 }
260
261
262
263
264
265 protected String normalizeSQL(String sql) {
266 return sql.trim();
267 }
268
269
270
271
272
273
274
275
276
277
278 public Object makeObject(Object obj) throws Exception {
279 if(null == obj || !(obj instanceof PStmtKey)) {
280 throw new IllegalArgumentException("Prepared statement key is null or invalid.");
281 } else {
282 PStmtKey key = (PStmtKey)obj;
283 if( null == key._resultSetType && null == key._resultSetConcurrency ) {
284 if (key._stmtType == STATEMENT_PREPAREDSTMT ) {
285 return new PoolablePreparedStatement(getDelegate().prepareStatement( key._sql), key, _pstmtPool, this);
286 } else {
287 return new PoolableCallableStatement(getDelegate().prepareCall( key._sql), key, _pstmtPool, this);
288 }
289 } else {
290 if(key._stmtType == STATEMENT_PREPAREDSTMT) {
291 return new PoolablePreparedStatement(getDelegate().prepareStatement(
292 key._sql, key._resultSetType.intValue(),key._resultSetConcurrency.intValue()), key, _pstmtPool, this);
293 } else {
294 return new PoolableCallableStatement( getDelegate().prepareCall(
295 key._sql,key._resultSetType.intValue(), key._resultSetConcurrency.intValue()), key, _pstmtPool, this);
296 }
297 }
298 }
299 }
300
301
302
303
304
305
306
307
308
309 public void destroyObject(Object key, Object obj) throws Exception {
310 if(obj instanceof DelegatingPreparedStatement) {
311 ((DelegatingPreparedStatement)obj).getInnermostDelegate().close();
312 } else {
313 ((PreparedStatement)obj).close();
314 }
315 }
316
317
318
319
320
321
322
323
324
325 public boolean validateObject(Object key, Object obj) {
326 return true;
327 }
328
329
330
331
332
333
334
335
336 public void activateObject(Object key, Object obj) throws Exception {
337 ((DelegatingPreparedStatement)obj).activate();
338 }
339
340
341
342
343
344
345
346
347
348 public void passivateObject(Object key, Object obj) throws Exception {
349 ((PreparedStatement)obj).clearParameters();
350 ((DelegatingPreparedStatement)obj).passivate();
351 }
352
353 public String toString() {
354 if (_pstmtPool != null ) {
355 return "PoolingConnection: " + _pstmtPool.toString();
356 } else {
357 return "PoolingConnection: null";
358 }
359 }
360
361
362
363
364 static class PStmtKey {
365
366
367 protected String _sql = null;
368
369
370 protected Integer _resultSetType = null;
371
372
373 protected Integer _resultSetConcurrency = null;
374
375
376 protected String _catalog = null;
377
378
379
380
381
382 protected byte _stmtType = STATEMENT_PREPAREDSTMT;
383
384 PStmtKey(String sql) {
385 _sql = sql;
386 }
387
388 PStmtKey(String sql, String catalog) {
389 _sql = sql;
390 _catalog = catalog;
391 }
392
393 PStmtKey(String sql, String catalog, byte stmtType) {
394 _sql = sql;
395 _catalog = catalog;
396 _stmtType = stmtType;
397 }
398
399 PStmtKey(String sql, int resultSetType, int resultSetConcurrency) {
400 _sql = sql;
401 _resultSetType = new Integer(resultSetType);
402 _resultSetConcurrency = new Integer(resultSetConcurrency);
403 }
404
405 PStmtKey(String sql, String catalog, int resultSetType, int resultSetConcurrency) {
406 _sql = sql;
407 _catalog = catalog;
408 _resultSetType = new Integer(resultSetType);
409 _resultSetConcurrency = new Integer(resultSetConcurrency);
410 }
411
412 PStmtKey(String sql, String catalog, int resultSetType, int resultSetConcurrency, byte stmtType) {
413 _sql = sql;
414 _catalog = catalog;
415 _resultSetType = new Integer(resultSetType);
416 _resultSetConcurrency = new Integer(resultSetConcurrency);
417 _stmtType = stmtType;
418 }
419
420 public boolean equals(Object that) {
421 try {
422 PStmtKey key = (PStmtKey)that;
423 return( ((null == _sql && null == key._sql) || _sql.equals(key._sql)) &&
424 ((null == _catalog && null == key._catalog) || _catalog.equals(key._catalog)) &&
425 ((null == _resultSetType && null == key._resultSetType) || _resultSetType.equals(key._resultSetType)) &&
426 ((null == _resultSetConcurrency && null == key._resultSetConcurrency) || _resultSetConcurrency.equals(key._resultSetConcurrency)) &&
427 (_stmtType == key._stmtType)
428 );
429 } catch(ClassCastException e) {
430 return false;
431 } catch(NullPointerException e) {
432 return false;
433 }
434 }
435
436 public int hashCode() {
437 if (_catalog==null)
438 return(null == _sql ? 0 : _sql.hashCode());
439 else
440 return(null == _sql ? _catalog.hashCode() : (_catalog + _sql).hashCode());
441 }
442
443 public String toString() {
444 StringBuffer buf = new StringBuffer();
445 buf.append("PStmtKey: sql=");
446 buf.append(_sql);
447 buf.append(", catalog=");
448 buf.append(_catalog);
449 buf.append(", resultSetType=");
450 buf.append(_resultSetType);
451 buf.append(", resultSetConcurrency=");
452 buf.append(_resultSetConcurrency);
453 buf.append(", statmentType=");
454 buf.append(_stmtType);
455 return buf.toString();
456 }
457 }
458 }