Coverage Report - org.apache.commons.dbcp.DelegatingStatement
 
Classes in this File Line Coverage Branch Coverage Complexity
DelegatingStatement
48%
60/124
58%
20/34
2.736
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one or more
 3  
  * contributor license agreements.  See the NOTICE file distributed with
 4  
  * this work for additional information regarding copyright ownership.
 5  
  * The ASF licenses this file to You under the Apache License, Version 2.0
 6  
  * (the "License"); you may not use this file except in compliance with
 7  
  * the License.  You may obtain a copy of the License at
 8  
  * 
 9  
  *      http://www.apache.org/licenses/LICENSE-2.0
 10  
  * 
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 
 18  
 package org.apache.commons.dbcp;
 19  
 
 20  
 import java.sql.Connection;
 21  
 import java.sql.ResultSet;
 22  
 import java.sql.SQLException;
 23  
 import java.sql.SQLWarning;
 24  
 import java.sql.Statement;
 25  
 import java.util.List;
 26  
 
 27  
 /**
 28  
  * A base delegating implementation of {@link Statement}.
 29  
  * <p>
 30  
  * All of the methods from the {@link Statement} interface
 31  
  * simply check to see that the {@link Statement} is active,
 32  
  * and call the corresponding method on the "delegate"
 33  
  * provided in my constructor.
 34  
  * <p>
 35  
  * Extends AbandonedTrace to implement Statement tracking and
 36  
  * logging of code which created the Statement. Tracking the
 37  
  * Statement ensures that the Connection which created it can
 38  
  * close any open Statement's on Connection close.
 39  
  *
 40  
  * @author Rodney Waldhoff
 41  
  * @author Glenn L. Nielsen
 42  
  * @author James House
 43  
  * @author Dirk Verbeeck
 44  
  * @version $Revision: 1023401 $ $Date: 2010-10-16 21:54:24 -0400 (Sat, 16 Oct 2010) $
 45  
  */
 46  
 public class DelegatingStatement extends AbandonedTrace implements Statement {
 47  
     /** My delegate. */
 48  50721
     protected Statement _stmt = null;
 49  
     /** The connection that created me. **/
 50  50721
     protected DelegatingConnection _conn = null;
 51  
 
 52  
     /**
 53  
      * Create a wrapper for the Statement which traces this
 54  
      * Statement to the Connection which created it and the
 55  
      * code which created it.
 56  
      *
 57  
      * @param s the {@link Statement} to delegate all calls to.
 58  
      * @param c the {@link DelegatingConnection} that created this statement.
 59  
      */
 60  
     public DelegatingStatement(DelegatingConnection c, Statement s) {
 61  50721
         super(c);
 62  50721
         _stmt = s;
 63  50721
         _conn = c;
 64  50721
     }
 65  
 
 66  
     /**
 67  
      * Returns my underlying {@link Statement}.
 68  
      * @return my underlying {@link Statement}.
 69  
      * @see #getInnermostDelegate
 70  
      */
 71  
     public Statement getDelegate() {
 72  53178
         return _stmt;
 73  
     }
 74  
 
 75  
     /**
 76  
      * This method considers two objects to be equal 
 77  
      * if the underlying jdbc objects are equal.
 78  
      */
 79  
     public boolean equals(Object obj) {
 80  20172
         Statement delegate = getInnermostDelegate();
 81  20172
         if (delegate == null) {
 82  0
             return false;
 83  
         }
 84  20172
         if (obj instanceof DelegatingStatement) {
 85  20170
             DelegatingStatement s = (DelegatingStatement) obj;
 86  20170
             return delegate.equals(s.getInnermostDelegate());
 87  
         }
 88  
         else {
 89  2
             return delegate.equals(obj);
 90  
         }
 91  
     }
 92  
 
 93  
     public int hashCode() {
 94  64
         Object obj = getInnermostDelegate();
 95  64
         if (obj == null) {
 96  4
             return 0;
 97  
         }
 98  60
         return obj.hashCode();
 99  
     }
 100  
     
 101  
     /**
 102  
      * If my underlying {@link Statement} is not a
 103  
      * <tt>DelegatingStatement</tt>, returns it,
 104  
      * otherwise recursively invokes this method on
 105  
      * my delegate.
 106  
      * <p>
 107  
      * Hence this method will return the first
 108  
      * delegate that is not a <tt>DelegatingStatement</tt>
 109  
      * or <tt>null</tt> when no non-<tt>DelegatingStatement</tt>
 110  
      * delegate can be found by transversing this chain.
 111  
      * <p>
 112  
      * This method is useful when you may have nested
 113  
      * <tt>DelegatingStatement</tt>s, and you want to make
 114  
      * sure to obtain a "genuine" {@link Statement}.
 115  
      * @see #getDelegate
 116  
      */
 117  
     public Statement getInnermostDelegate() {
 118  108933
         Statement s = _stmt;
 119  162105
         while(s != null && s instanceof DelegatingStatement) {
 120  53172
             s = ((DelegatingStatement)s).getDelegate();
 121  53172
             if(this == s) {
 122  0
                 return null;
 123  
             }
 124  
         }
 125  108933
         return s;
 126  
     }
 127  
 
 128  
     /** Sets my delegate. */
 129  
     public void setDelegate(Statement s) {
 130  0
         _stmt = s;
 131  0
     }
 132  
 
 133  50721
     protected boolean _closed = false;
 134  
 
 135  
     protected void checkOpen() throws SQLException {
 136  60773
         if(isClosed()) {
 137  590
             throw new SQLException
 138  
                 (this.getClass().getName() + " with address: \"" + 
 139  
                 this.toString() + "\" is closed.");
 140  
         }
 141  60183
     }
 142  
 
 143  
     /**
 144  
      * Close this DelegatingStatement, and close
 145  
      * any ResultSets that were not explicitly closed.
 146  
      */
 147  
     public void close() throws SQLException {
 148  
         try {
 149  
             try {
 150  50451
                 if (_conn != null) {
 151  49947
                     _conn.removeTrace(this);
 152  49947
                     _conn = null;
 153  
                 }
 154  
         
 155  
                 // The JDBC spec requires that a statment close any open
 156  
                 // ResultSet's when it is closed.
 157  
                 // FIXME The PreparedStatement we're wrapping should handle this for us.
 158  
                 // See bug 17301 for what could happen when ResultSets are closed twice.
 159  50451
                 List resultSets = getTrace();
 160  50451
                 if( resultSets != null) {
 161  50451
                     ResultSet[] set = (ResultSet[]) resultSets.toArray(new ResultSet[resultSets.size()]);
 162  51295
                     for (int i = 0; i < set.length; i++) {
 163  844
                         set[i].close();
 164  
                     }
 165  50451
                     clearTrace();
 166  
                 }
 167  
         
 168  50451
                 _stmt.close();
 169  
             }
 170  0
             catch (SQLException e) {
 171  0
                 handleException(e);
 172  50451
             }
 173  
         }
 174  
         finally {
 175  50451
             _closed = true;
 176  50451
         }
 177  50451
     }
 178  
 
 179  
     protected void handleException(SQLException e) throws SQLException {
 180  932
         if (_conn != null) {
 181  932
             _conn.handleException(e);
 182  
         }
 183  
         else {
 184  0
             throw e;
 185  
         }
 186  0
     }
 187  
 
 188  
     protected void activate() throws SQLException {
 189  3896
         if(_stmt instanceof DelegatingStatement) {
 190  0
             ((DelegatingStatement)_stmt).activate();
 191  
         }
 192  3896
     }
 193  
 
 194  
     protected void passivate() throws SQLException {
 195  3882
         if(_stmt instanceof DelegatingStatement) {
 196  0
             ((DelegatingStatement)_stmt).passivate();
 197  
         }
 198  3882
     }
 199  
 
 200  
     public Connection getConnection() throws SQLException {
 201  432
         checkOpen();
 202  432
         return _conn; // return the delegating connection that created this
 203  
     }
 204  
 
 205  
     public ResultSet executeQuery(String sql) throws SQLException {
 206  20314
         checkOpen();
 207  
         try {
 208  20314
             return DelegatingResultSet.wrapResultSet(this,_stmt.executeQuery(sql));
 209  
         }
 210  20
         catch (SQLException e) {
 211  20
             handleException(e);
 212  0
             throw new AssertionError();
 213  
         }
 214  
     }
 215  
 
 216  
     public ResultSet getResultSet() throws SQLException {
 217  550
         checkOpen();
 218  
         try {
 219  550
             return DelegatingResultSet.wrapResultSet(this,_stmt.getResultSet());
 220  
         }
 221  0
         catch (SQLException e) {
 222  0
             handleException(e);
 223  0
             throw new AssertionError();
 224  
         }
 225  
     }
 226  
 
 227  
     public int executeUpdate(String sql) throws SQLException
 228  0
     { checkOpen(); try { return _stmt.executeUpdate(sql); } catch (SQLException e) { handleException(e); return 0; } }
 229  
 
 230  
     public int getMaxFieldSize() throws SQLException
 231  0
     { checkOpen(); try { return _stmt.getMaxFieldSize(); } catch (SQLException e) { handleException(e); return 0; } }
 232  
 
 233  
     public void setMaxFieldSize(int max) throws SQLException
 234  0
     { checkOpen(); try { _stmt.setMaxFieldSize(max); } catch (SQLException e) { handleException(e); } }
 235  
 
 236  
     public int getMaxRows() throws SQLException
 237  0
     { checkOpen(); try { return _stmt.getMaxRows(); } catch (SQLException e) { handleException(e); return 0; } }
 238  
 
 239  
     public void setMaxRows(int max) throws SQLException
 240  0
     { checkOpen(); try { _stmt.setMaxRows(max); } catch (SQLException e) { handleException(e); } }
 241  
 
 242  
     public void setEscapeProcessing(boolean enable) throws SQLException
 243  0
     { checkOpen(); try { _stmt.setEscapeProcessing(enable); } catch (SQLException e) { handleException(e); } }
 244  
 
 245  
     public int getQueryTimeout() throws SQLException
 246  0
     { checkOpen(); try { return _stmt.getQueryTimeout(); } catch (SQLException e) { handleException(e); return 0; } }
 247  
 
 248  
     public void setQueryTimeout(int seconds) throws SQLException
 249  60
     { checkOpen(); try { _stmt.setQueryTimeout(seconds); } catch (SQLException e) { handleException(e); } }
 250  
 
 251  
     public void cancel() throws SQLException
 252  0
     { checkOpen(); try { _stmt.cancel(); } catch (SQLException e) { handleException(e); } }
 253  
 
 254  
     public SQLWarning getWarnings() throws SQLException
 255  1560
     { checkOpen(); try { return _stmt.getWarnings(); } catch (SQLException e) { handleException(e); throw new AssertionError(); } }
 256  
 
 257  
     public void clearWarnings() throws SQLException
 258  0
     { checkOpen(); try { _stmt.clearWarnings(); } catch (SQLException e) { handleException(e); } }
 259  
 
 260  
     public void setCursorName(String name) throws SQLException
 261  0
     { checkOpen(); try { _stmt.setCursorName(name); } catch (SQLException e) { handleException(e); } }
 262  
 
 263  
     public boolean execute(String sql) throws SQLException
 264  0
     { checkOpen(); try { return _stmt.execute(sql); } catch (SQLException e) { handleException(e); return false; } }
 265  
 
 266  
     public int getUpdateCount() throws SQLException
 267  0
     { checkOpen(); try { return _stmt.getUpdateCount(); } catch (SQLException e) { handleException(e); return 0; } }
 268  
 
 269  
     public boolean getMoreResults() throws SQLException
 270  0
     { checkOpen(); try { return _stmt.getMoreResults(); } catch (SQLException e) { handleException(e); return false; } }
 271  
 
 272  
     public void setFetchDirection(int direction) throws SQLException
 273  0
     { checkOpen(); try { _stmt.setFetchDirection(direction); } catch (SQLException e) { handleException(e); } }
 274  
 
 275  
     public int getFetchDirection() throws SQLException
 276  0
     { checkOpen(); try { return _stmt.getFetchDirection(); } catch (SQLException e) { handleException(e); return 0; } }
 277  
 
 278  
     public void setFetchSize(int rows) throws SQLException
 279  0
     { checkOpen(); try { _stmt.setFetchSize(rows); } catch (SQLException e) { handleException(e); } }
 280  
 
 281  
     public int getFetchSize() throws SQLException
 282  0
     { checkOpen(); try { return _stmt.getFetchSize(); } catch (SQLException e) { handleException(e); return 0; } }
 283  
 
 284  
     public int getResultSetConcurrency() throws SQLException
 285  0
     { checkOpen(); try { return _stmt.getResultSetConcurrency(); } catch (SQLException e) { handleException(e); return 0; } }
 286  
 
 287  
     public int getResultSetType() throws SQLException
 288  0
     { checkOpen(); try { return _stmt.getResultSetType(); } catch (SQLException e) { handleException(e); return 0; } }
 289  
 
 290  
     public void addBatch(String sql) throws SQLException
 291  0
     { checkOpen(); try { _stmt.addBatch(sql); } catch (SQLException e) { handleException(e); } }
 292  
 
 293  
     public void clearBatch() throws SQLException
 294  0
     { checkOpen(); try { _stmt.clearBatch(); } catch (SQLException e) { handleException(e); } }
 295  
 
 296  
     public int[] executeBatch() throws SQLException
 297  0
     { checkOpen(); try { return _stmt.executeBatch(); } catch (SQLException e) { handleException(e); throw new AssertionError(); } }
 298  
 
 299  
     /**
 300  
      * Returns a String representation of this object.
 301  
      *
 302  
      * @return String
 303  
      * @since 1.2.2
 304  
      */
 305  
     public String toString() {
 306  344
     return _stmt.toString();
 307  
     }
 308  
 
 309  
     public boolean getMoreResults(int current) throws SQLException
 310  0
     { checkOpen(); try { return _stmt.getMoreResults(current); } catch (SQLException e) { handleException(e); return false; } }
 311  
 
 312  
     public ResultSet getGeneratedKeys() throws SQLException {
 313  504
         checkOpen();
 314  
         try {
 315  504
             return DelegatingResultSet.wrapResultSet(this, _stmt.getGeneratedKeys());
 316  0
         } catch (SQLException e) {
 317  0
             handleException(e);
 318  0
             throw new AssertionError();
 319  
         }
 320  
     }
 321  
 
 322  
     public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException
 323  0
     { checkOpen(); try { return _stmt.executeUpdate(sql, autoGeneratedKeys); } catch (SQLException e) { handleException(e); return 0; } }
 324  
 
 325  
     public int executeUpdate(String sql, int columnIndexes[]) throws SQLException
 326  0
     { checkOpen(); try { return _stmt.executeUpdate(sql, columnIndexes); } catch (SQLException e) { handleException(e); return 0; } }
 327  
 
 328  
     public int executeUpdate(String sql, String columnNames[]) throws SQLException
 329  0
     { checkOpen(); try { return _stmt.executeUpdate(sql, columnNames); } catch (SQLException e) { handleException(e); return 0; } }
 330  
 
 331  
     public boolean execute(String sql, int autoGeneratedKeys) throws SQLException
 332  0
     { checkOpen(); try { return _stmt.execute(sql, autoGeneratedKeys); } catch (SQLException e) { handleException(e); return false; } }
 333  
 
 334  
     public boolean execute(String sql, int columnIndexes[]) throws SQLException
 335  0
     { checkOpen(); try { return _stmt.execute(sql, columnIndexes); } catch (SQLException e) { handleException(e); return false; } }
 336  
 
 337  
     public boolean execute(String sql, String columnNames[]) throws SQLException
 338  0
     { checkOpen(); try { return _stmt.execute(sql, columnNames); } catch (SQLException e) { handleException(e); return false; } }
 339  
 
 340  
     public int getResultSetHoldability() throws SQLException
 341  0
     { checkOpen(); try { return _stmt.getResultSetHoldability(); } catch (SQLException e) { handleException(e); return 0; } }
 342  
 
 343  
     /*
 344  
      * Note was protected prior to JDBC 4
 345  
      * TODO Consider adding build flags to make this protected unless we are
 346  
      *      using JDBC 4.
 347  
      */
 348  
     public boolean isClosed() throws SQLException {
 349  64703
         return _closed;
 350  
     }
 351  
 
 352  
 /* JDBC_4_ANT_KEY_BEGIN */
 353  
 
 354  
     public boolean isWrapperFor(Class<?> iface) throws SQLException {
 355  0
         return iface.isAssignableFrom(getClass()) || _stmt.isWrapperFor(iface);
 356  
     }
 357  
 
 358  
     public <T> T unwrap(Class<T> iface) throws SQLException {
 359  0
         if (iface.isAssignableFrom(getClass())) {
 360  0
             return iface.cast(this);
 361  0
         } else if (iface.isAssignableFrom(_stmt.getClass())) {
 362  0
             return iface.cast(_stmt);
 363  
         } else {
 364  0
             return _stmt.unwrap(iface);
 365  
         }
 366  
     }
 367  
 
 368  
     public void setPoolable(boolean poolable) throws SQLException {
 369  0
         checkOpen();
 370  
         try {
 371  0
             _stmt.setPoolable(poolable);
 372  
         }
 373  0
         catch (SQLException e) {
 374  0
             handleException(e);
 375  0
         }
 376  0
     }
 377  
 
 378  
     public boolean isPoolable() throws SQLException {
 379  0
         checkOpen();
 380  
         try {
 381  0
             return _stmt.isPoolable();
 382  
         }
 383  0
         catch (SQLException e) {
 384  0
             handleException(e);
 385  0
             return false;
 386  
         }
 387  
     }
 388  
 /* JDBC_4_ANT_KEY_END */
 389  
 }