/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.commons.dbcp;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.Statement;
import java.util.List;

A base delegating implementation of Statement.

All of the methods from the Statement interface simply check to see that the Statement is active, and call the corresponding method on the "delegate" provided in my constructor.

Extends AbandonedTrace to implement Statement tracking and logging of code which created the Statement. Tracking the Statement ensures that the Connection which created it can close any open Statement's on Connection close.

Author:Rodney Waldhoff, Glenn L. Nielsen, James House, Dirk Verbeeck
Version:$Revision: 896443 $ $Date: 2010-01-06 08:42:27 -0500 (Wed, 06 Jan 2010) $
/** * A base delegating implementation of {@link Statement}. * <p> * All of the methods from the {@link Statement} interface * simply check to see that the {@link Statement} is active, * and call the corresponding method on the "delegate" * provided in my constructor. * <p> * Extends AbandonedTrace to implement Statement tracking and * logging of code which created the Statement. Tracking the * Statement ensures that the Connection which created it can * close any open Statement's on Connection close. * * @author Rodney Waldhoff * @author Glenn L. Nielsen * @author James House * @author Dirk Verbeeck * @version $Revision: 896443 $ $Date: 2010-01-06 08:42:27 -0500 (Wed, 06 Jan 2010) $ */
public class DelegatingStatement extends AbandonedTrace implements Statement {
My delegate.
/** My delegate. */
protected Statement _stmt = null;
The connection that created me.
/** The connection that created me. **/
protected DelegatingConnection _conn = null;
Create a wrapper for the Statement which traces this Statement to the Connection which created it and the code which created it.
Params:
/** * Create a wrapper for the Statement which traces this * Statement to the Connection which created it and the * code which created it. * * @param s the {@link Statement} to delegate all calls to. * @param c the {@link DelegatingConnection} that created this statement. */
public DelegatingStatement(DelegatingConnection c, Statement s) { super(c); _stmt = s; _conn = c; }
Returns my underlying Statement.
See Also:
Returns:my underlying Statement.
/** * Returns my underlying {@link Statement}. * @return my underlying {@link Statement}. * @see #getInnermostDelegate */
public Statement getDelegate() { return _stmt; }
This method considers two objects to be equal if the underlying jdbc objects are equal.
/** * This method considers two objects to be equal * if the underlying jdbc objects are equal. */
public boolean equals(Object obj) { Statement delegate = getInnermostDelegate(); if (delegate == null) { return false; } if (obj instanceof DelegatingStatement) { DelegatingStatement s = (DelegatingStatement) obj; return delegate.equals(s.getInnermostDelegate()); } else { return delegate.equals(obj); } } public int hashCode() { Object obj = getInnermostDelegate(); if (obj == null) { return 0; } return obj.hashCode(); }
If my underlying Statement is not a DelegatingStatement, returns it, otherwise recursively invokes this method on my delegate.

Hence this method will return the first delegate that is not a DelegatingStatement or null when no non-DelegatingStatement delegate can be found by transversing this chain.

This method is useful when you may have nested DelegatingStatements, and you want to make sure to obtain a "genuine" Statement.

See Also:
/** * If my underlying {@link Statement} is not a * <tt>DelegatingStatement</tt>, returns it, * otherwise recursively invokes this method on * my delegate. * <p> * Hence this method will return the first * delegate that is not a <tt>DelegatingStatement</tt> * or <tt>null</tt> when no non-<tt>DelegatingStatement</tt> * delegate can be found by transversing this chain. * <p> * This method is useful when you may have nested * <tt>DelegatingStatement</tt>s, and you want to make * sure to obtain a "genuine" {@link Statement}. * @see #getDelegate */
public Statement getInnermostDelegate() { Statement s = _stmt; while(s != null && s instanceof DelegatingStatement) { s = ((DelegatingStatement)s).getDelegate(); if(this == s) { return null; } } return s; }
Sets my delegate.
/** Sets my delegate. */
public void setDelegate(Statement s) { _stmt = s; } protected boolean _closed = false; protected void checkOpen() throws SQLException { if(isClosed()) { throw new SQLException (this.getClass().getName() + " with address: \"" + this.toString() + "\" is closed."); } }
Close this DelegatingStatement, and close any ResultSets that were not explicitly closed.
/** * Close this DelegatingStatement, and close * any ResultSets that were not explicitly closed. */
public void close() throws SQLException { try { try { if (_conn != null) { _conn.removeTrace(this); _conn = null; } // The JDBC spec requires that a statment close any open // ResultSet's when it is closed. // FIXME The PreparedStatement we're wrapping should handle this for us. // See bug 17301 for what could happen when ResultSets are closed twice. List resultSets = getTrace(); if( resultSets != null) { ResultSet[] set = (ResultSet[]) resultSets.toArray(new ResultSet[resultSets.size()]); for (int i = 0; i < set.length; i++) { set[i].close(); } clearTrace(); } _stmt.close(); } catch (SQLException e) { handleException(e); } } finally { _closed = true; } } protected void handleException(SQLException e) throws SQLException { if (_conn != null) { _conn.handleException(e); } else { throw e; } } protected void activate() throws SQLException { if(_stmt instanceof DelegatingStatement) { ((DelegatingStatement)_stmt).activate(); } } protected void passivate() throws SQLException { if(_stmt instanceof DelegatingStatement) { ((DelegatingStatement)_stmt).passivate(); } } public Connection getConnection() throws SQLException { checkOpen(); return _conn; // return the delegating connection that created this } public ResultSet executeQuery(String sql) throws SQLException { checkOpen(); try { return DelegatingResultSet.wrapResultSet(this,_stmt.executeQuery(sql)); } catch (SQLException e) { handleException(e); throw new AssertionError(); } } public ResultSet getResultSet() throws SQLException { checkOpen(); try { return DelegatingResultSet.wrapResultSet(this,_stmt.getResultSet()); } catch (SQLException e) { handleException(e); throw new AssertionError(); } } public int executeUpdate(String sql) throws SQLException { checkOpen(); try { return _stmt.executeUpdate(sql); } catch (SQLException e) { handleException(e); return 0; } } public int getMaxFieldSize() throws SQLException { checkOpen(); try { return _stmt.getMaxFieldSize(); } catch (SQLException e) { handleException(e); return 0; } } public void setMaxFieldSize(int max) throws SQLException { checkOpen(); try { _stmt.setMaxFieldSize(max); } catch (SQLException e) { handleException(e); } } public int getMaxRows() throws SQLException { checkOpen(); try { return _stmt.getMaxRows(); } catch (SQLException e) { handleException(e); return 0; } } public void setMaxRows(int max) throws SQLException { checkOpen(); try { _stmt.setMaxRows(max); } catch (SQLException e) { handleException(e); } } public void setEscapeProcessing(boolean enable) throws SQLException { checkOpen(); try { _stmt.setEscapeProcessing(enable); } catch (SQLException e) { handleException(e); } } public int getQueryTimeout() throws SQLException { checkOpen(); try { return _stmt.getQueryTimeout(); } catch (SQLException e) { handleException(e); return 0; } } public void setQueryTimeout(int seconds) throws SQLException { checkOpen(); try { _stmt.setQueryTimeout(seconds); } catch (SQLException e) { handleException(e); } } public void cancel() throws SQLException { checkOpen(); try { _stmt.cancel(); } catch (SQLException e) { handleException(e); } } public SQLWarning getWarnings() throws SQLException { checkOpen(); try { return _stmt.getWarnings(); } catch (SQLException e) { handleException(e); throw new AssertionError(); } } public void clearWarnings() throws SQLException { checkOpen(); try { _stmt.clearWarnings(); } catch (SQLException e) { handleException(e); } } public void setCursorName(String name) throws SQLException { checkOpen(); try { _stmt.setCursorName(name); } catch (SQLException e) { handleException(e); } } public boolean execute(String sql) throws SQLException { checkOpen(); try { return _stmt.execute(sql); } catch (SQLException e) { handleException(e); return false; } } public int getUpdateCount() throws SQLException { checkOpen(); try { return _stmt.getUpdateCount(); } catch (SQLException e) { handleException(e); return 0; } } public boolean getMoreResults() throws SQLException { checkOpen(); try { return _stmt.getMoreResults(); } catch (SQLException e) { handleException(e); return false; } } public void setFetchDirection(int direction) throws SQLException { checkOpen(); try { _stmt.setFetchDirection(direction); } catch (SQLException e) { handleException(e); } } public int getFetchDirection() throws SQLException { checkOpen(); try { return _stmt.getFetchDirection(); } catch (SQLException e) { handleException(e); return 0; } } public void setFetchSize(int rows) throws SQLException { checkOpen(); try { _stmt.setFetchSize(rows); } catch (SQLException e) { handleException(e); } } public int getFetchSize() throws SQLException { checkOpen(); try { return _stmt.getFetchSize(); } catch (SQLException e) { handleException(e); return 0; } } public int getResultSetConcurrency() throws SQLException { checkOpen(); try { return _stmt.getResultSetConcurrency(); } catch (SQLException e) { handleException(e); return 0; } } public int getResultSetType() throws SQLException { checkOpen(); try { return _stmt.getResultSetType(); } catch (SQLException e) { handleException(e); return 0; } } public void addBatch(String sql) throws SQLException { checkOpen(); try { _stmt.addBatch(sql); } catch (SQLException e) { handleException(e); } } public void clearBatch() throws SQLException { checkOpen(); try { _stmt.clearBatch(); } catch (SQLException e) { handleException(e); } } public int[] executeBatch() throws SQLException { checkOpen(); try { return _stmt.executeBatch(); } catch (SQLException e) { handleException(e); throw new AssertionError(); } }
Returns a String representation of this object.
Returns:String
Since:1.2.2
/** * Returns a String representation of this object. * * @return String * @since 1.2.2 */
public String toString() { return _stmt.toString(); } public boolean getMoreResults(int current) throws SQLException { checkOpen(); try { return _stmt.getMoreResults(current); } catch (SQLException e) { handleException(e); return false; } } public ResultSet getGeneratedKeys() throws SQLException { checkOpen(); try { return DelegatingResultSet.wrapResultSet(this, _stmt.getGeneratedKeys()); } catch (SQLException e) { handleException(e); throw new AssertionError(); } } public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException { checkOpen(); try { return _stmt.executeUpdate(sql, autoGeneratedKeys); } catch (SQLException e) { handleException(e); return 0; } } public int executeUpdate(String sql, int columnIndexes[]) throws SQLException { checkOpen(); try { return _stmt.executeUpdate(sql, columnIndexes); } catch (SQLException e) { handleException(e); return 0; } } public int executeUpdate(String sql, String columnNames[]) throws SQLException { checkOpen(); try { return _stmt.executeUpdate(sql, columnNames); } catch (SQLException e) { handleException(e); return 0; } } public boolean execute(String sql, int autoGeneratedKeys) throws SQLException { checkOpen(); try { return _stmt.execute(sql, autoGeneratedKeys); } catch (SQLException e) { handleException(e); return false; } } public boolean execute(String sql, int columnIndexes[]) throws SQLException { checkOpen(); try { return _stmt.execute(sql, columnIndexes); } catch (SQLException e) { handleException(e); return false; } } public boolean execute(String sql, String columnNames[]) throws SQLException { checkOpen(); try { return _stmt.execute(sql, columnNames); } catch (SQLException e) { handleException(e); return false; } } public int getResultSetHoldability() throws SQLException { checkOpen(); try { return _stmt.getResultSetHoldability(); } catch (SQLException e) { handleException(e); return 0; } } /* * Note was protected prior to JDBC 4 * TODO Consider adding build flags to make this protected unless we are * using JDBC 4. */ public boolean isClosed() throws SQLException { return _closed; } /* JDBC_4_ANT_KEY_BEGIN */ public boolean isWrapperFor(Class<?> iface) throws SQLException { return iface.isAssignableFrom(getClass()) || _stmt.isWrapperFor(iface); } public <T> T unwrap(Class<T> iface) throws SQLException { if (iface.isAssignableFrom(getClass())) { return iface.cast(this); } else if (iface.isAssignableFrom(_stmt.getClass())) { return iface.cast(_stmt); } else { return _stmt.unwrap(iface); } } public void setPoolable(boolean poolable) throws SQLException { checkOpen(); try { _stmt.setPoolable(poolable); } catch (SQLException e) { handleException(e); } } public boolean isPoolable() throws SQLException { checkOpen(); try { return _stmt.isPoolable(); } catch (SQLException e) { handleException(e); return false; } } /* JDBC_4_ANT_KEY_END */ }