KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > dbcp > datasources > CPDSConnectionFactory


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.commons.dbcp.datasources;
18
19 import java.sql.Connection JavaDoc;
20 import java.sql.ResultSet JavaDoc;
21 import java.sql.SQLException JavaDoc;
22 import java.sql.Statement JavaDoc;
23 import java.util.HashMap JavaDoc;
24 import java.util.Map JavaDoc;
25 import java.util.WeakHashMap JavaDoc;
26
27 import javax.sql.ConnectionEvent JavaDoc;
28 import javax.sql.ConnectionEventListener JavaDoc;
29 import javax.sql.ConnectionPoolDataSource JavaDoc;
30 import javax.sql.PooledConnection JavaDoc;
31
32 import org.apache.commons.dbcp.SQLNestedException;
33 import org.apache.commons.pool.ObjectPool;
34 import org.apache.commons.pool.PoolableObjectFactory;
35
36 /**
37  * A {@link PoolableObjectFactory} that creates
38  * {@link PoolableConnection}s.
39  *
40  * @author John D. McNally
41  * @version $Revision: 1.5 $ $Date: 2004/02/28 12:18:17 $
42  */

43 class CPDSConnectionFactory
44         implements PoolableObjectFactory, ConnectionEventListener JavaDoc {
45
46     private static final String JavaDoc NO_KEY_MESSAGE
47             = "close() was called on a Connection, but "
48             + "I have no record of the underlying PooledConnection.";
49
50     protected ConnectionPoolDataSource JavaDoc _cpds = null;
51     protected String JavaDoc _validationQuery = null;
52     protected ObjectPool _pool = null;
53     protected String JavaDoc _username = null;
54     protected String JavaDoc _password = null;
55     private Map JavaDoc validatingMap = new HashMap JavaDoc();
56     private WeakHashMap JavaDoc pcMap = new WeakHashMap JavaDoc();
57
58     /**
59      * Create a new <tt>PoolableConnectionFactory</tt>.
60      * @param cpds the ConnectionPoolDataSource from which to obtain
61      * PooledConnection's
62      * @param pool the {*link ObjectPool} in which to pool those
63      * {*link Connection}s
64      * @param validationQuery a query to use to {*link #validateObject validate}
65      * {*link Connection}s. Should return at least one row.
66      * May be <tt>null</tt>
67      * @param username
68      * @param password
69      */

70     public CPDSConnectionFactory(ConnectionPoolDataSource JavaDoc cpds,
71                                  ObjectPool pool,
72                                  String JavaDoc validationQuery,
73                                  String JavaDoc username,
74                                  String JavaDoc password) {
75         _cpds = cpds;
76         _pool = pool;
77         _pool.setFactory(this);
78         _validationQuery = validationQuery;
79         _username = username;
80         _password = password;
81     }
82
83     /**
84      * Sets the {*link ConnectionFactory} from which to obtain base
85      * {*link Connection}s.
86      * @param connFactory the {*link ConnectionFactory} from which to obtain
87      * base {*link Connection}s
88      */

89     public synchronized void setCPDS(ConnectionPoolDataSource JavaDoc cpds) {
90         _cpds = cpds;
91     }
92
93     /**
94      * Sets the query I use to {*link #validateObject validate}
95      * {*link Connection}s.
96      * Should return at least one row.
97      * May be <tt>null</tt>
98      * @param validationQuery a query to use to {*link #validateObject validate}
99      * {*link Connection}s.
100      */

101     public synchronized void setValidationQuery(String JavaDoc validationQuery) {
102         _validationQuery = validationQuery;
103     }
104
105     /**
106      * Sets the {*link ObjectPool} in which to pool {*link Connection}s.
107      * @param pool the {*link ObjectPool} in which to pool those
108      * {*link Connection}s
109      */

110     public synchronized void setPool(ObjectPool pool) throws SQLException JavaDoc {
111         if (null != _pool && pool != _pool) {
112             try {
113                 _pool.close();
114             } catch (RuntimeException JavaDoc e) {
115                 throw e;
116             } catch (Exception JavaDoc e) {
117                 throw new SQLNestedException("Cannot set the pool on this factory", e);
118             }
119         }
120         _pool = pool;
121     }
122
123     public ObjectPool getPool() {
124         return _pool;
125     }
126
127     public synchronized Object JavaDoc makeObject() {
128         Object JavaDoc obj;
129         try {
130             PooledConnection JavaDoc pc = null;
131             if (_username == null) {
132                 pc = _cpds.getPooledConnection();
133             } else {
134                 pc = _cpds.getPooledConnection(_username, _password);
135             }
136             // should we add this object as a listener or the pool.
137
// consider the validateObject method in decision
138
pc.addConnectionEventListener(this);
139             obj = new PooledConnectionAndInfo(pc, _username, _password);
140             pcMap.put(pc, obj);
141         } catch (SQLException JavaDoc e) {
142             throw new RuntimeException JavaDoc(e.getMessage());
143         }
144         return obj;
145     }
146
147     public void destroyObject(Object JavaDoc obj) throws Exception JavaDoc {
148         if (obj instanceof PooledConnectionAndInfo) {
149             ((PooledConnectionAndInfo) obj).getPooledConnection().close();
150         }
151     }
152
153     public boolean validateObject(Object JavaDoc obj) {
154         boolean valid = false;
155         if (obj instanceof PooledConnectionAndInfo) {
156             PooledConnection JavaDoc pconn =
157                 ((PooledConnectionAndInfo) obj).getPooledConnection();
158             String JavaDoc query = _validationQuery;
159             if (null != query) {
160                 Connection JavaDoc conn = null;
161                 Statement JavaDoc stmt = null;
162                 ResultSet JavaDoc rset = null;
163                 // logical Connection from the PooledConnection must be closed
164
// before another one can be requested and closing it will
165
// generate an event. Keep track so we know not to return
166
// the PooledConnection
167
validatingMap.put(pconn, null);
168                 try {
169                     conn = pconn.getConnection();
170                     stmt = conn.createStatement();
171                     rset = stmt.executeQuery(query);
172                     if (rset.next()) {
173                         valid = true;
174                     } else {
175                         valid = false;
176                     }
177                 } catch (Exception JavaDoc e) {
178                     valid = false;
179                 } finally {
180                     try {
181                         rset.close();
182                     } catch (Throwable JavaDoc t) {
183                         // ignore
184
}
185                     try {
186                         stmt.close();
187                     } catch (Throwable JavaDoc t) {
188                         // ignore
189
}
190                     try {
191                         conn.close();
192                     } catch (Throwable JavaDoc t) {
193                         // ignore
194
}
195                     validatingMap.remove(pconn);
196                 }
197             } else {
198                 valid = true;
199             }
200         } else {
201             valid = false;
202         }
203         return valid;
204     }
205
206     public void passivateObject(Object JavaDoc obj) {
207     }
208
209     public void activateObject(Object JavaDoc obj) {
210     }
211
212     // ***********************************************************************
213
// java.sql.ConnectionEventListener implementation
214
// ***********************************************************************
215

216     /**
217      * This will be called if the Connection returned by the getConnection
218      * method came from a PooledConnection, and the user calls the close()
219      * method of this connection object. What we need to do here is to
220      * release this PooledConnection from our pool...
221      */

222     public void connectionClosed(ConnectionEvent JavaDoc event) {
223         PooledConnection JavaDoc pc = (PooledConnection JavaDoc) event.getSource();
224         // if this event occured becase we were validating, ignore it
225
// otherwise return the connection to the pool.
226
if (!validatingMap.containsKey(pc)) {
227             Object JavaDoc info = pcMap.get(pc);
228             if (info == null) {
229                 throw new IllegalStateException JavaDoc(NO_KEY_MESSAGE);
230             }
231
232             try {
233                 _pool.returnObject(info);
234             } catch (Exception JavaDoc e) {
235                 System.err.println("CLOSING DOWN CONNECTION AS IT COULD "
236                         + "NOT BE RETURNED TO THE POOL");
237                 try {
238                     destroyObject(info);
239                 } catch (Exception JavaDoc e2) {
240                     System.err.println("EXCEPTION WHILE DESTROYING OBJECT "
241                             + info);
242                     e2.printStackTrace();
243                 }
244             }
245         }
246     }
247
248     /**
249      * If a fatal error occurs, close the underlying physical connection so as
250      * not to be returned in the future
251      */

252     public void connectionErrorOccurred(ConnectionEvent JavaDoc event) {
253         PooledConnection JavaDoc pc = (PooledConnection JavaDoc)event.getSource();
254         try {
255             if (null != event.getSQLException()) {
256                 System.err.println(
257                         "CLOSING DOWN CONNECTION DUE TO INTERNAL ERROR ("
258                         + event.getSQLException() + ")");
259             }
260             //remove this from the listener list because we are no more
261
//interested in errors since we are about to close this connection
262
pc.removeConnectionEventListener(this);
263         } catch (Exception JavaDoc ignore) {
264             // ignore
265
}
266
267         Object JavaDoc info = pcMap.get(pc);
268         if (info == null) {
269             throw new IllegalStateException JavaDoc(NO_KEY_MESSAGE);
270         }
271         try {
272             destroyObject(info);
273         } catch (Exception JavaDoc e) {
274             System.err.println("EXCEPTION WHILE DESTROYING OBJECT " + info);
275             e.printStackTrace();
276         }
277     }
278
279 }
280
Popular Tags