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.Connection;
025: import java.sql.ResultSet;
026: import java.sql.SQLException;
027: import java.sql.SQLWarning;
028: import java.sql.Statement;
029: import java.util.HashMap;
030: import java.util.Iterator;
031: import java.util.Map;
032:
033: /**
034: * A wrapper for a statement.
035: *
036: * @todo remove the org.jboss.ejb.plugins.cmp.jdbc.WrappedStatement dependency
037: *
038: * @author <a href="mailto:d_jencks@users.sourceforge.net">David Jencks</a>
039: * @author <a href="mailto:adrian@jboss.com">Adrian Brock</a>
040: * @author <a href="weston.price@jboss.com">Weston Price</a>
041: * @version $Revision: 57189 $
042: */
043: public class WrappedStatement implements Statement, StatementAccess,
044: org.jboss.ejb.plugins.cmp.jdbc.WrappedStatement {
045: private final WrappedConnection lc;
046: private final Statement s;
047:
048: /** The result sets */
049: private HashMap resultSets;
050:
051: /** Whether we are closed */
052: private boolean closed = false;
053:
054: /** The state lock */
055: private Object lock = new Object();
056:
057: public WrappedStatement(final WrappedConnection lc, Statement s) {
058: this .lc = lc;
059: this .s = s;
060: lc.registerStatement(this );
061: }
062:
063: public void close() throws SQLException {
064: synchronized (lock) {
065: if (closed)
066: return;
067:
068: closed = true;
069: }
070: lc.unregisterStatement(this );
071: internalClose();
072: }
073:
074: public boolean execute(String sql) throws SQLException {
075: checkTransaction();
076: try {
077: checkConfiguredQueryTimeout();
078: return s.execute(sql);
079: } catch (Throwable t) {
080: throw checkException(t);
081: }
082: }
083:
084: public boolean execute(String sql, int autoGeneratedKeys)
085: throws SQLException {
086: checkTransaction();
087: try {
088: checkConfiguredQueryTimeout();
089: return s.execute(sql, autoGeneratedKeys);
090: } catch (Throwable t) {
091: throw checkException(t);
092: }
093: }
094:
095: public boolean execute(String sql, int[] columnIndexes)
096: throws SQLException {
097: checkTransaction();
098: try {
099: checkConfiguredQueryTimeout();
100: return s.execute(sql, columnIndexes);
101: } catch (Throwable t) {
102: throw checkException(t);
103: }
104: }
105:
106: public boolean execute(String sql, String[] columnNames)
107: throws SQLException {
108: checkTransaction();
109: try {
110: checkConfiguredQueryTimeout();
111: return s.execute(sql, columnNames);
112: } catch (Throwable t) {
113: throw checkException(t);
114: }
115: }
116:
117: public Connection getConnection() throws SQLException {
118: return lc;
119: }
120:
121: public SQLWarning getWarnings() throws SQLException {
122: checkState();
123: try {
124: return s.getWarnings();
125: } catch (Throwable t) {
126: throw checkException(t);
127: }
128: }
129:
130: public void clearWarnings() throws SQLException {
131: checkState();
132: try {
133: s.clearWarnings();
134: } catch (Throwable t) {
135: throw checkException(t);
136: }
137: }
138:
139: public ResultSet executeQuery(String sql) throws SQLException {
140: checkTransaction();
141: try {
142: checkConfiguredQueryTimeout();
143: ResultSet result = s.executeQuery(sql);
144: return registerResultSet(result);
145: } catch (Throwable t) {
146: throw checkException(t);
147: }
148: }
149:
150: public int executeUpdate(String sql) throws SQLException {
151: checkTransaction();
152: try {
153: checkConfiguredQueryTimeout();
154: return s.executeUpdate(sql);
155: } catch (Throwable t) {
156: throw checkException(t);
157: }
158: }
159:
160: public int executeUpdate(String sql, int autoGeneratedKeys)
161: throws SQLException {
162: checkTransaction();
163: try {
164: checkConfiguredQueryTimeout();
165: return s.executeUpdate(sql, autoGeneratedKeys);
166: } catch (Throwable t) {
167: throw checkException(t);
168: }
169: }
170:
171: public int executeUpdate(String sql, int[] columnIndexes)
172: throws SQLException {
173: checkTransaction();
174: try {
175: checkConfiguredQueryTimeout();
176: return s.executeUpdate(sql, columnIndexes);
177: } catch (Throwable t) {
178: throw checkException(t);
179: }
180: }
181:
182: public int executeUpdate(String sql, String[] columnNames)
183: throws SQLException {
184: checkTransaction();
185: try {
186: checkConfiguredQueryTimeout();
187: return s.executeUpdate(sql, columnNames);
188: } catch (Throwable t) {
189: throw checkException(t);
190: }
191: }
192:
193: public int getMaxFieldSize() throws SQLException {
194: checkState();
195: try {
196: return s.getMaxFieldSize();
197: } catch (Throwable t) {
198: throw checkException(t);
199: }
200: }
201:
202: public void setMaxFieldSize(int max) throws SQLException {
203: checkState();
204: try {
205: s.setMaxFieldSize(max);
206: } catch (Throwable t) {
207: throw checkException(t);
208: }
209: }
210:
211: public int getMaxRows() throws SQLException {
212: checkState();
213: try {
214: return s.getMaxRows();
215: } catch (Throwable t) {
216: throw checkException(t);
217: }
218: }
219:
220: public void setMaxRows(int max) throws SQLException {
221: checkState();
222: try {
223: s.setMaxRows(max);
224: } catch (Throwable t) {
225: throw checkException(t);
226: }
227: }
228:
229: public void setEscapeProcessing(boolean enable) throws SQLException {
230: checkState();
231: try {
232: s.setEscapeProcessing(enable);
233: } catch (Throwable t) {
234: throw checkException(t);
235: }
236: }
237:
238: public int getQueryTimeout() throws SQLException {
239: checkState();
240: try {
241: return s.getQueryTimeout();
242: } catch (Throwable t) {
243: throw checkException(t);
244: }
245: }
246:
247: public void setQueryTimeout(int timeout) throws SQLException {
248: checkState();
249: try {
250: s.setQueryTimeout(timeout);
251: } catch (Throwable t) {
252: throw checkException(t);
253: }
254: }
255:
256: public void cancel() throws SQLException {
257: checkState();
258: try {
259: s.cancel();
260: } catch (Throwable t) {
261: throw checkException(t);
262: }
263: }
264:
265: public void setCursorName(String name) throws SQLException {
266: checkState();
267: try {
268: s.setCursorName(name);
269: } catch (Throwable t) {
270: throw checkException(t);
271: }
272: }
273:
274: public ResultSet getResultSet() throws SQLException {
275: checkState();
276: try {
277: ResultSet result = s.getResultSet();
278: if (result == null)
279: return null;
280: else
281: return registerResultSet(result);
282: } catch (Throwable t) {
283: throw checkException(t);
284: }
285: }
286:
287: public int getUpdateCount() throws SQLException {
288: checkState();
289: try {
290: return s.getUpdateCount();
291: } catch (Throwable t) {
292: throw checkException(t);
293: }
294: }
295:
296: public boolean getMoreResults() throws SQLException {
297: checkState();
298: try {
299: return s.getMoreResults();
300: } catch (Throwable t) {
301: throw checkException(t);
302: }
303: }
304:
305: public boolean getMoreResults(int current) throws SQLException {
306: checkState();
307: try {
308: return s.getMoreResults(current);
309: } catch (Throwable t) {
310: throw checkException(t);
311: }
312: }
313:
314: public void setFetchDirection(int direction) throws SQLException {
315: checkState();
316: try {
317: s.setFetchDirection(direction);
318: } catch (Throwable t) {
319: throw checkException(t);
320: }
321: }
322:
323: public int getFetchDirection() throws SQLException {
324: checkState();
325: try {
326: return s.getFetchDirection();
327: } catch (Throwable t) {
328: throw checkException(t);
329: }
330: }
331:
332: public void setFetchSize(int rows) throws SQLException {
333: checkState();
334: try {
335: s.setFetchSize(rows);
336: } catch (Throwable t) {
337: throw checkException(t);
338: }
339: }
340:
341: public int getFetchSize() throws SQLException {
342: checkState();
343: try {
344: return s.getFetchSize();
345: } catch (Throwable t) {
346: throw checkException(t);
347: }
348: }
349:
350: public int getResultSetConcurrency() throws SQLException {
351: checkState();
352: try {
353: return s.getResultSetConcurrency();
354: } catch (Throwable t) {
355: throw checkException(t);
356: }
357: }
358:
359: public int getResultSetType() throws SQLException {
360: checkState();
361: try {
362: return s.getResultSetType();
363: } catch (Throwable t) {
364: throw checkException(t);
365: }
366: }
367:
368: public void addBatch(String sql) throws SQLException {
369: checkState();
370: try {
371: s.addBatch(sql);
372: } catch (Throwable t) {
373: throw checkException(t);
374: }
375: }
376:
377: public void clearBatch() throws SQLException {
378: checkState();
379: try {
380: s.clearBatch();
381: } catch (Throwable t) {
382: throw checkException(t);
383: }
384: }
385:
386: public int[] executeBatch() throws SQLException {
387: checkState();
388: try {
389: checkConfiguredQueryTimeout();
390: return s.executeBatch();
391: } catch (Throwable t) {
392: throw checkException(t);
393: }
394: }
395:
396: public ResultSet getGeneratedKeys() throws SQLException {
397: checkState();
398: try {
399: ResultSet resultSet = s.getGeneratedKeys();
400: return registerResultSet(resultSet);
401: } catch (Throwable t) {
402: throw checkException(t);
403: }
404: }
405:
406: public int getResultSetHoldability() throws SQLException {
407: checkState();
408: try {
409: return s.getResultSetHoldability();
410: } catch (Throwable t) {
411: throw checkException(t);
412: }
413: }
414:
415: public Statement getUnderlyingStatement() throws SQLException {
416: checkState();
417: return s;
418: }
419:
420: protected SQLException checkException(Throwable t)
421: throws SQLException {
422: throw lc.checkException(t);
423: }
424:
425: protected void checkTransaction() throws SQLException {
426: checkState();
427: lc.checkTransaction();
428: }
429:
430: protected void checkConfiguredQueryTimeout() throws SQLException {
431: lc.checkConfiguredQueryTimeout(this );
432: }
433:
434: protected void internalClose() throws SQLException {
435: synchronized (lock) {
436: closed = true;
437: }
438: try {
439: closeResultSets();
440: } finally {
441: s.close();
442: }
443: }
444:
445: void checkState() throws SQLException {
446: synchronized (lock) {
447: if (closed)
448: throw new SQLException("The statement is closed.");
449: }
450: }
451:
452: protected ResultSet registerResultSet(ResultSet resultSet) {
453: if (resultSet != null)
454: resultSet = new WrappedResultSet(this , resultSet);
455:
456: if (lc.getTrackStatements() == BaseWrapperManagedConnectionFactory.TRACK_STATEMENTS_FALSE_INT)
457: return resultSet;
458:
459: synchronized (this ) {
460: if (resultSets == null)
461: resultSets = new HashMap();
462:
463: if (lc.getTrackStatements() == BaseWrapperManagedConnectionFactory.TRACK_STATEMENTS_TRUE_INT)
464: resultSets.put(resultSet, new Throwable("STACKTRACE"));
465: else
466: resultSets.put(resultSet, null);
467: }
468: return resultSet;
469: }
470:
471: protected void unregisterResultSet(WrappedResultSet resultSet) {
472: if (lc.getTrackStatements() == BaseWrapperManagedConnectionFactory.TRACK_STATEMENTS_FALSE_INT)
473: return;
474:
475: synchronized (this ) {
476: if (resultSets != null)
477: resultSets.remove(resultSet);
478: }
479: }
480:
481: protected void closeResultSets() {
482: if (lc.getTrackStatements() == BaseWrapperManagedConnectionFactory.TRACK_STATEMENTS_FALSE_INT)
483: return;
484:
485: synchronized (this ) {
486: if (resultSets == null)
487: return;
488: for (Iterator i = resultSets.entrySet().iterator(); i
489: .hasNext();) {
490: Map.Entry entry = (Map.Entry) i.next();
491: WrappedResultSet resultSet = (WrappedResultSet) entry
492: .getKey();
493: if (lc.getTrackStatements() == BaseWrapperManagedConnectionFactory.TRACK_STATEMENTS_TRUE_INT) {
494: Throwable stackTrace = (Throwable) entry.getValue();
495: lc
496: .getLogger()
497: .warn(
498: "Closing a result set you left open! Please close it yourself.",
499: stackTrace);
500: }
501: try {
502: resultSet.internalClose();
503: } catch (Throwable t) {
504: lc
505: .getLogger()
506: .warn(
507: "Error closing a result set you left open! Please close it yourself.",
508: t);
509: }
510: }
511: resultSets.clear();
512: }
513: }
514: }
|