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.SQLException; 022 import org.apache.commons.pool.ObjectPool; 023 024 /** 025 * A delegating connection that, rather than closing the underlying 026 * connection, returns itself to an {@link ObjectPool} when 027 * closed. 028 * 029 * @author Rodney Waldhoff 030 * @author Glenn L. Nielsen 031 * @author James House 032 * @version $Revision: 892307 $ $Date: 2013-12-31 23:27:28 +0000 (Tue, 31 Dec 2013) $ 033 */ 034 public class PoolableConnection extends DelegatingConnection { 035 /** The pool to which I should return. */ 036 // TODO: Correct use of the pool requires that this connection is only every returned to the pool once. 037 protected ObjectPool _pool = null; 038 039 /** 040 * 041 * @param conn my underlying connection 042 * @param pool the pool to which I should return when closed 043 */ 044 public PoolableConnection(Connection conn, ObjectPool pool) { 045 super(conn); 046 _pool = pool; 047 } 048 049 /** 050 * 051 * @param conn my underlying connection 052 * @param pool the pool to which I should return when closed 053 * @param config the abandoned configuration settings 054 */ 055 public PoolableConnection(Connection conn, ObjectPool pool, AbandonedConfig config) { 056 super(conn, config); 057 _pool = pool; 058 } 059 060 061 /** 062 * Returns me to my pool. 063 */ 064 public synchronized void close() throws SQLException { 065 if (_closed) { 066 // already closed 067 return; 068 } 069 070 boolean isUnderlyingConectionClosed; 071 try { 072 isUnderlyingConectionClosed = _conn.isClosed(); 073 } catch (SQLException e) { 074 try { 075 _pool.invalidateObject(this); // XXX should be guarded to happen at most once 076 } catch(IllegalStateException ise) { 077 // pool is closed, so close the connection 078 passivate(); 079 getInnermostDelegate().close(); 080 } catch (Exception ie) { 081 // DO NOTHING the original exception will be rethrown 082 } 083 throw (SQLException) new SQLException("Cannot close connection (isClosed check failed)").initCause(e); 084 } 085 086 if (!isUnderlyingConectionClosed) { 087 // Normal close: underlying connection is still open, so we 088 // simply need to return this proxy to the pool 089 try { 090 _pool.returnObject(this); // XXX should be guarded to happen at most once 091 } catch(IllegalStateException e) { 092 // pool is closed, so close the connection 093 passivate(); 094 getInnermostDelegate().close(); 095 } catch(SQLException e) { 096 throw e; 097 } catch(RuntimeException e) { 098 throw e; 099 } catch(Exception e) { 100 throw (SQLException) new SQLException("Cannot close connection (return to pool failed)").initCause(e); 101 } 102 } else { 103 // Abnormal close: underlying connection closed unexpectedly, so we 104 // must destroy this proxy 105 try { 106 _pool.invalidateObject(this); // XXX should be guarded to happen at most once 107 } catch(IllegalStateException e) { 108 // pool is closed, so close the connection 109 passivate(); 110 getInnermostDelegate().close(); 111 } catch (Exception ie) { 112 // DO NOTHING, "Already closed" exception thrown below 113 } 114 throw new SQLException("Already closed."); 115 } 116 } 117 118 /** 119 * Actually close my underlying {@link Connection}. 120 */ 121 public void reallyClose() throws SQLException { 122 super.close(); 123 } 124 } 125