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