/* * JBoss, Home of Professional Open Source. * Copyright 2006, Red Hat Middleware LLC, and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jboss.resource.adapter.jdbc; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.SQLWarning; import java.sql.Statement; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; /** * A wrapper for a statement. * * @todo remove the org.jboss.ejb.plugins.cmp.jdbc.WrappedStatement dependency * * @author <a href="mailto:d_jencks@users.sourceforge.net">David Jencks</a> * @author <a href="mailto:adrian@jboss.com">Adrian Brock</a> * @version $Revision: 74335 $ */ public abstract class WrappedStatement extends JBossWrapper implements Statement, StatementAccess, org.jboss.ejb.plugins.cmp.jdbc.WrappedStatement { private final WrappedConnection lc; private final Statement s; /** The result sets */ private HashMap<WrappedResultSet, Throwable> resultSets; /** Whether we are closed */ private AtomicBoolean closed = new AtomicBoolean(false); public WrappedStatement(final WrappedConnection lc, Statement s) { this.lc = lc; this.s = s; lc.registerStatement(this); } protected void lock() throws SQLException { lc.lock(); } protected void unlock() { lc.unlock(); } public void close() throws SQLException { if (closed.get()) return; closed.set(true); lc.unregisterStatement(this); internalClose(); } public boolean execute(String sql) throws SQLException { lock(); try { checkTransaction(); try { checkConfiguredQueryTimeout(); return s.execute(sql); } catch (Throwable t) { throw checkException(t); } } finally { unlock(); } } public boolean execute(String sql, int autoGeneratedKeys) throws SQLException { lock(); try { checkTransaction(); try { checkConfiguredQueryTimeout(); return s.execute(sql, autoGeneratedKeys); } catch (Throwable t) { throw checkException(t); } } finally { unlock(); } } public boolean execute(String sql, int[] columnIndexes) throws SQLException { lock(); try { checkTransaction(); try { checkConfiguredQueryTimeout(); return s.execute(sql, columnIndexes); } catch (Throwable t) { throw checkException(t); } } finally { unlock(); } } public boolean execute(String sql, String[]columnNames ) throws SQLException { lock(); try { checkTransaction(); try { checkConfiguredQueryTimeout(); return s.execute(sql, columnNames); } catch (Throwable t) { throw checkException(t); } } finally { unlock(); } } public Connection getConnection() throws SQLException { return lc; } public SQLWarning getWarnings() throws SQLException { lock(); try { checkState(); try { return s.getWarnings(); } catch (Throwable t) { throw checkException(t); } } finally { unlock(); } } public void clearWarnings() throws SQLException { lock(); try { checkState(); try { s.clearWarnings(); } catch (Throwable t) { throw checkException(t); } } finally { unlock(); } } public ResultSet executeQuery(String sql) throws SQLException { lock(); try { checkTransaction(); try { checkConfiguredQueryTimeout(); ResultSet result = s.executeQuery(sql); return registerResultSet(result); } catch (Throwable t) { throw checkException(t); } } finally { unlock(); } } public int executeUpdate(String sql) throws SQLException { lock(); try { checkTransaction(); try { checkConfiguredQueryTimeout(); return s.executeUpdate(sql); } catch (Throwable t) { throw checkException(t); } } finally { unlock(); } } public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException { lock(); try { checkTransaction(); try { checkConfiguredQueryTimeout(); return s.executeUpdate(sql, autoGeneratedKeys); } catch (Throwable t) { throw checkException(t); } } finally { unlock(); } } public int executeUpdate(String sql, int[] columnIndexes) throws SQLException { lock(); try { checkTransaction(); try { checkConfiguredQueryTimeout(); return s.executeUpdate(sql, columnIndexes); } catch (Throwable t) { throw checkException(t); } } finally { unlock(); } } public int executeUpdate(String sql, String[] columnNames) throws SQLException { lock(); try { checkTransaction(); try { checkConfiguredQueryTimeout(); return s.executeUpdate(sql, columnNames); } catch (Throwable t) { throw checkException(t); } } finally { unlock(); } } public int getMaxFieldSize() throws SQLException { lock(); try { checkState(); try { return s.getMaxFieldSize(); } catch (Throwable t) { throw checkException(t); } } finally { unlock(); } } public void setMaxFieldSize(int max) throws SQLException { lock(); try { checkState(); try { s.setMaxFieldSize(max); } catch (Throwable t) { throw checkException(t); } } finally { unlock(); } } public int getMaxRows() throws SQLException { lock(); try { checkState(); try { return s.getMaxRows(); } catch (Throwable t) { throw checkException(t); } } finally { unlock(); } } public void setMaxRows(int max) throws SQLException { lock(); try { checkState(); try { s.setMaxRows(max); } catch (Throwable t) { throw checkException(t); } } finally { unlock(); } } public void setEscapeProcessing(boolean enable) throws SQLException { lock(); try { checkState(); try { s.setEscapeProcessing(enable); } catch (Throwable t) { throw checkException(t); } } finally { unlock(); } } public int getQueryTimeout() throws SQLException { lock(); try { checkState(); try { return s.getQueryTimeout(); } catch (Throwable t) { throw checkException(t); } } finally { unlock(); } } public void setQueryTimeout(int timeout) throws SQLException { lock(); try { checkState(); try { s.setQueryTimeout(timeout); } catch (Throwable t) { throw checkException(t); } } finally { unlock(); } } public void cancel() throws SQLException { checkState(); try { s.cancel(); } catch (Throwable t) { throw checkException(t); } } public void setCursorName(String name) throws SQLException { lock(); try { checkState(); try { s.setCursorName(name); } catch (Throwable t) { throw checkException(t); } } finally { unlock(); } } public ResultSet getResultSet() throws SQLException { lock(); try { checkState(); try { ResultSet result = s.getResultSet(); if (result == null) return null; else return registerResultSet(result); } catch (Throwable t) { throw checkException(t); } } finally { unlock(); } } public int getUpdateCount() throws SQLException { lock(); try { checkState(); try { return s.getUpdateCount(); } catch (Throwable t) { throw checkException(t); } } finally { unlock(); } } public boolean getMoreResults() throws SQLException { lock(); try { checkState(); try { return s.getMoreResults(); } catch (Throwable t) { throw checkException(t); } } finally { unlock(); } } public boolean getMoreResults(int current) throws SQLException { lock(); try { checkState(); try { return s.getMoreResults(current); } catch (Throwable t) { throw checkException(t); } } finally { unlock(); } } public void setFetchDirection(int direction) throws SQLException { lock(); try { checkState(); try { s.setFetchDirection(direction); } catch (Throwable t) { throw checkException(t); } } finally { unlock(); } } public int getFetchDirection() throws SQLException { lock(); try { checkState(); try { return s.getFetchDirection(); } catch (Throwable t) { throw checkException(t); } } finally { unlock(); } } public void setFetchSize(int rows) throws SQLException { lock(); try { checkState(); try { s.setFetchSize(rows); } catch (Throwable t) { throw checkException(t); } } finally { unlock(); } } public int getFetchSize() throws SQLException { lock(); try { checkState(); try { return s.getFetchSize(); } catch (Throwable t) { throw checkException(t); } } finally { unlock(); } } public int getResultSetConcurrency() throws SQLException { lock(); try { checkState(); try { return s.getResultSetConcurrency(); } catch (Throwable t) { throw checkException(t); } } finally { unlock(); } } public int getResultSetType() throws SQLException { lock(); try { checkState(); try { return s.getResultSetType(); } catch (Throwable t) { throw checkException(t); } } finally { unlock(); } } public void addBatch(String sql) throws SQLException { lock(); try { checkState(); try { s.addBatch(sql); } catch (Throwable t) { throw checkException(t); } } finally { unlock(); } } public void clearBatch() throws SQLException { lock(); try { checkState(); try { s.clearBatch(); } catch (Throwable t) { throw checkException(t); } } finally { unlock(); } } public int[] executeBatch() throws SQLException { lock(); try { checkState(); try { checkConfiguredQueryTimeout(); return s.executeBatch(); } catch (Throwable t) { throw checkException(t); } } finally { unlock(); } } public ResultSet getGeneratedKeys() throws SQLException { lock(); try { checkState(); try { ResultSet resultSet = s.getGeneratedKeys(); return registerResultSet(resultSet); } catch (Throwable t) { throw checkException(t); } } finally { unlock(); } } public int getResultSetHoldability() throws SQLException { lock(); try { checkState(); try { return s.getResultSetHoldability(); } catch (Throwable t) { throw checkException(t); } } finally { unlock(); } } public Statement getUnderlyingStatement() throws SQLException { lock(); try { checkState(); return s; } finally { unlock(); } } protected Statement getWrappedObject() throws SQLException { return getUnderlyingStatement(); } protected SQLException checkException(Throwable t) throws SQLException { throw lc.checkException(t); } protected void checkTransaction() throws SQLException { checkState(); lc.checkTransaction(); } protected void checkConfiguredQueryTimeout() throws SQLException { lc.checkConfiguredQueryTimeout(this); } protected void checkTransactionActive() throws SQLException { lc.checkTransactionActive(); } protected void internalClose() throws SQLException { closed.set(true); try { closeResultSets(); } finally { s.close(); } } void checkState() throws SQLException { if (closed.get()) throw new SQLException("The statement is closed."); } protected abstract WrappedResultSet wrapResultSet(ResultSet resultSet); protected ResultSet registerResultSet(ResultSet resultSet) { if (resultSet != null) resultSet = wrapResultSet(resultSet); if (lc.getTrackStatements() == BaseWrapperManagedConnectionFactory.TRACK_STATEMENTS_FALSE_INT) return resultSet; WrappedResultSet wrapped = (WrappedResultSet) resultSet; synchronized (this) { if (resultSets == null) resultSets = new HashMap<WrappedResultSet, Throwable>(); if (lc.getTrackStatements() == BaseWrapperManagedConnectionFactory.TRACK_STATEMENTS_TRUE_INT) resultSets.put(wrapped, new Throwable("STACKTRACE")); else resultSets.put(wrapped, null); } return resultSet; } protected void unregisterResultSet(WrappedResultSet resultSet) { if (lc.getTrackStatements() == BaseWrapperManagedConnectionFactory.TRACK_STATEMENTS_FALSE_INT) return; synchronized (this) { if (resultSets != null) resultSets.remove(resultSet); } } protected void closeResultSets() { if (lc.getTrackStatements() == BaseWrapperManagedConnectionFactory.TRACK_STATEMENTS_FALSE_INT) return; synchronized (this) { if (resultSets == null) return; for (Iterator<Map.Entry<WrappedResultSet, Throwable>> i = resultSets.entrySet().iterator(); i.hasNext();) { Map.Entry<WrappedResultSet, Throwable> entry = i.next(); WrappedResultSet resultSet = entry.getKey(); if (lc.getTrackStatements() == BaseWrapperManagedConnectionFactory.TRACK_STATEMENTS_TRUE_INT) { Throwable stackTrace = entry.getValue(); lc.getLogger().warn("Closing a result set you left open! Please close it yourself.", stackTrace); } try { resultSet.internalClose(); } catch (Throwable t) { lc.getLogger().warn("Error closing a result set you left open! Please close it yourself.", t); } } resultSets.clear(); } } }