001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.resource.adapter.jdbc;
023:
024: import java.sql.CallableStatement;
025: import java.sql.Connection;
026: import java.sql.DatabaseMetaData;
027: import java.sql.PreparedStatement;
028: import java.sql.ResultSet;
029: import java.sql.SQLException;
030: import java.sql.SQLWarning;
031: import java.sql.Savepoint;
032: import java.sql.Statement;
033: import java.util.HashMap;
034: import java.util.Iterator;
035: import java.util.Map;
036:
037: import org.jboss.logging.Logger;
038: import org.jboss.util.NestedSQLException;
039:
040: /**
041: * A wrapper for a connection.
042: *
043: * @author <a href="mailto:d_jencks@users.sourceforge.net">David Jencks</a>
044: * @author <a href="mailto:adrian@jboss.com">Adrian Brock</a>
045: * @version $Revision: 57189 $
046: */
047: public class WrappedConnection implements Connection {
048: private static final Logger log = Logger
049: .getLogger(WrappedConnection.class);
050:
051: private BaseWrapperManagedConnection mc;
052:
053: private WrapperDataSource dataSource;
054:
055: private HashMap statements;
056:
057: private boolean closed = false;
058:
059: private int trackStatements;
060:
061: public WrappedConnection(final BaseWrapperManagedConnection mc) {
062: this .mc = mc;
063: if (mc != null)
064: trackStatements = mc.getTrackStatements();
065: }
066:
067: void setManagedConnection(final BaseWrapperManagedConnection mc) {
068: this .mc = mc;
069: if (mc != null)
070: trackStatements = mc.getTrackStatements();
071: }
072:
073: public WrapperDataSource getDataSource() {
074: return dataSource;
075: }
076:
077: protected void setDataSource(WrapperDataSource dataSource) {
078: this .dataSource = dataSource;
079: }
080:
081: public void setReadOnly(boolean readOnly) throws SQLException {
082: checkStatus();
083: mc.setJdbcReadOnly(readOnly);
084: }
085:
086: public boolean isReadOnly() throws SQLException {
087: checkStatus();
088: return mc.isJdbcReadOnly();
089: }
090:
091: public void close() throws SQLException {
092: closed = true;
093: if (mc != null) {
094: if (trackStatements != BaseWrapperManagedConnectionFactory.TRACK_STATEMENTS_FALSE_INT) {
095: synchronized (this ) {
096: if (statements != null) {
097: for (Iterator i = statements.entrySet()
098: .iterator(); i.hasNext();) {
099: Map.Entry entry = (Map.Entry) i.next();
100: WrappedStatement ws = (WrappedStatement) entry
101: .getKey();
102: if (trackStatements == BaseWrapperManagedConnectionFactory.TRACK_STATEMENTS_TRUE_INT) {
103: Throwable stackTrace = (Throwable) entry
104: .getValue();
105: log
106: .warn(
107: "Closing a statement you left open, please do your own housekeeping",
108: stackTrace);
109: }
110: try {
111: ws.internalClose();
112: } catch (Throwable t) {
113: log
114: .warn(
115: "Exception trying to close statement:",
116: t);
117: }
118: }
119: }
120: }
121: }
122: mc.closeHandle(this );
123: }
124: mc = null;
125: dataSource = null;
126: }
127:
128: public boolean isClosed() throws SQLException {
129: return closed;
130: }
131:
132: public Statement createStatement() throws SQLException {
133: checkTransaction();
134: try {
135: return new WrappedStatement(this , mc.getConnection()
136: .createStatement());
137: } catch (Throwable t) {
138: throw checkException(t);
139: }
140: }
141:
142: public Statement createStatement(int resultSetType,
143: int resultSetConcurrency) throws SQLException {
144: checkTransaction();
145: try {
146: return new WrappedStatement(this , mc.getConnection()
147: .createStatement(resultSetType,
148: resultSetConcurrency));
149: } catch (Throwable t) {
150: throw checkException(t);
151: }
152: }
153:
154: public Statement createStatement(int resultSetType,
155: int resultSetConcurrency, int resultSetHoldability)
156: throws SQLException {
157:
158: checkTransaction();
159: try {
160: return new WrappedStatement(this , mc.getConnection()
161: .createStatement(resultSetType,
162: resultSetConcurrency, resultSetHoldability));
163: } catch (Throwable t) {
164: throw checkException(t);
165: }
166: }
167:
168: public PreparedStatement prepareStatement(String sql)
169: throws SQLException {
170: checkTransaction();
171: try {
172: return new WrappedPreparedStatement(this , mc
173: .prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY,
174: ResultSet.CONCUR_READ_ONLY));
175: } catch (Throwable t) {
176: throw checkException(t);
177: }
178: }
179:
180: public PreparedStatement prepareStatement(String sql,
181: int resultSetType, int resultSetConcurrency)
182: throws SQLException {
183: checkTransaction();
184: try {
185: return new WrappedPreparedStatement(this , mc
186: .prepareStatement(sql, resultSetType,
187: resultSetConcurrency));
188: } catch (Throwable t) {
189: throw checkException(t);
190: }
191: }
192:
193: public PreparedStatement prepareStatement(String sql,
194: int resultSetType, int resultSetConcurrency,
195: int resultSetHoldability) throws SQLException {
196: checkTransaction();
197: try {
198: return new WrappedPreparedStatement(this , mc
199: .getConnection().prepareStatement(sql,
200: resultSetType, resultSetConcurrency,
201: resultSetHoldability));
202: } catch (Throwable t) {
203: throw checkException(t);
204: }
205: }
206:
207: public PreparedStatement prepareStatement(String sql,
208: int autoGeneratedKeys) throws SQLException {
209: checkTransaction();
210: try {
211: return new WrappedPreparedStatement(this , mc
212: .getConnection().prepareStatement(sql,
213: autoGeneratedKeys));
214: } catch (Throwable t) {
215: throw checkException(t);
216: }
217: }
218:
219: public PreparedStatement prepareStatement(String sql,
220: int[] columnIndexes) throws SQLException {
221: checkTransaction();
222: try {
223: return new WrappedPreparedStatement(this , mc
224: .getConnection().prepareStatement(sql,
225: columnIndexes));
226: } catch (Throwable t) {
227: throw checkException(t);
228: }
229: }
230:
231: public PreparedStatement prepareStatement(String sql,
232: String[] columnNames) throws SQLException {
233:
234: checkTransaction();
235: try {
236: return new WrappedPreparedStatement(this , mc
237: .getConnection().prepareStatement(sql, columnNames));
238: } catch (Throwable t) {
239: throw checkException(t);
240: }
241: }
242:
243: public CallableStatement prepareCall(String sql)
244: throws SQLException {
245: checkTransaction();
246: try {
247: return new WrappedCallableStatement(this , mc.prepareCall(
248: sql, ResultSet.TYPE_FORWARD_ONLY,
249: ResultSet.CONCUR_READ_ONLY));
250: } catch (Throwable t) {
251: throw checkException(t);
252: }
253: }
254:
255: public CallableStatement prepareCall(String sql, int resultSetType,
256: int resultSetConcurrency) throws SQLException {
257: checkTransaction();
258: try {
259: return new WrappedCallableStatement(this , mc.prepareCall(
260: sql, resultSetType, resultSetConcurrency));
261: } catch (Throwable t) {
262: throw checkException(t);
263: }
264: }
265:
266: public CallableStatement prepareCall(String sql, int resultSetType,
267: int resultSetConcurrency, int resultSetHoldability)
268: throws SQLException {
269:
270: checkTransaction();
271: try {
272: return new WrappedCallableStatement(this , mc
273: .getConnection().prepareCall(sql, resultSetType,
274: resultSetConcurrency, resultSetHoldability));
275: } catch (Throwable t) {
276: throw checkException(t);
277: }
278: }
279:
280: public String nativeSQL(String sql) throws SQLException {
281: checkTransaction();
282: try {
283: return mc.getConnection().nativeSQL(sql);
284: } catch (Throwable t) {
285: throw checkException(t);
286: }
287: }
288:
289: public void setAutoCommit(boolean autocommit) throws SQLException {
290: checkStatus();
291: mc.setJdbcAutoCommit(autocommit);
292: }
293:
294: public boolean getAutoCommit() throws SQLException {
295: checkStatus();
296: return mc.isJdbcAutoCommit();
297: }
298:
299: public void commit() throws SQLException {
300: checkTransaction();
301: mc.jdbcCommit();
302: }
303:
304: public void rollback() throws SQLException {
305: checkTransaction();
306: mc.jdbcRollback();
307: }
308:
309: public void rollback(Savepoint savepoint) throws SQLException {
310: checkTransaction();
311: mc.jdbcRollback(savepoint);
312: }
313:
314: public DatabaseMetaData getMetaData() throws SQLException {
315: checkTransaction();
316: try {
317: return mc.getConnection().getMetaData();
318: } catch (Throwable t) {
319: throw checkException(t);
320: }
321: }
322:
323: public void setCatalog(String catalog) throws SQLException {
324: checkTransaction();
325: try {
326: mc.getConnection().setCatalog(catalog);
327: } catch (Throwable t) {
328: throw checkException(t);
329: }
330: }
331:
332: public String getCatalog() throws SQLException {
333: checkTransaction();
334: try {
335: return mc.getConnection().getCatalog();
336: } catch (Throwable t) {
337: throw checkException(t);
338: }
339: }
340:
341: public void setTransactionIsolation(int isolationLevel)
342: throws SQLException {
343: checkStatus();
344: mc.setJdbcTransactionIsolation(isolationLevel);
345: }
346:
347: public int getTransactionIsolation() throws SQLException {
348: checkStatus();
349: return mc.getJdbcTransactionIsolation();
350: }
351:
352: public SQLWarning getWarnings() throws SQLException {
353: checkTransaction();
354: try {
355: return mc.getConnection().getWarnings();
356: } catch (Throwable t) {
357: throw checkException(t);
358: }
359: }
360:
361: public void clearWarnings() throws SQLException {
362: checkTransaction();
363: try {
364: mc.getConnection().clearWarnings();
365: } catch (Throwable t) {
366: throw checkException(t);
367: }
368: }
369:
370: public Map getTypeMap() throws SQLException {
371: checkTransaction();
372: try {
373: return mc.getConnection().getTypeMap();
374: } catch (Throwable t) {
375: throw checkException(t);
376: }
377: }
378:
379: public void setTypeMap(Map typeMap) throws SQLException {
380: checkTransaction();
381: try {
382: mc.getConnection().setTypeMap(typeMap);
383: } catch (Throwable t) {
384: throw checkException(t);
385: }
386: }
387:
388: public void setHoldability(int holdability) throws SQLException {
389: checkTransaction();
390: try {
391: mc.getConnection().setHoldability(holdability);
392: } catch (Throwable t) {
393: throw checkException(t);
394: }
395: }
396:
397: public int getHoldability() throws SQLException {
398: checkTransaction();
399: try {
400: return mc.getConnection().getHoldability();
401: } catch (Throwable t) {
402: throw checkException(t);
403: }
404: }
405:
406: public Savepoint setSavepoint() throws SQLException {
407: checkTransaction();
408: try {
409: return mc.getConnection().setSavepoint();
410: } catch (Throwable t) {
411: throw checkException(t);
412: }
413: }
414:
415: public Savepoint setSavepoint(String name) throws SQLException {
416: checkTransaction();
417: try {
418: return mc.getConnection().setSavepoint(name);
419: } catch (Throwable t) {
420: throw checkException(t);
421: }
422: }
423:
424: public void releaseSavepoint(Savepoint savepoint)
425: throws SQLException {
426: checkTransaction();
427: try {
428: mc.getConnection().releaseSavepoint(savepoint);
429: } catch (Throwable t) {
430: throw checkException(t);
431: }
432: }
433:
434: public Connection getUnderlyingConnection() throws SQLException {
435: checkTransaction();
436: return mc.getConnection();
437: }
438:
439: void checkTransaction() throws SQLException {
440: checkStatus();
441: mc.checkTransaction();
442: }
443:
444: /**
445: * The checkStatus method checks that the handle has not been closed and
446: * that it is associated with a managed connection.
447: *
448: * @exception SQLException if an error occurs
449: */
450: protected void checkStatus() throws SQLException {
451: if (closed)
452: throw new SQLException(
453: "Connection handle has been closed and is unusable");
454: if (mc == null)
455: throw new SQLException(
456: "Connection handle is not currently associated with a ManagedConnection");
457: }
458:
459: /**
460: * The base checkException method rethrows the supplied exception, informing
461: * the ManagedConnection of the error. Subclasses may override this to
462: * filter exceptions based on their severity.
463: *
464: * @param e a <code>SQLException</code> value
465: * @exception Exception if an error occurs
466: */
467: protected SQLException checkException(Throwable t)
468: throws SQLException {
469: if (mc != null)
470: mc.connectionError(t);
471: if (t instanceof SQLException)
472: throw (SQLException) t;
473: else
474: throw new NestedSQLException("Error", t);
475: }
476:
477: int getTrackStatements() {
478: return trackStatements;
479: }
480:
481: void registerStatement(WrappedStatement ws) {
482: if (trackStatements == BaseWrapperManagedConnectionFactory.TRACK_STATEMENTS_FALSE_INT)
483: return;
484:
485: synchronized (this ) {
486: if (statements == null)
487: statements = new HashMap();
488:
489: if (trackStatements == BaseWrapperManagedConnectionFactory.TRACK_STATEMENTS_TRUE_INT)
490: statements.put(ws, new Throwable("STACKTRACE"));
491: else
492: statements.put(ws, null);
493: }
494: }
495:
496: void unregisterStatement(WrappedStatement ws) {
497: if (trackStatements == BaseWrapperManagedConnectionFactory.TRACK_STATEMENTS_FALSE_INT)
498: return;
499: synchronized (this ) {
500: if (statements != null)
501: statements.remove(ws);
502: }
503: }
504:
505: void checkConfiguredQueryTimeout(WrappedStatement ws)
506: throws SQLException {
507: if (mc == null || dataSource == null)
508: return;
509:
510: int timeout = 0;
511:
512: // Use the transaction timeout
513: if (mc.isTransactionQueryTimeout())
514: timeout = dataSource.getTimeLeftBeforeTransactionTimeout();
515:
516: // Look for a configured value
517: if (timeout <= 0)
518: timeout = mc.getQueryTimeout();
519:
520: if (timeout > 0)
521: ws.setQueryTimeout(timeout);
522: }
523:
524: Logger getLogger() {
525: return log;
526: }
527: }
|