001: /*
002: * The contents of this file are subject to the Mozilla Public License
003: * Version 1.1 (the "License"); you may not use this file except in
004: * compliance with the License. You may obtain a copy of the License at
005: * http://www.mozilla.org/MPL/
006: *
007: * Software distributed under the License is distributed on an "AS IS"
008: * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
009: * License for the specific language governing rights and limitations
010: * under the License.
011: *
012: * The Original Code is iSQL-Viewer, A Mutli-Platform Database Tool.
013: *
014: * The Initial Developer of the Original Code is iSQL-Viewer, A Mutli-Platform Database Tool.
015: * Portions created by Mark A. Kobold are Copyright (C) 2000-2007. All Rights Reserved.
016: *
017: * Contributor(s):
018: * Mark A. Kobold [mkobold <at> isqlviewer <dot> com].
019: *
020: * If you didn't download this code from the following link, you should check
021: * if you aren't using an obsolete version: http://www.isqlviewer.com
022: */
023: package org.isqlviewer.sql;
024:
025: import java.sql.CallableStatement;
026: import java.sql.Connection;
027: import java.sql.DatabaseMetaData;
028: import java.sql.PreparedStatement;
029: import java.sql.SQLException;
030: import java.sql.SQLWarning;
031: import java.sql.Savepoint;
032: import java.sql.Statement;
033: import java.util.ArrayList;
034: import java.util.Enumeration;
035: import java.util.Hashtable;
036: import java.util.Map;
037:
038: import org.isqlviewer.util.BasicUtilities;
039: import org.isqlviewer.util.LocalMessages;
040:
041: /**
042: * TODO Add ConnectionWrapper Overview JavaDoc.
043: * <p>
044: *
045: * @author Mark A. Kobold <mkobold at isqlviewer dot com>
046: * @version 1.0
047: */
048: class ConnectionWrapper implements Connection {
049:
050: static final String BUNDLE_NAME = "org.isqlviewer.sql.ResourceBundle";
051: private static final LocalMessages messages = new LocalMessages(
052: BUNDLE_NAME);
053: // Maximum for retrying creating a connection before giving up.
054: private static final int CONN_MAX_RETRY = 5;
055: // Delay between retries for creating a connection.
056: private static final int CONN_RETRY_INTERVAL = 1000;
057: private Hashtable<String, Statement> stmtMap = new Hashtable<String, Statement>();
058: private Hashtable<String, CallableStatement> procMap = new Hashtable<String, CallableStatement>();
059: private int holdability = 0;
060: private String catalog = null;
061: private boolean isClosed = false;
062: private long lastAccess = 0;
063: private Connection proxy = null;
064: private DatabaseMetadataWrapper metaData = null;
065: private StatementWrapper theStatement = null;
066: private ArrayList<Statement> openStatements = new ArrayList<Statement>();
067: private JdbcService dataSource = null;
068:
069: public ConnectionWrapper(JdbcService dataSource, Connection conn) {
070:
071: this .proxy = conn;
072: this .dataSource = dataSource;
073: }
074:
075: @Override
076: public int hashCode() {
077:
078: return proxy.hashCode();
079: }
080:
081: public Statement createStatement() throws SQLException {
082:
083: guardConnection();
084: if (theStatement == null) {
085: try {
086: theStatement = new StatementWrapper(this , proxy
087: .createStatement(), null);
088: } catch (SQLException sqle) {
089: error(messages.format("DataSource.GeneralMethodError",
090: "createStatement()"), sqle);
091: throw sqle;
092: } catch (Throwable t) {
093: SQLException sqle = createWrappedSQLException(t,
094: "createStatement()");
095: throw sqle;
096: }
097: }
098: return theStatement;
099: }
100:
101: public Statement createStatement(int resultSetType,
102: int resultSetConcurrency) throws SQLException {
103:
104: guardConnection();
105: try {
106: Statement stmt = proxy.createStatement(resultSetType,
107: resultSetConcurrency);
108: return new StatementWrapper(this , stmt, null);
109: } catch (SQLException sqle) {
110: error(messages.format("DataSource.GeneralMethodError",
111: "createStatement(int,int)"), sqle);
112: throw sqle;
113: } catch (Throwable t) {
114: SQLException sqle = createWrappedSQLException(t,
115: "createStatement(int,int)");
116: throw sqle;
117: }
118: }
119:
120: public Statement createStatement(int resultSetType,
121: int resultSetConcurrency, int resultSetHoldability)
122: throws SQLException {
123:
124: guardConnection();
125: try {
126: Statement stmt = proxy.createStatement(resultSetType,
127: resultSetConcurrency, resultSetHoldability);
128: return new StatementWrapper(this , stmt, null);
129: } catch (SQLException sqle) {
130: error(messages.format("DataSource.GeneralMethodError",
131: "createStatement(int,int,int)"), sqle);
132: throw sqle;
133: } catch (Throwable t) {
134: SQLException sqle = createWrappedSQLException(t,
135: "createStatement(int,int,int)");
136: throw sqle;
137: }
138: }
139:
140: public CallableStatement prepareCall(String sql)
141: throws SQLException {
142:
143: guardConnection();
144: CallableStatement stmt = procMap.get(sql);
145: if (stmt == null) {
146: try {
147: stmt = proxy.prepareCall(sql);
148: } catch (SQLException sqle) {
149: error(messages.format("DataSource.GeneralMethodError",
150: "prepareCall(String)"), sqle);
151: throw sqle;
152: } catch (Throwable t) {
153: SQLException sqle = createWrappedSQLException(t,
154: "prepareCall(String)");
155: throw sqle;
156: }
157:
158: stmt = new CallableStatementWrapper(this , stmt, sql);
159: synchronized (procMap) {
160: procMap.put(sql, stmt);
161: }
162: }
163: return stmt;
164: }
165:
166: public CallableStatement prepareCall(String sql, int resultSetType,
167: int resultSetConcurrency) throws SQLException {
168:
169: guardConnection();
170: try {
171: CallableStatement stmt = proxy.prepareCall(sql,
172: resultSetType, resultSetConcurrency);
173: return new CallableStatementWrapper(this , stmt, sql);
174: } catch (SQLException sqle) {
175: error(messages.format("DataSource.GeneralMethodError",
176: "prepareCall(String,int,int)"), sqle);
177: throw sqle;
178: } catch (Throwable t) {
179: SQLException sqle = createWrappedSQLException(t,
180: "prepareCall(String,int,int)");
181: throw sqle;
182: }
183: }
184:
185: public CallableStatement prepareCall(String sql, int resultSetType,
186: int resultSetConcurrency, int resultSetHoldability)
187: throws SQLException {
188:
189: guardConnection();
190: try {
191: CallableStatement stmt = proxy.prepareCall(sql,
192: resultSetType, resultSetConcurrency,
193: resultSetHoldability);
194: return stmt;
195: } catch (SQLException sqle) {
196: error(messages.format("DataSource.GeneralMethodError",
197: "prepareCall(String,int,int,int)"), sqle);
198: throw sqle;
199: } catch (Throwable t) {
200: SQLException sqle = createWrappedSQLException(t,
201: "prepareCall(String,int,int,int)");
202: throw sqle;
203: }
204: }
205:
206: public PreparedStatement prepareStatement(String sql)
207: throws SQLException {
208:
209: guardConnection();
210: PreparedStatement stmt = (PreparedStatement) stmtMap.get(sql);
211: if (stmt == null) {
212: try {
213: stmt = proxy.prepareStatement(sql);
214: } catch (SQLException sqle) {
215: error(messages.format("DataSource.GeneralMethodError",
216: "prepareStatement(String)"), sqle);
217: throw sqle;
218: } catch (Throwable t) {
219: SQLException sqle = createWrappedSQLException(t,
220: "prepareStatement(String)");
221: throw sqle;
222: }
223: stmt = new PreparedStatementWrapper(this , stmt, sql);
224: synchronized (stmtMap) {
225: stmtMap.put(sql, stmt);
226: }
227: }
228: return stmt;
229: }
230:
231: public PreparedStatement prepareStatement(String sql,
232: int resultSetType, int resultSetConcurrency)
233: throws SQLException {
234:
235: guardConnection();
236: try {
237: PreparedStatement stmt = proxy.prepareStatement(sql,
238: resultSetType, resultSetConcurrency);
239: return stmt;
240: } catch (SQLException sqle) {
241: error(messages.format("DataSource.GeneralMethodError",
242: "prepareStatement(String,int,int)"), sqle);
243: throw sqle;
244: } catch (Throwable t) {
245: SQLException sqle = createWrappedSQLException(t,
246: "prepareStatement(String,int,int)");
247: throw sqle;
248: }
249: }
250:
251: public PreparedStatement prepareStatement(String sql,
252: int resultSetType, int resultSetConcurrency,
253: int resultSetHoldability) throws SQLException {
254:
255: guardConnection();
256: try {
257: PreparedStatement stmt = proxy.prepareStatement(sql,
258: resultSetType, resultSetConcurrency,
259: resultSetHoldability);
260: return stmt;
261: } catch (SQLException sqle) {
262: error(messages.format("DataSource.GeneralMethodError",
263: "prepareStatement(String,int,int,int)"), sqle);
264: throw sqle;
265: } catch (Throwable t) {
266: SQLException sqle = createWrappedSQLException(t,
267: "prepareStatement(String,int,int,int)");
268: throw sqle;
269: }
270: }
271:
272: public PreparedStatement prepareStatement(String sql,
273: int autoGeneratedKeys) throws SQLException {
274:
275: guardConnection();
276: try {
277: PreparedStatement stmt = proxy.prepareStatement(sql,
278: autoGeneratedKeys);
279: return stmt;
280: } catch (SQLException sqle) {
281: error(messages.format("DataSource.GeneralMethodError",
282: "prepareStatement(String,int)"), sqle);
283: throw sqle;
284: } catch (Throwable t) {
285: SQLException sqle = createWrappedSQLException(t,
286: "prepareStatement(String,int)");
287: throw sqle;
288: }
289: }
290:
291: public PreparedStatement prepareStatement(String sql,
292: int[] columnIndexes) throws SQLException {
293:
294: guardConnection();
295: try {
296: PreparedStatement stmt = proxy.prepareStatement(sql,
297: columnIndexes);
298: return stmt;
299: } catch (SQLException sqle) {
300: error(messages.format("DataSource.GeneralMethodError",
301: "prepareStatement(String,int[])"), sqle);
302: throw sqle;
303: } catch (Throwable t) {
304: SQLException sqle = createWrappedSQLException(t,
305: "prepareStatement(String,int[])");
306: throw sqle;
307: }
308: }
309:
310: public PreparedStatement prepareStatement(String sql,
311: String[] columnNames) throws SQLException {
312:
313: guardConnection();
314: try {
315: PreparedStatement stmt = proxy.prepareStatement(sql,
316: columnNames);
317: return stmt;
318: } catch (SQLException sqle) {
319: error(messages.format("DataSource.GeneralMethodError",
320: "prepareStatement(String,String[])"), sqle);
321: throw sqle;
322: } catch (Throwable t) {
323: SQLException sqle = createWrappedSQLException(t,
324: "prepareStatement(String,String[])");
325: throw sqle;
326: }
327: }
328:
329: public void close() throws SQLException {
330:
331: updateLastAccess();
332: proxy.clearWarnings();
333: if (theStatement != null) {
334: theStatement.clearWarnings();
335: theStatement.close();
336: }
337: theStatement = null;
338: try {
339: proxy.setAutoCommit(true);
340: } catch (SQLException sqle) {
341: }
342: try {
343: proxy.setCatalog(catalog);
344: } catch (SQLException sqle) {
345: }
346: try {
347: proxy.setHoldability(holdability);
348: } catch (SQLException sqle) {
349: }
350: closeStatements(false);
351: try {
352: proxy.close();
353: } finally {
354: proxy = null;
355: dataSource.clearConnection();
356: dataSource = null;
357: }
358: }
359:
360: public Map<String, Class<?>> getTypeMap() throws SQLException {
361:
362: updateLastAccess();
363: try {
364: return proxy.getTypeMap();
365: } catch (SQLException sqle) {
366: error(messages.format("DataSource.GeneralMethodError",
367: "getTypeMap()"), sqle);
368: throw sqle;
369: } catch (Throwable t) {
370: SQLException sqle = createWrappedSQLException(t,
371: "getTypeMap()");
372: throw sqle;
373: }
374: }
375:
376: public int getHoldability() throws SQLException {
377:
378: updateLastAccess();
379: try {
380: return proxy.getHoldability();
381: } catch (SQLException sqle) {
382: error(messages.format("DataSource.GeneralMethodError",
383: "getHoldability()"), sqle);
384: throw sqle;
385: } catch (Throwable t) {
386: SQLException sqle = createWrappedSQLException(t,
387: "getHoldability()");
388: throw sqle;
389: }
390: }
391:
392: public String nativeSQL(String sql) throws SQLException {
393:
394: updateLastAccess();
395: try {
396: return proxy.nativeSQL(sql);
397: } catch (SQLException sqle) {
398: error(messages.format("DataSource.GeneralMethodError",
399: "nativeSQL(String)"), sqle);
400: throw sqle;
401: } catch (Throwable t) {
402: SQLException sqle = createWrappedSQLException(t,
403: "nativeSQL(String)");
404: throw sqle;
405: }
406: }
407:
408: public void setAutoCommit(boolean autoCommit) throws SQLException {
409:
410: updateLastAccess();
411: try {
412: // TODO re-implement this
413: // JdbcCommandLogger logger = dataSource.getCommandLogger();
414: // if (logger != null) {
415: // if (!autoCommit) {
416: // logger.logTransactionStarted(dataSource);
417: // } else {
418: // logger.logTransactionFinished(dataSource);
419: // }
420: // }
421: proxy.setAutoCommit(autoCommit);
422: } catch (SQLException sqle) {
423: error(messages.format("DataSource.GeneralMethodError",
424: "setAutoCommit(boolean)"), sqle);
425: throw sqle;
426: } catch (Throwable t) {
427: SQLException sqle = createWrappedSQLException(t,
428: "setAutoCommit(boolean)");
429: throw sqle;
430: }
431: }
432:
433: public boolean getAutoCommit() throws SQLException {
434:
435: updateLastAccess();
436: try {
437: return proxy.getAutoCommit();
438: } catch (SQLException sqle) {
439: error(messages.format("DataSource.GeneralMethodError",
440: "getAutoCommit()"), sqle);
441: throw sqle;
442: } catch (Throwable t) {
443: SQLException sqle = createWrappedSQLException(t,
444: "getAutoCommit()");
445: throw sqle;
446: }
447: }
448:
449: public void commit() throws SQLException {
450:
451: updateLastAccess();
452: try {
453: // TODO re-implement this
454: // JdbcCommandLogger logger = dataSource.getCommandLogger();
455: // if (logger != null) {
456: // logger.logTransactionCommited(dataSource);
457: // }
458: proxy.commit();
459: } catch (SQLException sqle) {
460: error(messages.format("DataSource.GeneralMethodError",
461: "commit()"), sqle);
462: throw sqle;
463: } catch (Throwable t) {
464: SQLException sqle = createWrappedSQLException(t, "commit()");
465: throw sqle;
466: } finally {
467: if (!supportsOpenCursorsAcrossCommit()) {
468: closeStatements(true);
469: }
470: if (!supportsOpenStatementsAcrossCommit()) {
471: closeStatements(false);
472: }
473: }
474: }
475:
476: public void rollback() throws SQLException {
477:
478: updateLastAccess();
479: try {
480: // TODO re-implement this
481: // JdbcCommandLogger logger = dataSource.getCommandLogger();
482: // if (logger != null) {
483: // logger.logTransactionRolledback(dataSource);
484: // }
485: proxy.rollback();
486: } catch (SQLException sqle) {
487: error(messages.format("DataSource.GeneralMethodError",
488: "rollback()"), sqle);
489: throw sqle;
490: } catch (Throwable t) {
491: SQLException sqle = createWrappedSQLException(t,
492: "rollback()");
493: throw sqle;
494: } finally {
495: if (!supportsOpenCursorsAcrossRollback()) {
496: closeStatements(true);
497: }
498: if (!supportsOpenStatementsAcrossRollback()) {
499: closeStatements(false);
500: }
501: }
502: }
503:
504: public boolean isClosed() throws SQLException {
505:
506: updateLastAccess();
507: try {
508: return proxy.isClosed();
509: } catch (SQLException sqle) {
510: error(messages.format("DataSource.GeneralMethodError",
511: "isClosed()"), sqle);
512: throw sqle;
513: } catch (Throwable t) {
514: SQLException sqle = createWrappedSQLException(t,
515: "isClosed()");
516: throw sqle;
517: }
518: }
519:
520: public synchronized DatabaseMetaData getMetaData()
521: throws SQLException {
522:
523: updateLastAccess();
524: try {
525: if (metaData == null) {
526: metaData = new DatabaseMetadataWrapper(this , proxy
527: .getMetaData());
528: }
529: return metaData;
530: } catch (SQLException sqle) {
531: error(messages.format("DataSource.GeneralMethodError",
532: "getMetaData()"), sqle);
533: throw sqle;
534: } catch (Throwable t) {
535: SQLException sqle = createWrappedSQLException(t,
536: "getMetaData()");
537: throw sqle;
538: }
539: }
540:
541: public void setReadOnly(boolean readOnly) throws SQLException {
542:
543: updateLastAccess();
544: try {
545: proxy.setReadOnly(readOnly);
546: } catch (SQLException sqle) {
547: error(messages.format("DataSource.GeneralMethodError",
548: "setReadOnly(boolean)"), sqle);
549: throw sqle;
550: } catch (Throwable t) {
551: SQLException sqle = createWrappedSQLException(t,
552: "setReadOnly(boolean)");
553: throw sqle;
554: }
555: }
556:
557: public boolean isReadOnly() throws SQLException {
558:
559: updateLastAccess();
560: try {
561: return proxy.isReadOnly();
562: } catch (SQLException sqle) {
563: error(messages.format("DataSource.GeneralMethodError",
564: "isReadOnly()"), sqle);
565: throw sqle;
566: } catch (Throwable t) {
567: SQLException sqle = createWrappedSQLException(t,
568: "isReadOnly()");
569: throw sqle;
570: }
571: }
572:
573: public void setCatalog(String catalog) throws SQLException {
574:
575: updateLastAccess();
576: try {
577: proxy.setCatalog(catalog);
578: } catch (SQLException sqle) {
579: error(messages.format("DataSource.GeneralMethodError",
580: "setCatalog(String)"), sqle);
581: throw sqle;
582: } catch (Throwable t) {
583: SQLException sqle = createWrappedSQLException(t,
584: "setCatalog(String)");
585: throw sqle;
586: }
587: }
588:
589: public String getCatalog() throws SQLException {
590:
591: updateLastAccess();
592: try {
593: return proxy.getCatalog();
594: } catch (SQLException sqle) {
595: error(messages.format("DataSource.GeneralMethodError",
596: "getCatalog()"), sqle);
597: throw sqle;
598: } catch (Throwable t) {
599: SQLException sqle = createWrappedSQLException(t,
600: "getCatalog())");
601: throw sqle;
602: }
603: }
604:
605: public void setTypeMap(Map<String, Class<?>> map)
606: throws SQLException {
607:
608: updateLastAccess();
609: try {
610: proxy.setTypeMap(map);
611: } catch (SQLException sqle) {
612: error(messages.format("DataSource.GeneralMethodError",
613: "setTypeMap(Map)"), sqle);
614: throw sqle;
615: } catch (Throwable t) {
616: SQLException sqle = createWrappedSQLException(t,
617: "setTypeMap(Map)");
618: throw sqle;
619: }
620: }
621:
622: public void setTransactionIsolation(int level) throws SQLException {
623:
624: updateLastAccess();
625: throw new SQLException(messages
626: .format("DataSource.TransactioIsoError"));
627: }
628:
629: public int getTransactionIsolation() throws SQLException {
630:
631: updateLastAccess();
632: try {
633: return proxy.getTransactionIsolation();
634: } catch (SQLException sqle) {
635: error(messages.format("DataSource.GeneralMethodError",
636: "getTransactionIsolation()"), sqle);
637: throw sqle;
638: } catch (Throwable t) {
639: SQLException sqle = createWrappedSQLException(t,
640: "getTransactionIsolation()");
641: throw sqle;
642: }
643: }
644:
645: public SQLWarning getWarnings() throws SQLException {
646:
647: updateLastAccess();
648: try {
649: return proxy.getWarnings();
650: } catch (SQLException sqle) {
651: error(messages.format("DataSource.GeneralMethodError",
652: "getWarnings()"), sqle);
653: throw sqle;
654: } catch (Throwable t) {
655: SQLException sqle = createWrappedSQLException(t,
656: "getWarnings()");
657: throw sqle;
658: }
659: }
660:
661: public void clearWarnings() throws SQLException {
662:
663: updateLastAccess();
664: try {
665: proxy.clearWarnings();
666: } catch (SQLException sqle) {
667: error(messages.format("DataSource.GeneralMethodError",
668: "clearWarnings()"), sqle);
669: throw sqle;
670: } catch (Throwable t) {
671: SQLException sqle = createWrappedSQLException(t,
672: "clearWarnings()");
673: throw sqle;
674: }
675: }
676:
677: public void releaseSavepoint(Savepoint savepoint)
678: throws SQLException {
679:
680: updateLastAccess();
681: try {
682: proxy.releaseSavepoint(savepoint);
683: } catch (SQLException sqle) {
684: error(messages.format("DataSource.GeneralMethodError",
685: "releaseSavepoint(Savepoint)"), sqle);
686: throw sqle;
687: } catch (Throwable t) {
688: SQLException sqle = createWrappedSQLException(t,
689: "releaseSavepoint(Savepoint)");
690: throw sqle;
691: }
692: }
693:
694: public void rollback(Savepoint savepoint) throws SQLException {
695:
696: updateLastAccess();
697: try {
698: proxy.rollback(savepoint);
699: } catch (SQLException sqle) {
700: error(messages.format("DataSource.GeneralMethodError",
701: "rollback(Savepoint)"), sqle);
702: throw sqle;
703: } catch (Throwable t) {
704: SQLException sqle = createWrappedSQLException(t,
705: "rollback(Savepoint)");
706: throw sqle;
707: }
708: }
709:
710: public void setHoldability(int holdability) throws SQLException {
711:
712: updateLastAccess();
713: try {
714: proxy.setHoldability(holdability);
715: } catch (SQLException sqle) {
716: error(messages.format("DataSource.GeneralMethodError",
717: "setHoldability(int)"), sqle);
718: throw sqle;
719: } catch (Throwable t) {
720: SQLException sqle = createWrappedSQLException(t,
721: "setHoldability(int)");
722: throw sqle;
723: }
724: }
725:
726: public Savepoint setSavepoint() throws SQLException {
727:
728: updateLastAccess();
729: try {
730: Savepoint savePoint = proxy.setSavepoint();
731: return savePoint;
732: } catch (SQLException sqle) {
733: error(messages.format("DataSource.GeneralMethodError",
734: "setSavePoint()"), sqle);
735: throw sqle;
736: } catch (Throwable t) {
737: SQLException sqle = createWrappedSQLException(t,
738: "setSavepoint()");
739: throw sqle;
740: }
741: }
742:
743: public Savepoint setSavepoint(String name) throws SQLException {
744:
745: updateLastAccess();
746: try {
747: Savepoint savePoint = proxy.setSavepoint(name);
748: return savePoint;
749: } catch (SQLException sqle) {
750: error(messages.format("DataSource.GeneralMethodError",
751: "setSavePoint(String)"), sqle);
752: throw sqle;
753: } catch (Throwable t) {
754: SQLException sqle = createWrappedSQLException(t,
755: "setSavepoint(name)");
756: throw sqle;
757: }
758: }
759:
760: boolean isIdle(int timeout) {
761:
762: long idle = timeout * 1000;
763: return (System.currentTimeMillis() - lastAccess) >= idle;
764: }
765:
766: /**
767: * Closes all PreparedStatments and CallableStatements
768: */
769: void closeStatements(boolean cursorsOnly) throws SQLException {
770:
771: boolean throwException = false;
772: if (theStatement != null && !cursorsOnly) {
773: try {
774: theStatement.getParent().close();
775: } catch (SQLException sqle) {
776: error("Error closing callable statements", sqle);
777: throwException = true;
778: }
779: }
780: // for prepared statements
781: Enumeration enumer = stmtMap.keys();
782: while (enumer.hasMoreElements()) {
783: Object key = enumer.nextElement();
784: try {
785: PreparedStatementWrapper stmt = (PreparedStatementWrapper) stmtMap
786: .get(key);
787: stmt.close();
788: } catch (SQLException ex) {
789: throwException = true;
790: } finally {
791: stmtMap.remove(key);
792: }
793: }
794: // for callable statements
795: enumer = procMap.keys();
796: while (enumer.hasMoreElements()) {
797: Object key = enumer.nextElement();
798: try {
799: PreparedStatementWrapper stmt = (PreparedStatementWrapper) stmtMap
800: .get(key);
801: if (stmt == null) {
802: continue;
803: }
804: stmt.close();
805: } catch (SQLException ex) {
806: throwException = true;
807: } finally {
808: procMap.remove(key);
809: }
810: }
811: if (throwException) {
812: throw new SQLException("Error closing statements");
813: }
814: }
815:
816: /**
817: * Returns when this connection was last checked out; 0 if it has never been used.
818: */
819: long getLastAccess() {
820:
821: return lastAccess;
822: }
823:
824: /**
825: * Returns when this connection was last checked out; 0 if it has never been used.
826: */
827: synchronized void updateLastAccess() throws SQLException {
828:
829: if (isClosed) {
830: throw new SQLException(messages
831: .format("DataSource.ConnectionClosed"));
832: }
833: lastAccess = System.currentTimeMillis();
834: }
835:
836: void add(StatementWrapper statement) {
837:
838: openStatements.add(statement);
839: }
840:
841: void remove(StatementWrapper statement) {
842:
843: openStatements.remove(statement);
844: }
845:
846: SQLException createWrappedSQLException(Throwable t, String method) {
847:
848: error(messages.format(
849: "DataSource.UnhandledExceptionDuringCall", method), t);
850: SQLException sqle = new SQLException(messages.format(
851: "DataSource.GeneralMethodError", method));
852: BasicUtilities.wrapThrowable(t, sqle);
853: return sqle;
854: }
855:
856: protected void info(Object message, Throwable error) {
857:
858: dataSource.info(message, error);
859: }
860:
861: protected void info(Object message) {
862:
863: dataSource.info(message);
864: }
865:
866: protected void trace(Object message, Throwable error) {
867:
868: dataSource.trace(message, error);
869: }
870:
871: protected void trace(Object message) {
872:
873: dataSource.trace(message);
874: }
875:
876: protected void error(Object message, Throwable error) {
877:
878: dataSource.error(message, error);
879: }
880:
881: protected void error(Object message) {
882:
883: dataSource.error(message);
884: }
885:
886: protected void warn(Object message, Throwable error) {
887:
888: dataSource.warn(message, error);
889: }
890:
891: protected void warn(Object message) {
892:
893: dataSource.warn(message);
894: }
895:
896: protected Connection getConnection() {
897:
898: return proxy;
899: }
900:
901: /*
902: * Check to see if the connection has been closed (typically by the server) and attempt to recover if it has.
903: */
904: protected void guardConnection() throws SQLException {
905:
906: boolean badConnection;
907: try {
908: badConnection = proxy.isClosed();
909: } catch (SQLException sqe) {
910: badConnection = true;
911: }
912: if (badConnection) {
913: String poolName = null;
914: synchronized (this ) {
915: warn(messages.format(
916: "PooledConnection.ConnectionGuardError",
917: poolName));
918: this .theStatement = null;
919: int retryCount = 0;
920: for (retryCount = 0; retryCount < CONN_MAX_RETRY; retryCount++) {
921: try {
922: proxy = dataSource.createDriverConnection(
923: dataSource.getPrincipal(), dataSource
924: .getCredentials());
925: } catch (SQLException SQE) {
926: try {
927: Thread.sleep(CONN_RETRY_INTERVAL);
928: } catch (InterruptedException ie) {
929: Thread.currentThread().interrupt();
930: trace(messages
931: .format(
932: "PooledConnection.ConnectionGuardInterrupted",
933: poolName));
934: throw new SQLException(
935: messages
936: .format("PooledConnection.ConnectionClosedUnexpectedly"));
937: }
938: continue;
939: }
940: info(messages.format(
941: "PooledConnection.ConnectionGuardSuccess",
942: poolName));
943: return;
944: }
945: }
946: }
947: }
948:
949: protected boolean supportsStatementPooling() {
950:
951: try {
952: DatabaseMetaData md = proxy.getMetaData();
953: return md.supportsStatementPooling();
954: } catch (Throwable t) {
955: return false;
956: }
957: }
958:
959: protected boolean supportsOpenCursorsAcrossCommit() {
960:
961: try {
962: DatabaseMetaData md = proxy.getMetaData();
963: return md.supportsOpenCursorsAcrossCommit();
964: } catch (Throwable t) {
965: return false;
966: }
967: }
968:
969: protected boolean supportsOpenCursorsAcrossRollback() {
970:
971: try {
972: DatabaseMetaData md = proxy.getMetaData();
973: return md.supportsOpenCursorsAcrossRollback();
974: } catch (Throwable t) {
975: return false;
976: }
977: }
978:
979: protected boolean supportsOpenStatementsAcrossCommit() {
980:
981: try {
982: DatabaseMetaData md = proxy.getMetaData();
983: return md.supportsOpenStatementsAcrossCommit();
984: } catch (Throwable t) {
985: return false;
986: }
987: }
988:
989: protected boolean supportsOpenStatementsAcrossRollback() {
990:
991: try {
992: DatabaseMetaData md = proxy.getMetaData();
993: return md.supportsOpenStatementsAcrossRollback();
994: } catch (Throwable t) {
995: return false;
996: }
997: }
998: }
|