001: /*
002: Copyright (C) 2002-2007 MySQL AB
003:
004: This program is free software; you can redistribute it and/or modify
005: it under the terms of version 2 of the GNU General Public License as
006: published by the Free Software Foundation.
007:
008: There are special exceptions to the terms and conditions of the GPL
009: as it is applied to this software. View the full text of the
010: exception in file EXCEPTIONS-CONNECTOR-J in the directory of this
011: software distribution.
012:
013: This program is distributed in the hope that it will be useful,
014: but WITHOUT ANY WARRANTY; without even the implied warranty of
015: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016: GNU General Public License for more details.
017:
018: You should have received a copy of the GNU General Public License
019: along with this program; if not, write to the Free Software
020: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
021:
022:
023:
024: */
025: package com.mysql.jdbc.jdbc2.optional;
026:
027: import java.lang.reflect.Constructor;
028: import java.sql.Connection;
029: import java.sql.SQLException;
030: import java.sql.Savepoint;
031: import java.sql.Statement;
032:
033: import com.mysql.jdbc.ConnectionImpl;
034: import com.mysql.jdbc.MysqlErrorNumbers;
035: import com.mysql.jdbc.SQLError;
036: import com.mysql.jdbc.Util;
037:
038: /**
039: * This class serves as a wrapper for the org.gjt.mm.mysql.jdbc2.Connection
040: * class. It is returned to the application server which may wrap it again and
041: * then return it to the application client in response to
042: * dataSource.getConnection().
043: *
044: * <p>
045: * All method invocations are forwarded to org.gjt.mm.mysql.jdbc2.Connection
046: * unless the close method was previously called, in which case a sqlException
047: * is thrown. The close method performs a 'logical close' on the connection.
048: * </p>
049: *
050: * <p>
051: * All sqlExceptions thrown by the physical connection are intercepted and sent
052: * to connectionEvent listeners before being thrown to client.
053: * </p>
054: *
055: * @author Todd Wolff todd.wolff_at_prodigy.net
056: *
057: * @see org.gjt.mm.mysql.jdbc2.Connection
058: * @see org.gjt.mm.mysql.jdbc2.optional.MysqlPooledConnection
059: */
060: public class ConnectionWrapper extends WrapperBase implements
061: Connection {
062: protected com.mysql.jdbc.ConnectionImpl mc = null;
063:
064: private MysqlPooledConnection mpc = null;
065:
066: private String invalidHandleStr = "Logical handle no longer valid";
067:
068: private boolean closed;
069: private boolean isForXa;
070:
071: private static final Constructor JDBC_4_CONNECTION_WRAPPER_CTOR;
072:
073: static {
074: if (Util.isJdbc4()) {
075: try {
076: JDBC_4_CONNECTION_WRAPPER_CTOR = Class
077: .forName(
078: "com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper")
079: .getConstructor(
080: new Class[] {
081: MysqlPooledConnection.class,
082: ConnectionImpl.class,
083: Boolean.TYPE });
084: } catch (SecurityException e) {
085: throw new RuntimeException(e);
086: } catch (NoSuchMethodException e) {
087: throw new RuntimeException(e);
088: } catch (ClassNotFoundException e) {
089: throw new RuntimeException(e);
090: }
091: } else {
092: JDBC_4_CONNECTION_WRAPPER_CTOR = null;
093: }
094: }
095:
096: protected static ConnectionWrapper getInstance(
097: MysqlPooledConnection mysqlPooledConnection,
098: ConnectionImpl mysqlConnection, boolean forXa)
099: throws SQLException {
100: if (!Util.isJdbc4()) {
101: return new ConnectionWrapper(mysqlPooledConnection,
102: mysqlConnection, forXa);
103: }
104:
105: return (ConnectionWrapper) Util.handleNewInstance(
106: JDBC_4_CONNECTION_WRAPPER_CTOR, new Object[] {
107: mysqlPooledConnection, mysqlConnection,
108: Boolean.valueOf(forXa) });
109: }
110:
111: /**
112: * Construct a new LogicalHandle and set instance variables
113: *
114: * @param mysqlPooledConnection
115: * reference to object that instantiated this object
116: * @param mysqlConnection
117: * physical connection to db
118: *
119: * @throws SQLException
120: * if an error occurs.
121: */
122: public ConnectionWrapper(
123: MysqlPooledConnection mysqlPooledConnection,
124: ConnectionImpl mysqlConnection, boolean forXa)
125: throws SQLException {
126: this .mpc = mysqlPooledConnection;
127: this .mc = mysqlConnection;
128: this .closed = false;
129: this .pooledConnection = this .mpc;
130: this .isForXa = forXa;
131:
132: if (this .isForXa) {
133: setInGlobalTx(false);
134: setAutoCommit(false);
135: }
136: }
137:
138: /**
139: * Passes call to method on physical connection instance. Notifies listeners
140: * of any caught exceptions before re-throwing to client.
141: *
142: * @see java.sql.Connection#setAutoCommit
143: */
144: public void setAutoCommit(boolean autoCommit) throws SQLException {
145: checkClosed();
146:
147: if (autoCommit && isInGlobalTx()) {
148: throw SQLError
149: .createSQLException(
150: "Can't set autocommit to 'true' on an XAConnection",
151: SQLError.SQL_STATE_INVALID_TRANSACTION_TERMINATION,
152: MysqlErrorNumbers.ER_XA_RMERR);
153: }
154:
155: try {
156: this .mc.setAutoCommit(autoCommit);
157: } catch (SQLException sqlException) {
158: checkAndFireConnectionError(sqlException);
159: }
160: }
161:
162: /**
163: * Passes call to method on physical connection instance. Notifies listeners
164: * of any caught exceptions before re-throwing to client.
165: *
166: * @see java.sql.Connection#getAutoCommit()
167: */
168: public boolean getAutoCommit() throws SQLException {
169: checkClosed();
170:
171: try {
172: return this .mc.getAutoCommit();
173: } catch (SQLException sqlException) {
174: checkAndFireConnectionError(sqlException);
175: }
176:
177: return false; // we don't reach this code, compiler can't tell
178: }
179:
180: /**
181: * Passes call to method on physical connection instance. Notifies listeners
182: * of any caught exceptions before re-throwing to client.
183: *
184: * @see java.sql.Connection#setCatalog()
185: */
186: public void setCatalog(String catalog) throws SQLException {
187: checkClosed();
188:
189: try {
190: this .mc.setCatalog(catalog);
191: } catch (SQLException sqlException) {
192: checkAndFireConnectionError(sqlException);
193: }
194: }
195:
196: /**
197: * Passes call to method on physical connection instance. Notifies listeners
198: * of any caught exceptions before re-throwing to client.
199: *
200: * @return the current catalog
201: *
202: * @throws SQLException
203: * if an error occurs
204: */
205: public String getCatalog() throws SQLException {
206: checkClosed();
207:
208: try {
209: return this .mc.getCatalog();
210: } catch (SQLException sqlException) {
211: checkAndFireConnectionError(sqlException);
212: }
213:
214: return null; // we don't reach this code, compiler can't tell
215: }
216:
217: /**
218: * Passes call to method on physical connection instance. Notifies listeners
219: * of any caught exceptions before re-throwing to client.
220: *
221: * @see java.sql.Connection#isClosed()
222: */
223: public boolean isClosed() throws SQLException {
224: return (this .closed || this .mc.isClosed());
225: }
226:
227: public boolean isMasterConnection() throws SQLException {
228: return this .mc.isMasterConnection();
229: }
230:
231: /**
232: * @see Connection#setHoldability(int)
233: */
234: public void setHoldability(int arg0) throws SQLException {
235: checkClosed();
236:
237: try {
238: this .mc.setHoldability(arg0);
239: } catch (SQLException sqlException) {
240: checkAndFireConnectionError(sqlException);
241: }
242: }
243:
244: /**
245: * @see Connection#getHoldability()
246: */
247: public int getHoldability() throws SQLException {
248: checkClosed();
249:
250: try {
251: return this .mc.getHoldability();
252: } catch (SQLException sqlException) {
253: checkAndFireConnectionError(sqlException);
254: }
255:
256: return Statement.CLOSE_CURRENT_RESULT; // we don't reach this code,
257: // compiler can't tell
258: }
259:
260: /**
261: * Allows clients to determine how long this connection has been idle.
262: *
263: * @return how long the connection has been idle.
264: */
265: public long getIdleFor() {
266: return this .mc.getIdleFor();
267: }
268:
269: /**
270: * Passes call to method on physical connection instance. Notifies listeners
271: * of any caught exceptions before re-throwing to client.
272: *
273: * @return a metadata instance
274: *
275: * @throws SQLException
276: * if an error occurs
277: */
278: public java.sql.DatabaseMetaData getMetaData() throws SQLException {
279: checkClosed();
280:
281: try {
282: return this .mc.getMetaData();
283: } catch (SQLException sqlException) {
284: checkAndFireConnectionError(sqlException);
285: }
286:
287: return null; // we don't reach this code, compiler can't tell
288: }
289:
290: /**
291: * Passes call to method on physical connection instance. Notifies listeners
292: * of any caught exceptions before re-throwing to client.
293: *
294: * @see java.sql.Connection#setReadOnly()
295: */
296: public void setReadOnly(boolean readOnly) throws SQLException {
297: checkClosed();
298:
299: try {
300: this .mc.setReadOnly(readOnly);
301: } catch (SQLException sqlException) {
302: checkAndFireConnectionError(sqlException);
303: }
304: }
305:
306: /**
307: * Passes call to method on physical connection instance. Notifies listeners
308: * of any caught exceptions before re-throwing to client.
309: *
310: * @see java.sql.Connection#isReadOnly()
311: */
312: public boolean isReadOnly() throws SQLException {
313: checkClosed();
314:
315: try {
316: return this .mc.isReadOnly();
317: } catch (SQLException sqlException) {
318: checkAndFireConnectionError(sqlException);
319: }
320:
321: return false; // we don't reach this code, compiler can't tell
322: }
323:
324: /**
325: * @see Connection#setSavepoint()
326: */
327: public java.sql.Savepoint setSavepoint() throws SQLException {
328: checkClosed();
329:
330: if (isInGlobalTx()) {
331: throw SQLError
332: .createSQLException(
333: "Can't set autocommit to 'true' on an XAConnection",
334: SQLError.SQL_STATE_INVALID_TRANSACTION_TERMINATION,
335: MysqlErrorNumbers.ER_XA_RMERR);
336: }
337:
338: try {
339: return this .mc.setSavepoint();
340: } catch (SQLException sqlException) {
341: checkAndFireConnectionError(sqlException);
342: }
343:
344: return null; // we don't reach this code, compiler can't tell
345: }
346:
347: /**
348: * @see Connection#setSavepoint(String)
349: */
350: public java.sql.Savepoint setSavepoint(String arg0)
351: throws SQLException {
352: checkClosed();
353:
354: if (isInGlobalTx()) {
355: throw SQLError
356: .createSQLException(
357: "Can't set autocommit to 'true' on an XAConnection",
358: SQLError.SQL_STATE_INVALID_TRANSACTION_TERMINATION,
359: MysqlErrorNumbers.ER_XA_RMERR);
360: }
361:
362: try {
363: return this .mc.setSavepoint(arg0);
364: } catch (SQLException sqlException) {
365: checkAndFireConnectionError(sqlException);
366: }
367:
368: return null; // we don't reach this code, compiler can't tell
369: }
370:
371: /**
372: * Passes call to method on physical connection instance. Notifies listeners
373: * of any caught exceptions before re-throwing to client.
374: *
375: * @see java.sql.Connection#setTransactionIsolation()
376: */
377: public void setTransactionIsolation(int level) throws SQLException {
378: checkClosed();
379:
380: try {
381: this .mc.setTransactionIsolation(level);
382: } catch (SQLException sqlException) {
383: checkAndFireConnectionError(sqlException);
384: }
385: }
386:
387: /**
388: * Passes call to method on physical connection instance. Notifies listeners
389: * of any caught exceptions before re-throwing to client.
390: *
391: * @see java.sql.Connection#getTransactionIsolation()
392: */
393: public int getTransactionIsolation() throws SQLException {
394: checkClosed();
395:
396: try {
397: return this .mc.getTransactionIsolation();
398: } catch (SQLException sqlException) {
399: checkAndFireConnectionError(sqlException);
400: }
401:
402: return TRANSACTION_REPEATABLE_READ; // we don't reach this code,
403: // compiler can't tell
404: }
405:
406: /**
407: * Passes call to method on physical connection instance. Notifies listeners
408: * of any caught exceptions before re-throwing to client.
409: *
410: * @see java.sql.Connection#setTypeMap()
411: */
412: public void setTypeMap(java.util.Map map) throws SQLException {
413: checkClosed();
414:
415: try {
416: this .mc.setTypeMap(map);
417: } catch (SQLException sqlException) {
418: checkAndFireConnectionError(sqlException);
419: }
420: }
421:
422: /**
423: * Passes call to method on physical connection instance. Notifies listeners
424: * of any caught exceptions before re-throwing to client.
425: *
426: * @see java.sql.Connection#getTypeMap()
427: */
428: public java.util.Map getTypeMap() throws SQLException {
429: checkClosed();
430:
431: try {
432: return this .mc.getTypeMap();
433: } catch (SQLException sqlException) {
434: checkAndFireConnectionError(sqlException);
435: }
436:
437: return null; // we don't reach this code, compiler can't tell
438: }
439:
440: /**
441: * Passes call to method on physical connection instance. Notifies listeners
442: * of any caught exceptions before re-throwing to client.
443: *
444: * @see java.sql.Connection#getWarnings
445: */
446: public java.sql.SQLWarning getWarnings() throws SQLException {
447: checkClosed();
448:
449: try {
450: return this .mc.getWarnings();
451: } catch (SQLException sqlException) {
452: checkAndFireConnectionError(sqlException);
453: }
454:
455: return null; // we don't reach this code, compiler can't tell
456: }
457:
458: /**
459: * Passes call to method on physical connection instance. Notifies listeners
460: * of any caught exceptions before re-throwing to client.
461: *
462: * @throws SQLException
463: * if an error occurs
464: */
465: public void clearWarnings() throws SQLException {
466: checkClosed();
467:
468: try {
469: this .mc.clearWarnings();
470: } catch (SQLException sqlException) {
471: checkAndFireConnectionError(sqlException);
472: }
473: }
474:
475: /**
476: * The physical connection is not actually closed. the physical connection
477: * is closed when the application server calls
478: * mysqlPooledConnection.close(). this object is de-referenced by the pooled
479: * connection each time mysqlPooledConnection.getConnection() is called by
480: * app server.
481: *
482: * @throws SQLException
483: * if an error occurs
484: */
485: public void close() throws SQLException {
486: close(true);
487: }
488:
489: /**
490: * Passes call to method on physical connection instance. Notifies listeners
491: * of any caught exceptions before re-throwing to client.
492: *
493: * @throws SQLException
494: * if an error occurs
495: */
496: public void commit() throws SQLException {
497: checkClosed();
498:
499: if (isInGlobalTx()) {
500: throw SQLError
501: .createSQLException(
502: "Can't call commit() on an XAConnection associated with a global transaction",
503: SQLError.SQL_STATE_INVALID_TRANSACTION_TERMINATION,
504: MysqlErrorNumbers.ER_XA_RMERR);
505: }
506:
507: try {
508: this .mc.commit();
509: } catch (SQLException sqlException) {
510: checkAndFireConnectionError(sqlException);
511: }
512: }
513:
514: /**
515: * Passes call to method on physical connection instance. Notifies listeners
516: * of any caught exceptions before re-throwing to client.
517: *
518: * @see java.sql.Connection#createStatement()
519: */
520: public java.sql.Statement createStatement() throws SQLException {
521: checkClosed();
522:
523: try {
524: return new StatementWrapper(this , this .mpc, this .mc
525: .createStatement());
526: } catch (SQLException sqlException) {
527: checkAndFireConnectionError(sqlException);
528: }
529:
530: return null; // we don't reach this code, compiler can't tell
531: }
532:
533: /**
534: * Passes call to method on physical connection instance. Notifies listeners
535: * of any caught exceptions before re-throwing to client.
536: *
537: * @see java.sql.Connection#createStatement()
538: */
539: public java.sql.Statement createStatement(int resultSetType,
540: int resultSetConcurrency) throws SQLException {
541: checkClosed();
542:
543: try {
544: return new StatementWrapper(this , this .mpc, this .mc
545: .createStatement(resultSetType,
546: resultSetConcurrency));
547: } catch (SQLException sqlException) {
548: checkAndFireConnectionError(sqlException);
549: }
550:
551: return null; // we don't reach this code, compiler can't tell
552: }
553:
554: /**
555: * @see Connection#createStatement(int, int, int)
556: */
557: public java.sql.Statement createStatement(int arg0, int arg1,
558: int arg2) throws SQLException {
559: checkClosed();
560:
561: try {
562: return new StatementWrapper(this , this .mpc, this .mc
563: .createStatement(arg0, arg1, arg2));
564: } catch (SQLException sqlException) {
565: checkAndFireConnectionError(sqlException);
566: }
567:
568: return null; // we don't reach this code, compiler can't tell
569: }
570:
571: /**
572: * Passes call to method on physical connection instance. Notifies listeners
573: * of any caught exceptions before re-throwing to client.
574: *
575: * @see java.sql.Connection#nativeSQL()
576: */
577: public String nativeSQL(String sql) throws SQLException {
578: checkClosed();
579:
580: try {
581: return this .mc.nativeSQL(sql);
582: } catch (SQLException sqlException) {
583: checkAndFireConnectionError(sqlException);
584: }
585:
586: return null; // we don't reach this code, compiler can't tell
587: }
588:
589: /**
590: * Passes call to method on physical connection instance. Notifies listeners
591: * of any caught exceptions before re-throwing to client.
592: *
593: * @see java.sql.Connection#prepareCall()
594: */
595: public java.sql.CallableStatement prepareCall(String sql)
596: throws SQLException {
597: checkClosed();
598:
599: try {
600: return new CallableStatementWrapper(this , this .mpc, this .mc
601: .prepareCall(sql));
602: } catch (SQLException sqlException) {
603: checkAndFireConnectionError(sqlException);
604: }
605:
606: return null; // we don't reach this code, compiler can't tell
607: }
608:
609: /**
610: * Passes call to method on physical connection instance. Notifies listeners
611: * of any caught exceptions before re-throwing to client.
612: *
613: * @see java.sql.Connection#prepareCall()
614: */
615: public java.sql.CallableStatement prepareCall(String sql,
616: int resultSetType, int resultSetConcurrency)
617: throws SQLException {
618: checkClosed();
619:
620: try {
621: return new CallableStatementWrapper(this , this .mpc, this .mc
622: .prepareCall(sql, resultSetType,
623: resultSetConcurrency));
624: } catch (SQLException sqlException) {
625: checkAndFireConnectionError(sqlException);
626: }
627:
628: return null; // we don't reach this code, compiler can't tell
629: }
630:
631: /**
632: * @see Connection#prepareCall(String, int, int, int)
633: */
634: public java.sql.CallableStatement prepareCall(String arg0,
635: int arg1, int arg2, int arg3) throws SQLException {
636: checkClosed();
637:
638: try {
639: return new CallableStatementWrapper(this , this .mpc, this .mc
640: .prepareCall(arg0, arg1, arg2, arg3));
641: } catch (SQLException sqlException) {
642: checkAndFireConnectionError(sqlException);
643: }
644:
645: return null; // we don't reach this code, compiler can't tell
646: }
647:
648: public java.sql.PreparedStatement clientPrepare(String sql)
649: throws SQLException {
650: checkClosed();
651:
652: try {
653: return new PreparedStatementWrapper(this , this .mpc, this .mc
654: .clientPrepareStatement(sql));
655: } catch (SQLException sqlException) {
656: checkAndFireConnectionError(sqlException);
657: }
658:
659: return null;
660: }
661:
662: public java.sql.PreparedStatement clientPrepare(String sql,
663: int resultSetType, int resultSetConcurrency)
664: throws SQLException {
665: checkClosed();
666:
667: try {
668: return new PreparedStatementWrapper(this , this .mpc, this .mc
669: .clientPrepareStatement(sql, resultSetType,
670: resultSetConcurrency));
671: } catch (SQLException sqlException) {
672: checkAndFireConnectionError(sqlException);
673: }
674:
675: return null;
676: }
677:
678: /**
679: * Passes call to method on physical connection instance. Notifies listeners
680: * of any caught exceptions before re-throwing to client.
681: *
682: * @see java.sql.Connection#prepareStatement()
683: */
684: public java.sql.PreparedStatement prepareStatement(String sql)
685: throws SQLException {
686: checkClosed();
687:
688: try {
689: return new PreparedStatementWrapper(this , this .mpc, this .mc
690: .prepareStatement(sql));
691: } catch (SQLException sqlException) {
692: checkAndFireConnectionError(sqlException);
693: }
694:
695: return null; // we don't reach this code, compiler can't tell
696: }
697:
698: /**
699: * Passes call to method on physical connection instance. Notifies listeners
700: * of any caught exceptions before re-throwing to client.
701: *
702: * @see java.sql.Connection#prepareStatement()
703: */
704: public java.sql.PreparedStatement prepareStatement(String sql,
705: int resultSetType, int resultSetConcurrency)
706: throws SQLException {
707: checkClosed();
708:
709: try {
710: return new PreparedStatementWrapper(this , this .mpc, this .mc
711: .prepareStatement(sql, resultSetType,
712: resultSetConcurrency));
713: } catch (SQLException sqlException) {
714: checkAndFireConnectionError(sqlException);
715: }
716:
717: return null; // we don't reach this code, compiler can't tell
718: }
719:
720: /**
721: * @see Connection#prepareStatement(String, int, int, int)
722: */
723: public java.sql.PreparedStatement prepareStatement(String arg0,
724: int arg1, int arg2, int arg3) throws SQLException {
725: checkClosed();
726:
727: try {
728: return new PreparedStatementWrapper(this , this .mpc, this .mc
729: .prepareStatement(arg0, arg1, arg2, arg3));
730: } catch (SQLException sqlException) {
731: checkAndFireConnectionError(sqlException);
732: }
733:
734: return null; // we don't reach this code, compiler can't tell
735: }
736:
737: /**
738: * @see Connection#prepareStatement(String, int)
739: */
740: public java.sql.PreparedStatement prepareStatement(String arg0,
741: int arg1) throws SQLException {
742: checkClosed();
743:
744: try {
745: return new PreparedStatementWrapper(this , this .mpc, this .mc
746: .prepareStatement(arg0, arg1));
747: } catch (SQLException sqlException) {
748: checkAndFireConnectionError(sqlException);
749: }
750:
751: return null; // we don't reach this code, compiler can't tell
752: }
753:
754: /**
755: * @see Connection#prepareStatement(String, int[])
756: */
757: public java.sql.PreparedStatement prepareStatement(String arg0,
758: int[] arg1) throws SQLException {
759: checkClosed();
760:
761: try {
762: return new PreparedStatementWrapper(this , this .mpc, this .mc
763: .prepareStatement(arg0, arg1));
764: } catch (SQLException sqlException) {
765: checkAndFireConnectionError(sqlException);
766: }
767:
768: return null; // we don't reach this code, compiler can't tell
769: }
770:
771: /**
772: * @see Connection#prepareStatement(String, String[])
773: */
774: public java.sql.PreparedStatement prepareStatement(String arg0,
775: String[] arg1) throws SQLException {
776: checkClosed();
777:
778: try {
779: return new PreparedStatementWrapper(this , this .mpc, this .mc
780: .prepareStatement(arg0, arg1));
781: } catch (SQLException sqlException) {
782: checkAndFireConnectionError(sqlException);
783: }
784:
785: return null; // we don't reach this code, compiler can't tell
786: }
787:
788: /**
789: * @see Connection#releaseSavepoint(Savepoint)
790: */
791: public void releaseSavepoint(Savepoint arg0) throws SQLException {
792: checkClosed();
793:
794: try {
795: this .mc.releaseSavepoint(arg0);
796: } catch (SQLException sqlException) {
797: checkAndFireConnectionError(sqlException);
798: }
799: }
800:
801: /**
802: * Passes call to method on physical connection instance. Notifies listeners
803: * of any caught exceptions before re-throwing to client.
804: *
805: * @see java.sql.Connection#rollback()
806: */
807: public void rollback() throws SQLException {
808: checkClosed();
809:
810: if (isInGlobalTx()) {
811: throw SQLError
812: .createSQLException(
813: "Can't call rollback() on an XAConnection associated with a global transaction",
814: SQLError.SQL_STATE_INVALID_TRANSACTION_TERMINATION,
815: MysqlErrorNumbers.ER_XA_RMERR);
816: }
817:
818: try {
819: this .mc.rollback();
820: } catch (SQLException sqlException) {
821: checkAndFireConnectionError(sqlException);
822: }
823: }
824:
825: /**
826: * @see Connection#rollback(Savepoint)
827: */
828: public void rollback(Savepoint arg0) throws SQLException {
829: checkClosed();
830:
831: if (isInGlobalTx()) {
832: throw SQLError
833: .createSQLException(
834: "Can't call rollback() on an XAConnection associated with a global transaction",
835: SQLError.SQL_STATE_INVALID_TRANSACTION_TERMINATION,
836: MysqlErrorNumbers.ER_XA_RMERR);
837: }
838:
839: try {
840: this .mc.rollback(arg0);
841: } catch (SQLException sqlException) {
842: checkAndFireConnectionError(sqlException);
843: }
844: }
845:
846: public boolean isSameResource(Connection c) {
847: if (c instanceof ConnectionWrapper) {
848: return this .mc.isSameResource(((ConnectionWrapper) c).mc);
849: } else if (c instanceof com.mysql.jdbc.Connection) {
850: return this .mc
851: .isSameResource((com.mysql.jdbc.Connection) c);
852: }
853:
854: return false;
855: }
856:
857: protected void close(boolean fireClosedEvent) throws SQLException {
858: synchronized (this .mpc) {
859: if (this .closed) {
860: return;
861: }
862:
863: if (!isInGlobalTx() && this .mc.getRollbackOnPooledClose()
864: && !this .getAutoCommit()) {
865: rollback();
866: }
867:
868: if (fireClosedEvent) {
869: this .mpc.callListener(
870: MysqlPooledConnection.CONNECTION_CLOSED_EVENT,
871: null);
872: }
873:
874: // set closed status to true so that if application client tries to
875: // make additional
876: // calls a sqlException will be thrown. The physical connection is
877: // re-used by the pooled connection each time getConnection is
878: // called.
879: this .closed = true;
880: }
881: }
882:
883: protected void checkClosed() throws SQLException {
884: if (this .closed) {
885: throw SQLError.createSQLException(this .invalidHandleStr);
886: }
887: }
888:
889: protected boolean isInGlobalTx() {
890: return this .mc.isInGlobalTx();
891: }
892:
893: protected void setInGlobalTx(boolean flag) {
894: this .mc.setInGlobalTx(flag);
895: }
896:
897: public void ping() throws SQLException {
898: if (this.mc != null) {
899: this.mc.ping();
900: }
901: }
902: }
|