Source code: com/mysql/jdbc/jdbc2/optional/ConnectionWrapper.java
1 /*
2 Copyright (C) 2002-2004 MySQL AB
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of version 2 of the GNU General Public License as
6 published by the Free Software Foundation.
7
8
9 There are special exceptions to the terms and conditions of the GPL
10 as it is applied to this software. View the full text of the
11 exception exception in file EXCEPTIONS-CONNECTOR-J in the directory of this
12 software distribution.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
23 */
24 package com.mysql.jdbc.jdbc2.optional;
25
26 import java.sql.Connection;
27 import java.sql.SQLException;
28 import java.sql.Savepoint;
29 import java.sql.Statement;
30
31
32 /**
33 * This class serves as a wrapper for the org.gjt.mm.mysql.jdbc2.Connection
34 * class. It is returned to the application server which may wrap it again
35 * and then return it to the application client in response to
36 * dataSource.getConnection().
37 *
38 * <p>
39 * All method invocations are forwarded to org.gjt.mm.mysql.jdbc2.Connection
40 * unless the close method was previously called, in which case a sqlException
41 * is thrown. The close method performs a 'logical close' on the connection.
42 * </p>
43 *
44 * <p>
45 * All sqlExceptions thrown by the physical connection are intercepted and sent
46 * to connectionEvent listeners before being thrown to client.
47 * </p>
48 *
49 * @author Todd Wolff todd.wolff_at_prodigy.net
50 *
51 * @see org.gjt.mm.mysql.jdbc2.Connection
52 * @see org.gjt.mm.mysql.jdbc2.optional.MysqlPooledConnection
53 */
54 class ConnectionWrapper extends WrapperBase implements Connection {
55 private Connection mc = null;
56 private MysqlPooledConnection mpc = null;
57 private String invalidHandleStr = "Logical handle no longer valid";
58 private boolean closed;
59
60 /**
61 * Construct a new LogicalHandle and set instance variables
62 *
63 * @param mysqlPooledConnection reference to object that instantiated this
64 * object
65 * @param mysqlConnection physical connection to db
66 *
67 * @throws SQLException if an error occurs.
68 */
69 public ConnectionWrapper(MysqlPooledConnection mysqlPooledConnection,
70 Connection mysqlConnection) throws SQLException {
71 this.mpc = mysqlPooledConnection;
72 this.mc = mysqlConnection;
73 this.closed = false;
74 this.pooledConnection = this.mpc;
75 }
76
77 /**
78 * Passes call to method on physical connection instance. Notifies
79 * listeners of any caught exceptions before re-throwing to client.
80 *
81 * @see java.sql.Connection#setAutoCommit
82 */
83 public void setAutoCommit(boolean autoCommit) throws SQLException {
84 if (closed) {
85 throw new SQLException(invalidHandleStr);
86 } else {
87 try {
88 this.mc.setAutoCommit(autoCommit);
89 } catch (SQLException sqlException) {
90 checkAndFireConnectionError(sqlException);
91 }
92 }
93 }
94
95 /**
96 * Passes call to method on physical connection instance. Notifies
97 * listeners of any caught exceptions before re-throwing to client.
98 *
99 * @see java.sql.Connection#getAutoCommit()
100 */
101 public boolean getAutoCommit() throws SQLException {
102 if (closed) {
103 throw new SQLException(invalidHandleStr);
104 } else {
105 try {
106 return this.mc.getAutoCommit();
107 } catch (SQLException sqlException) {
108 checkAndFireConnectionError(sqlException);
109 }
110 }
111
112 return false; // we don't reach this code, compiler can't tell
113 }
114
115 /**
116 * Passes call to method on physical connection instance. Notifies
117 * listeners of any caught exceptions before re-throwing to client.
118 *
119 * @see java.sql.Connection#setCatalog()
120 */
121 public void setCatalog(String catalog) throws SQLException {
122 if (closed) {
123 throw new SQLException(invalidHandleStr);
124 } else {
125 try {
126 this.mc.setCatalog(catalog);
127 } catch (SQLException sqlException) {
128 checkAndFireConnectionError(sqlException);
129 }
130 }
131 }
132
133 /**
134 * Passes call to method on physical connection instance. Notifies
135 * listeners of any caught exceptions before re-throwing to client.
136 *
137 * @return the current catalog
138 *
139 * @throws SQLException if an error occurs
140 */
141 public String getCatalog() throws SQLException {
142 if (closed) {
143 throw new SQLException(invalidHandleStr);
144 } else {
145 try {
146 return this.mc.getCatalog();
147 } catch (SQLException sqlException) {
148 checkAndFireConnectionError(sqlException);
149 }
150 }
151
152 return null; // we don't reach this code, compiler can't tell
153 }
154
155 /**
156 * Passes call to method on physical connection instance. Notifies
157 * listeners of any caught exceptions before re-throwing to client.
158 *
159 * @see java.sql.Connection#isClosed()
160 */
161 public boolean isClosed() throws SQLException {
162 return (closed || this.mc.isClosed());
163 }
164
165 /**
166 * @see Connection#setHoldability(int)
167 */
168 public void setHoldability(int arg0) throws SQLException {
169 if (closed) {
170 throw new SQLException(invalidHandleStr);
171 } else {
172 try {
173 this.mc.setHoldability(arg0);
174 } catch (SQLException sqlException) {
175 checkAndFireConnectionError(sqlException);
176 }
177 }
178 }
179
180 /**
181 * @see Connection#getHoldability()
182 */
183 public int getHoldability() throws SQLException {
184 if (closed) {
185 throw new SQLException(invalidHandleStr);
186 } else {
187 try {
188 return this.mc.getHoldability();
189 } catch (SQLException sqlException) {
190 checkAndFireConnectionError(sqlException);
191 }
192 }
193
194 return Statement.CLOSE_CURRENT_RESULT; // we don't reach this code, compiler can't tell
195 }
196
197 /**
198 * Allows clients to determine how long this connection has been idle.
199 *
200 * @return how long the connection has been idle.
201 */
202 public long getIdleFor() {
203 return ((com.mysql.jdbc.Connection) mc).getIdleFor();
204 }
205
206 /**
207 * Passes call to method on physical connection instance. Notifies
208 * listeners of any caught exceptions before re-throwing to client.
209 *
210 * @return a metadata instance
211 *
212 * @throws SQLException if an error occurs
213 */
214 public java.sql.DatabaseMetaData getMetaData() throws SQLException {
215 if (closed) {
216 throw new SQLException(invalidHandleStr);
217 } else {
218 try {
219 return this.mc.getMetaData();
220 } catch (SQLException sqlException) {
221 checkAndFireConnectionError(sqlException);
222 }
223 }
224
225 return null; // we don't reach this code, compiler can't tell
226 }
227
228 /**
229 * Passes call to method on physical connection instance. Notifies
230 * listeners of any caught exceptions before re-throwing to client.
231 *
232 * @see java.sql.Connection#setReadOnly()
233 */
234 public void setReadOnly(boolean readOnly) throws SQLException {
235 if (closed) {
236 throw new SQLException(invalidHandleStr);
237 } else {
238 try {
239 this.mc.setReadOnly(readOnly);
240 } catch (SQLException sqlException) {
241 checkAndFireConnectionError(sqlException);
242 }
243 }
244 }
245
246 /**
247 * Passes call to method on physical connection instance. Notifies
248 * listeners of any caught exceptions before re-throwing to client.
249 *
250 * @see java.sql.Connection#isReadOnly()
251 */
252 public boolean isReadOnly() throws SQLException {
253 if (closed) {
254 throw new SQLException(invalidHandleStr);
255 } else {
256 try {
257 return this.mc.isReadOnly();
258 } catch (SQLException sqlException) {
259 checkAndFireConnectionError(sqlException);
260 }
261 }
262
263 return false; // we don't reach this code, compiler can't tell
264 }
265
266 /**
267 * @see Connection#setSavepoint()
268 */
269 public java.sql.Savepoint setSavepoint() throws SQLException {
270 if (closed) {
271 throw new SQLException(invalidHandleStr);
272 } else {
273 try {
274 return this.mc.setSavepoint();
275 } catch (SQLException sqlException) {
276 checkAndFireConnectionError(sqlException);
277 }
278 }
279
280 return null; // we don't reach this code, compiler can't tell
281 }
282
283 /**
284 * @see Connection#setSavepoint(String)
285 */
286 public java.sql.Savepoint setSavepoint(String arg0)
287 throws SQLException {
288 if (closed) {
289 throw new SQLException(invalidHandleStr);
290 } else {
291 try {
292 return this.mc.setSavepoint(arg0);
293 } catch (SQLException sqlException) {
294 checkAndFireConnectionError(sqlException);
295 }
296 }
297
298 return null; // we don't reach this code, compiler can't tell
299 }
300
301 /**
302 * Passes call to method on physical connection instance. Notifies
303 * listeners of any caught exceptions before re-throwing to client.
304 *
305 * @see java.sql.Connection#setTransactionIsolation()
306 */
307 public void setTransactionIsolation(int level) throws SQLException {
308 if (closed) {
309 throw new SQLException(invalidHandleStr);
310 } else {
311 try {
312 this.mc.setTransactionIsolation(level);
313 } catch (SQLException sqlException) {
314 checkAndFireConnectionError(sqlException);
315 }
316 }
317 }
318
319 /**
320 * Passes call to method on physical connection instance. Notifies
321 * listeners of any caught exceptions before re-throwing to client.
322 *
323 * @see java.sql.Connection#getTransactionIsolation()
324 */
325 public int getTransactionIsolation() throws SQLException {
326 if (closed) {
327 throw new SQLException(invalidHandleStr);
328 } else {
329 try {
330 return this.mc.getTransactionIsolation();
331 } catch (SQLException sqlException) {
332 checkAndFireConnectionError(sqlException);
333 }
334 }
335
336 return TRANSACTION_REPEATABLE_READ; // we don't reach this code, compiler can't tell
337 }
338
339 /**
340 * Passes call to method on physical connection instance. Notifies
341 * listeners of any caught exceptions before re-throwing to client.
342 *
343 * @see java.sql.Connection#setTypeMap()
344 */
345 public void setTypeMap(java.util.Map map) throws SQLException {
346 if (closed) {
347 throw new SQLException(invalidHandleStr);
348 } else {
349 try {
350 this.mc.setTypeMap(map);
351 } catch (SQLException sqlException) {
352 checkAndFireConnectionError(sqlException);
353 }
354 }
355 }
356
357 /**
358 * Passes call to method on physical connection instance. Notifies
359 * listeners of any caught exceptions before re-throwing to client.
360 *
361 * @see java.sql.Connection#getTypeMap()
362 */
363 public java.util.Map getTypeMap() throws SQLException {
364 if (closed) {
365 throw new SQLException(invalidHandleStr);
366 } else {
367 try {
368 return this.mc.getTypeMap();
369 } catch (SQLException sqlException) {
370 checkAndFireConnectionError(sqlException);
371 }
372 }
373
374 return null; // we don't reach this code, compiler can't tell
375 }
376
377 /**
378 * Passes call to method on physical connection instance. Notifies
379 * listeners of any caught exceptions before re-throwing to client.
380 *
381 * @see java.sql.Connection#getWarnings
382 */
383 public java.sql.SQLWarning getWarnings() throws SQLException {
384 if (closed) {
385 throw new SQLException(invalidHandleStr);
386 } else {
387 try {
388 return this.mc.getWarnings();
389 } catch (SQLException sqlException) {
390 checkAndFireConnectionError(sqlException);
391 }
392 }
393
394 return null; // we don't reach this code, compiler can't tell
395 }
396
397 /**
398 * Passes call to method on physical connection instance. Notifies
399 * listeners of any caught exceptions before re-throwing to client.
400 *
401 * @throws SQLException if an error occurs
402 */
403 public void clearWarnings() throws SQLException {
404 if (closed) {
405 throw new SQLException(invalidHandleStr);
406 } else {
407 try {
408 this.mc.clearWarnings();
409 } catch (SQLException sqlException) {
410 checkAndFireConnectionError(sqlException);
411 }
412 }
413 }
414
415 /**
416 * The physical connection is not actually closed. the physical connection
417 * is closed when the application server calls
418 * mysqlPooledConnection.close(). this object is de-referenced by the
419 * pooled connection each time mysqlPooledConnection.getConnection() is
420 * called by app server.
421 *
422 * @throws SQLException if an error occurs
423 */
424 public void close() throws SQLException {
425 close(true);
426 }
427
428 /**
429 * Passes call to method on physical connection instance. Notifies
430 * listeners of any caught exceptions before re-throwing to client.
431 *
432 * @throws SQLException if an error occurs
433 */
434 public void commit() throws SQLException {
435 if (closed) {
436 throw new SQLException(invalidHandleStr);
437 } else {
438 try {
439 this.mc.commit();
440 } catch (SQLException sqlException) {
441 checkAndFireConnectionError(sqlException);
442 }
443 }
444 }
445
446 /**
447 * Passes call to method on physical connection instance. Notifies
448 * listeners of any caught exceptions before re-throwing to client.
449 *
450 * @see java.sql.Connection#createStatement()
451 */
452 public java.sql.Statement createStatement() throws SQLException {
453 if (this.closed) {
454 throw new SQLException(invalidHandleStr);
455 } else {
456 try {
457 return new StatementWrapper(this.mpc, this.mc.createStatement());
458 } catch (SQLException sqlException) {
459 checkAndFireConnectionError(sqlException);
460 }
461 }
462
463 return null; // we don't reach this code, compiler can't tell
464 }
465
466 /**
467 * Passes call to method on physical connection instance. Notifies
468 * listeners of any caught exceptions before re-throwing to client.
469 *
470 * @see java.sql.Connection#createStatement()
471 */
472 public java.sql.Statement createStatement(int resultSetType,
473 int resultSetConcurrency) throws SQLException {
474 if (this.closed) {
475 throw new SQLException(invalidHandleStr);
476 } else {
477 try {
478 return new StatementWrapper(this.mpc,
479 this.mc.createStatement(resultSetType, resultSetConcurrency));
480 } catch (SQLException sqlException) {
481 checkAndFireConnectionError(sqlException);
482 }
483 }
484
485 return null; // we don't reach this code, compiler can't tell
486 }
487
488 /**
489 * @see Connection#createStatement(int, int, int)
490 */
491 public java.sql.Statement createStatement(int arg0, int arg1, int arg2)
492 throws SQLException {
493 if (this.closed) {
494 throw new SQLException(invalidHandleStr);
495 } else {
496 try {
497 return new StatementWrapper(this.mpc,
498 this.mc.createStatement(arg0, arg1, arg2));
499 } catch (SQLException sqlException) {
500 checkAndFireConnectionError(sqlException);
501 }
502 }
503
504 return null; // we don't reach this code, compiler can't tell
505 }
506
507 /**
508 * Passes call to method on physical connection instance. Notifies
509 * listeners of any caught exceptions before re-throwing to client.
510 *
511 * @see java.sql.Connection#nativeSQL()
512 */
513 public String nativeSQL(String sql) throws SQLException {
514 if (closed) {
515 throw new SQLException(invalidHandleStr);
516 } else {
517 try {
518 return this.mc.nativeSQL(sql);
519 } catch (SQLException sqlException) {
520 checkAndFireConnectionError(sqlException);
521 }
522 }
523
524 return null; // we don't reach this code, compiler can't tell
525 }
526
527 /**
528 * Passes call to method on physical connection instance. Notifies
529 * listeners of any caught exceptions before re-throwing to client.
530 *
531 * @see java.sql.Connection#prepareCall()
532 */
533 public java.sql.CallableStatement prepareCall(String sql)
534 throws SQLException {
535 if (closed) {
536 throw new SQLException(invalidHandleStr);
537 } else {
538 try {
539 return this.mc.prepareCall(sql);
540 } catch (SQLException sqlException) {
541 checkAndFireConnectionError(sqlException);
542 }
543 }
544
545 return null; // we don't reach this code, compiler can't tell
546 }
547
548 /**
549 * Passes call to method on physical connection instance. Notifies
550 * listeners of any caught exceptions before re-throwing to client.
551 *
552 * @see java.sql.Connection#prepareCall()
553 */
554 public java.sql.CallableStatement prepareCall(String sql,
555 int resultSetType, int resultSetConcurrency) throws SQLException {
556 if (closed) {
557 throw new SQLException(invalidHandleStr);
558 } else {
559 try {
560 return this.mc.prepareCall(sql, resultSetType,
561 resultSetConcurrency);
562 } catch (SQLException sqlException) {
563 checkAndFireConnectionError(sqlException);
564 }
565 }
566
567 return null; // we don't reach this code, compiler can't tell
568 }
569
570 /**
571 * @see Connection#prepareCall(String, int, int, int)
572 */
573 public java.sql.CallableStatement prepareCall(String arg0, int arg1,
574 int arg2, int arg3) throws SQLException {
575 if (closed) {
576 throw new SQLException(invalidHandleStr);
577 } else {
578 try {
579 return this.mc.prepareCall(arg0, arg1, arg2, arg3);
580 } catch (SQLException sqlException) {
581 checkAndFireConnectionError(sqlException);
582 }
583 }
584
585 return null; // we don't reach this code, compiler can't tell
586 }
587
588 /**
589 * Passes call to method on physical connection instance. Notifies
590 * listeners of any caught exceptions before re-throwing to client.
591 *
592 * @see java.sql.Connection#prepareStatement()
593 */
594 public java.sql.PreparedStatement prepareStatement(String sql)
595 throws SQLException {
596 if (this.closed) {
597 throw new SQLException(invalidHandleStr);
598 } else {
599 try {
600 return new PreparedStatementWrapper(this.mpc,
601 this.mc.prepareStatement(sql));
602 } catch (SQLException sqlException) {
603 checkAndFireConnectionError(sqlException);
604 }
605 }
606
607 return null; // we don't reach this code, compiler can't tell
608 }
609
610 /**
611 * Passes call to method on physical connection instance. Notifies
612 * listeners of any caught exceptions before re-throwing to client.
613 *
614 * @see java.sql.Connection#prepareStatement()
615 */
616 public java.sql.PreparedStatement prepareStatement(String sql,
617 int resultSetType, int resultSetConcurrency) throws SQLException {
618 if (this.closed) {
619 throw new SQLException(invalidHandleStr);
620 } else {
621 try {
622 return new PreparedStatementWrapper(this.mpc,
623 this.mc.prepareStatement(sql, resultSetType,
624 resultSetConcurrency));
625 } catch (SQLException sqlException) {
626 checkAndFireConnectionError(sqlException);
627 }
628 }
629
630 return null; // we don't reach this code, compiler can't tell
631 }
632
633 /**
634 * @see Connection#prepareStatement(String, int, int, int)
635 */
636 public java.sql.PreparedStatement prepareStatement(String arg0, int arg1,
637 int arg2, int arg3) throws SQLException {
638 if (this.closed) {
639 throw new SQLException(invalidHandleStr);
640 } else {
641 try {
642 return new PreparedStatementWrapper(this.mpc,
643 this.mc.prepareStatement(arg0, arg1, arg2, arg3));
644 } catch (SQLException sqlException) {
645 checkAndFireConnectionError(sqlException);
646 }
647 }
648
649 return null; // we don't reach this code, compiler can't tell
650 }
651
652 /**
653 * @see Connection#prepareStatement(String, int)
654 */
655 public java.sql.PreparedStatement prepareStatement(String arg0, int arg1)
656 throws SQLException {
657 if (this.closed) {
658 throw new SQLException(invalidHandleStr);
659 } else {
660 try {
661 return new PreparedStatementWrapper(this.mpc,
662 this.mc.prepareStatement(arg0, arg1));
663 } catch (SQLException sqlException) {
664 checkAndFireConnectionError(sqlException);
665 }
666 }
667
668 return null; // we don't reach this code, compiler can't tell
669 }
670
671 /**
672 * @see Connection#prepareStatement(String, int[])
673 */
674 public java.sql.PreparedStatement prepareStatement(String arg0, int[] arg1)
675 throws SQLException {
676 if (this.closed) {
677 throw new SQLException(invalidHandleStr);
678 } else {
679 try {
680 return new PreparedStatementWrapper(this.mpc,
681 this.mc.prepareStatement(arg0, arg1));
682 } catch (SQLException sqlException) {
683 checkAndFireConnectionError(sqlException);
684 }
685 }
686
687 return null; // we don't reach this code, compiler can't tell
688 }
689
690 /**
691 * @see Connection#prepareStatement(String, String[])
692 */
693 public java.sql.PreparedStatement prepareStatement(String arg0,
694 String[] arg1) throws SQLException {
695 if (this.closed) {
696 throw new SQLException(invalidHandleStr);
697 } else {
698 try {
699 return new PreparedStatementWrapper(this.mpc,
700 this.mc.prepareStatement(arg0, arg1));
701 } catch (SQLException sqlException) {
702 checkAndFireConnectionError(sqlException);
703 }
704 }
705
706 return null; // we don't reach this code, compiler can't tell
707 }
708
709 /**
710 * @see Connection#releaseSavepoint(Savepoint)
711 */
712 public void releaseSavepoint(Savepoint arg0) throws SQLException {
713 if (closed) {
714 throw new SQLException(invalidHandleStr);
715 } else {
716 try {
717 this.mc.releaseSavepoint(arg0);
718 } catch (SQLException sqlException) {
719 checkAndFireConnectionError(sqlException);
720 }
721 }
722 }
723
724 /**
725 * Passes call to method on physical connection instance. Notifies
726 * listeners of any caught exceptions before re-throwing to client.
727 *
728 * @see java.sql.Connection#rollback()
729 */
730 public void rollback() throws SQLException {
731 if (closed) {
732 throw new SQLException(invalidHandleStr);
733 } else {
734 try {
735 this.mc.rollback();
736 } catch (SQLException sqlException) {
737 checkAndFireConnectionError(sqlException);
738 }
739 }
740 }
741
742 /**
743 * @see Connection#rollback(Savepoint)
744 */
745 public void rollback(Savepoint arg0) throws SQLException {
746 if (closed) {
747 throw new SQLException(invalidHandleStr);
748 } else {
749 try {
750 this.mc.rollback(arg0);
751 } catch (SQLException sqlException) {
752 checkAndFireConnectionError(sqlException);
753 }
754 }
755 }
756
757 protected void close(boolean fireClosedEvent) throws SQLException {
758 synchronized (this.mpc) {
759 if (this.closed) {
760 return;
761 }
762
763 if (((com.mysql.jdbc.Connection) this.mc).getRollbackOnPooledClose() &&
764 !this.getAutoCommit()) {
765 rollback();
766 }
767
768 if (fireClosedEvent) {
769 this.mpc.callListener(MysqlPooledConnection.CONNECTION_CLOSED_EVENT,
770 null);
771 }
772
773 // set closed status to true so that if application client tries to make additional
774 // calls a sqlException will be thrown. The physical connection is
775 // re-used by the pooled connection each time getConnection is called.
776 this.closed = true;
777 }
778 }
779 }