001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.commons.dbcp;
019:
020: import java.sql.Connection;
021: import java.sql.PreparedStatement;
022: import java.sql.ResultSet;
023: import java.sql.SQLException;
024: import java.util.List;
025:
026: import org.apache.commons.pool.KeyedObjectPool;
027:
028: /**
029: * A {@link DelegatingPreparedStatement} that cooperates with
030: * {@link PoolingConnection} to implement a pool of {@link PreparedStatement}s.
031: * <p>
032: * My {@link #close} method returns me to my containing pool. (See {@link PoolingConnection}.)
033: *
034: * @see PoolingConnection
035: * @author Rodney Waldhoff
036: * @author Glenn L. Nielsen
037: * @author James House
038: * @author Dirk Verbeeck
039: * @version $Revision: 479137 $ $Date: 2006-11-25 08:51:48 -0700 (Sat, 25 Nov 2006) $
040: */
041: public class PoolablePreparedStatement extends
042: DelegatingPreparedStatement implements PreparedStatement {
043: /**
044: * The {@link KeyedObjectPool} from which I was obtained.
045: */
046: protected KeyedObjectPool _pool = null;
047:
048: /**
049: * My "key" as used by {@link KeyedObjectPool}.
050: */
051: protected Object _key = null;
052:
053: /**
054: * Constructor
055: * @param stmt my underlying {@link PreparedStatement}
056: * @param key my key" as used by {@link KeyedObjectPool}
057: * @param pool the {@link KeyedObjectPool} from which I was obtained.
058: * @param conn the {@link Connection} from which I was created
059: */
060: public PoolablePreparedStatement(PreparedStatement stmt,
061: Object key, KeyedObjectPool pool, Connection conn) {
062: super ((DelegatingConnection) conn, stmt);
063: _pool = pool;
064: _key = key;
065:
066: // Remove from trace now because this statement will be
067: // added by the activate method.
068: if (_conn != null) {
069: _conn.removeTrace(this );
070: }
071: }
072:
073: /**
074: * Return me to my pool.
075: */
076: public void close() throws SQLException {
077: if (isClosed()) {
078: throw new SQLException("Already closed");
079: } else {
080: try {
081: _pool.returnObject(_key, this );
082: } catch (SQLException e) {
083: throw e;
084: } catch (RuntimeException e) {
085: throw e;
086: } catch (Exception e) {
087: throw new SQLNestedException(
088: "Cannot close preparedstatement (return to pool failed)",
089: e);
090: }
091: }
092: }
093:
094: protected void activate() throws SQLException {
095: _closed = false;
096: if (_conn != null) {
097: _conn.addTrace(this );
098: }
099: super .activate();
100: }
101:
102: protected void passivate() throws SQLException {
103: _closed = true;
104: if (_conn != null) {
105: _conn.removeTrace(this );
106: }
107:
108: // The JDBC spec requires that a statment close any open
109: // ResultSet's when it is closed.
110: // FIXME The PreparedStatement we're wrapping should handle this for us.
111: // See bug 17301 for what could happen when ResultSets are closed twice.
112: List resultSets = getTrace();
113: if (resultSets != null) {
114: ResultSet[] set = (ResultSet[]) resultSets
115: .toArray(new ResultSet[resultSets.size()]);
116: for (int i = 0; i < set.length; i++) {
117: set[i].close();
118: }
119: clearTrace();
120: }
121:
122: super.passivate();
123: }
124:
125: }
|