KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectstyle > cayenne > conn > PooledConnectionImpl


1 /* ====================================================================
2  *
3  * The ObjectStyle Group Software License, version 1.1
4  * ObjectStyle Group - http://objectstyle.org/
5  *
6  * Copyright (c) 2002-2005, Andrei (Andrus) Adamchik and individual authors
7  * of the software. All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above copyright
17  * notice, this list of conditions and the following disclaimer in
18  * the documentation and/or other materials provided with the
19  * distribution.
20  *
21  * 3. The end-user documentation included with the redistribution, if any,
22  * must include the following acknowlegement:
23  * "This product includes software developed by independent contributors
24  * and hosted on ObjectStyle Group web site (http://objectstyle.org/)."
25  * Alternately, this acknowlegement may appear in the software itself,
26  * if and wherever such third-party acknowlegements normally appear.
27  *
28  * 4. The names "ObjectStyle Group" and "Cayenne" must not be used to endorse
29  * or promote products derived from this software without prior written
30  * permission. For written permission, email
31  * "andrus at objectstyle dot org".
32  *
33  * 5. Products derived from this software may not be called "ObjectStyle"
34  * or "Cayenne", nor may "ObjectStyle" or "Cayenne" appear in their
35  * names without prior written permission.
36  *
37  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40  * DISCLAIMED. IN NO EVENT SHALL THE OBJECTSTYLE GROUP OR
41  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48  * SUCH DAMAGE.
49  * ====================================================================
50  *
51  * This software consists of voluntary contributions made by many
52  * individuals and hosted on ObjectStyle Group web site. For more
53  * information on the ObjectStyle Group, please see
54  * <http://objectstyle.org/>.
55  */

56
57 package org.objectstyle.cayenne.conn;
58
59 import java.sql.Connection JavaDoc;
60 import java.sql.SQLException JavaDoc;
61 import java.util.ArrayList JavaDoc;
62 import java.util.Collections JavaDoc;
63 import java.util.Iterator JavaDoc;
64 import java.util.List JavaDoc;
65
66 import javax.sql.ConnectionEvent JavaDoc;
67 import javax.sql.ConnectionEventListener JavaDoc;
68 import javax.sql.DataSource JavaDoc;
69 import javax.sql.PooledConnection JavaDoc;
70
71 import org.apache.log4j.Logger;
72
73 /**
74  * PooledConnectionImpl is an implementation of a pooling wrapper
75  * for the database connection as per JDBC3 spec. Most of the modern
76  * JDBC drivers should have its own implementation that may be
77  * used instead of this class.
78  *
79  * @author Andrei Adamchik
80  */

81 public class PooledConnectionImpl implements PooledConnection JavaDoc {
82     private static Logger logObj = Logger.getLogger(PooledConnectionImpl.class);
83
84     private Connection JavaDoc connectionObj;
85     private List JavaDoc connectionEventListeners;
86     private boolean hadErrors;
87     private DataSource JavaDoc connectionSource;
88     private String JavaDoc userName;
89     private String JavaDoc password;
90
91     protected PooledConnectionImpl() {
92         // TODO: maybe remove synchronization and use
93
// FastArrayList from commons-collections? After
94
// all the only listener is usually pool manager.
95
this.connectionEventListeners =
96             Collections.synchronizedList(new ArrayList JavaDoc(10));
97     }
98
99     /** Creates new PooledConnection */
100     public PooledConnectionImpl(
101         DataSource JavaDoc connectionSource,
102         String JavaDoc userName,
103         String JavaDoc password)
104         throws SQLException JavaDoc {
105
106         this();
107
108         this.connectionSource = connectionSource;
109         this.userName = userName;
110         this.password = password;
111
112     }
113
114     public void reconnect() throws SQLException JavaDoc {
115         if (connectionObj != null) {
116             try {
117                 connectionObj.close();
118             } catch (SQLException JavaDoc ex) {
119                 // ignore exception, since connection is expected
120
// to be in a bad state
121
} finally {
122                 connectionObj = null;
123             }
124         }
125
126         connectionObj =
127             (userName != null)
128                 ? connectionSource.getConnection(userName, password)
129                 : connectionSource.getConnection();
130     }
131
132     public void addConnectionEventListener(ConnectionEventListener JavaDoc listener) {
133         synchronized (connectionEventListeners) {
134             if (!connectionEventListeners.contains(listener))
135                 connectionEventListeners.add(listener);
136         }
137     }
138
139     public void removeConnectionEventListener(ConnectionEventListener JavaDoc listener) {
140         synchronized (connectionEventListeners) {
141             connectionEventListeners.remove(listener);
142         }
143     }
144
145     public void close() throws SQLException JavaDoc {
146
147         synchronized (connectionEventListeners) {
148             // remove all listeners
149
connectionEventListeners.clear();
150         }
151
152         if (connectionObj != null) {
153             try {
154                 connectionObj.close();
155             } finally {
156                 connectionObj = null;
157             }
158         }
159     }
160
161     public Connection JavaDoc getConnection() throws SQLException JavaDoc {
162         if (connectionObj == null) {
163             reconnect();
164         }
165
166         // set autocommit to false to return connection
167
// always in consistent state
168
if (!connectionObj.getAutoCommit()) {
169
170             try {
171                 connectionObj.setAutoCommit(true);
172             } catch (SQLException JavaDoc sqlEx) {
173                 // try applying Sybase patch
174
ConnectionWrapper.sybaseAutoCommitPatch(
175                     connectionObj,
176                     sqlEx,
177                     true);
178             }
179         }
180
181         connectionObj.clearWarnings();
182         return new ConnectionWrapper(connectionObj, this);
183     }
184
185     protected void returnConnectionToThePool() throws SQLException JavaDoc {
186         // do not return to pool bad connections
187
if (hadErrors)
188             close();
189         else
190             // notify the listeners that connection is no longer used by application...
191
this.connectionClosedNotification();
192     }
193
194     /** This method creates and sents an event to listeners when an error occurs in the
195      * underlying connection. Listeners can have special logic to
196      * analyze the error and do things like closing this PooledConnection
197      * (if the error is fatal), etc...
198      */

199     public void connectionErrorNotification(SQLException JavaDoc exception) {
200         // hint for later to avoid returning bad connections to the pool
201
hadErrors = true;
202
203         if (logObj.isDebugEnabled()) {
204             logObj.debug(
205                 "Child connection error, retiring pooled connection.",
206                 exception);
207         }
208
209         synchronized (connectionEventListeners) {
210             if (connectionEventListeners.size() == 0)
211                 return;
212
213             ConnectionEvent JavaDoc closedEvent = new ConnectionEvent JavaDoc(this, exception);
214             Iterator JavaDoc listeners = connectionEventListeners.iterator();
215             while (listeners.hasNext()) {
216                 ConnectionEventListener JavaDoc nextListener =
217                     (ConnectionEventListener JavaDoc) listeners.next();
218                 nextListener.connectionErrorOccurred(closedEvent);
219             }
220         }
221     }
222
223     /** Creates and sends an event to listeners when a user closes
224      * java.sql.Connection object belonging to this PooledConnection.
225      */

226     protected void connectionClosedNotification() {
227         synchronized (connectionEventListeners) {
228             if (connectionEventListeners.size() == 0)
229                 return;
230
231             ConnectionEvent JavaDoc closedEvent = new ConnectionEvent JavaDoc(this);
232             Iterator JavaDoc listeners = connectionEventListeners.iterator();
233
234             while (listeners.hasNext()) {
235                 ConnectionEventListener JavaDoc nextListener =
236                     (ConnectionEventListener JavaDoc) listeners.next();
237                 nextListener.connectionClosed(closedEvent);
238             }
239         }
240     }
241 }
Popular Tags