Source code: com/mysql/jdbc/jdbc2/optional/MysqlPooledConnection.java
1 /*
2 Copyright (C) 2002-2004 MySQL AB
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of version 2 of the GNU General Public License as
6 published by the Free Software Foundation.
7
8
9 There are special exceptions to the terms and conditions of the GPL
10 as it is applied to this software. View the full text of the
11 exception exception in file EXCEPTIONS-CONNECTOR-J in the directory of this
12 software distribution.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
23 */
24 package com.mysql.jdbc.jdbc2.optional;
25
26 import java.sql.Connection;
27 import java.sql.SQLException;
28 import java.util.Enumeration;
29 import java.util.Hashtable;
30
31 import javax.sql.ConnectionEvent;
32 import javax.sql.ConnectionEventListener;
33 import javax.sql.PooledConnection;
34
35
36 /**
37 * This class is used to wrap and return a physical connection within a logical handle.
38 * It also registers and notifies ConnectionEventListeners of any ConnectionEvents
39 *
40 * @see javax.sql.PooledConnection
41 * @see org.gjt.mm.mysql.jdbc2.optional.LogicalHandle
42 * @author Todd Wolff <todd.wolff_at_prodigy.net>
43 */
44 public class MysqlPooledConnection
45 implements PooledConnection {
46
47 /**
48 * The flag for an exception being thrown.
49 */
50 public static final int CONNECTION_ERROR_EVENT = 1;
51
52 /**
53 * The flag for a connection being closed.
54 */
55 public static final int CONNECTION_CLOSED_EVENT = 2;
56
57 //~ Instance/static variables .............................................
58
59 private Hashtable eventListeners;
60 private Connection logicalHandle;
61 private Connection physicalConn;
62
63
64 //~ Constructors ..........................................................
65
66 /**
67 * Construct a new MysqlPooledConnection and set instance variables
68 *
69 * @param connection physical connection to db
70 */
71 public MysqlPooledConnection(Connection connection) {
72 logicalHandle = null;
73 physicalConn = connection;
74 eventListeners = new Hashtable(10);
75 }
76
77 //~ Methods ...............................................................
78
79 /**
80 * Adds ConnectionEventListeners to a hash table to be used for notification of
81 * ConnectionEvents
82 *
83 * @param connectioneventlistener listener to be notified with ConnectionEvents
84 */
85 public synchronized void addConnectionEventListener(ConnectionEventListener connectioneventlistener) {
86
87 if (eventListeners != null) {
88 eventListeners.put(connectioneventlistener,
89 connectioneventlistener);
90 }
91 }
92
93 /**
94 * Removes ConnectionEventListeners from hash table used for notification of
95 * ConnectionEvents
96 *
97 * @param connectioneventlistener listener to be removed
98 */
99 public synchronized void removeConnectionEventListener(ConnectionEventListener connectioneventlistener) {
100
101 if (eventListeners != null) {
102 eventListeners.remove(connectioneventlistener);
103 }
104 }
105
106 /**
107 * Invoked by the container. Return a logicalHandle object that wraps a physical
108 * connection.
109 *
110 * @see java.sql.DataSource#getConnection()
111 */
112 public synchronized Connection getConnection()
113 throws SQLException {
114
115 if (physicalConn == null) {
116
117 SQLException sqlException = new SQLException(
118 "Physical Connection doesn't exist");
119 callListener(CONNECTION_ERROR_EVENT, sqlException);
120
121 return null;
122 }
123
124 try {
125
126 if (logicalHandle != null) {
127 ((ConnectionWrapper)logicalHandle).close(false);
128 }
129
130 ((com.mysql.jdbc.Connection)this.physicalConn).resetServerState();
131
132 logicalHandle = new ConnectionWrapper(this, physicalConn);
133 } catch (SQLException sqlException) {
134 callListener(CONNECTION_ERROR_EVENT, sqlException);
135
136 return null;
137 }
138
139 return logicalHandle;
140 }
141
142 /**
143 * Invoked by the container (not the client), and should close the physical connection.
144 * This will be called if the pool is destroyed or the connectionEventListener receives
145 * a connectionErrorOccurred event.
146 *
147 * @see java.sql.DataSource#close()
148 */
149 public synchronized void close()
150 throws SQLException {
151 if (physicalConn != null) {
152 physicalConn.close();
153 }
154
155 physicalConn = null;
156 }
157
158 /**
159 * Notifies all registered ConnectionEventListeners of ConnectionEvents. Instantiates
160 * a new ConnectionEvent which wraps sqlException and invokes either connectionClose
161 * or connectionErrorOccurred on listener as appropriate.
162 *
163 * @param eventType value indicating whether connectionClosed or connectionErrorOccurred called
164 * @param sqlException the exception being thrown
165 */
166 protected synchronized void callListener(int eventType, SQLException sqlException) {
167
168 if (eventListeners == null) {
169
170 return;
171 }
172
173 Enumeration enumeration = eventListeners.keys();
174 ConnectionEvent connectionevent = new ConnectionEvent(this,
175 sqlException);
176
177 while (enumeration.hasMoreElements()) {
178
179 ConnectionEventListener connectioneventlistener =
180 (ConnectionEventListener) enumeration.nextElement();
181 ConnectionEventListener connectioneventlistener1 =
182 (ConnectionEventListener) eventListeners.get(
183 connectioneventlistener);
184
185 if (eventType == CONNECTION_CLOSED_EVENT) {
186 connectioneventlistener1.connectionClosed(connectionevent);
187 } else if (eventType == CONNECTION_ERROR_EVENT) {
188 connectioneventlistener1.connectionErrorOccurred(
189 connectionevent);
190 }
191 }
192 }
193 }