View Javadoc

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.CallableStatement;
21  import java.sql.Connection;
22  import java.sql.ResultSet;
23  import java.sql.SQLException;
24  import java.util.List;
25  
26  import org.apache.commons.pool.KeyedObjectPool;
27  
28  /**
29   * A {@link DelegatingCallableStatement} that cooperates with
30   * {@link PoolingConnection} to implement a pool of {@link CallableStatement}s.
31   * <p>
32   * The {@link #close} method returns this statement to its containing pool. (See {@link PoolingConnection}.)
33   *
34   * @see PoolingConnection
35   * @version $Revision: 1023401 $ $Date: 2010-10-16 21:54:24 -0400 (Sat, 16 Oct 2010) $
36   * @since 1.3
37   */
38  public class PoolableCallableStatement extends DelegatingCallableStatement implements CallableStatement {
39  
40      /**
41       * The {@link KeyedObjectPool} from which this CallableStatement was obtained.
42       */
43      private final KeyedObjectPool _pool;
44  
45      /**
46       * Key for this statement in the containing {@link KeyedObjectPool}.
47       */
48      private final Object _key;
49  
50      /**
51       * Constructor.
52       * 
53       * @param stmt the underlying {@link CallableStatement}
54       * @param key the key for this statement in the {@link KeyedObjectPool}
55       * @param pool the {@link KeyedObjectPool} from which this CallableStatement was obtained
56       * @param conn the {@link Connection} that created this CallableStatement
57       */
58      public PoolableCallableStatement(CallableStatement stmt, Object key, KeyedObjectPool pool, Connection conn) {
59          super((DelegatingConnection)conn, stmt);
60          _pool = pool;
61          _key = key;
62  
63          // Remove from trace now because this statement will be 
64          // added by the activate method.
65          if(_conn != null) {
66              _conn.removeTrace(this);
67          }
68      }
69  
70      /**
71       * Returns the CallableStatement to the pool.  If {{@link #isClosed()}, this is a No-op.
72       */
73      public void close() throws SQLException {
74          // calling close twice should have no effect
75          if (!isClosed()) {
76              try {
77                  _pool.returnObject(_key,this);
78              } catch(SQLException e) {
79                  throw e;
80              } catch(RuntimeException e) {
81                  throw e;
82              } catch(Exception e) {
83                  throw new SQLNestedException("Cannot close CallableStatement (return to pool failed)", e);
84              }
85          }
86      }
87  
88      /**
89       * Activates after retrieval from the pool. Adds a trace for this CallableStatement to the Connection
90       * that created it.
91       */
92      protected void activate() throws SQLException {
93          _closed = false;
94          if( _conn != null ) {
95              _conn.addTrace( this );
96          }
97          super.activate();
98      }
99  
100     /**
101      * Passivates to prepare for return to the pool.  Removes the trace associated with this CallableStatement
102      * from the Connection that created it.  Also closes any associated ResultSets.
103      */
104     protected void passivate() throws SQLException {
105         _closed = true;
106         if( _conn != null ) {
107             _conn.removeTrace(this);
108         }
109 
110         // The JDBC spec requires that a statment close any open
111         // ResultSet's when it is closed.
112         // FIXME The PreparedStatement we're wrapping should handle this for us.
113         // See DBCP-10 for what could happen when ResultSets are closed twice.
114         List resultSets = getTrace();
115         if(resultSets != null) {
116             ResultSet[] set = (ResultSet[])resultSets.toArray(new ResultSet[resultSets.size()]);
117             for(int i = 0; i < set.length; i++) {
118                 set[i].close();
119             }
120             clearTrace();
121         }
122 
123         super.passivate();
124     }
125 
126 }