001: /*
002: Copyright (C) 2002-2007 MySQL AB
003:
004: This program is free software; you can redistribute it and/or modify
005: it under the terms of version 2 of the GNU General Public License as
006: published by the Free Software Foundation.
007:
008: There are special exceptions to the terms and conditions of the GPL
009: as it is applied to this software. View the full text of the
010: exception in file EXCEPTIONS-CONNECTOR-J in the directory of this
011: software distribution.
012:
013: This program is distributed in the hope that it will be useful,
014: but WITHOUT ANY WARRANTY; without even the implied warranty of
015: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016: GNU General Public License for more details.
017:
018: You should have received a copy of the GNU General Public License
019: along with this program; if not, write to the Free Software
020: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
021:
022: */
023:
024: package com.mysql.jdbc.jdbc2.optional;
025:
026: import java.sql.Connection;
027: import java.sql.SQLException;
028:
029: import java.util.Enumeration;
030: import java.util.Hashtable;
031:
032: import javax.sql.ConnectionEvent;
033: import javax.sql.ConnectionEventListener;
034: import javax.sql.PooledConnection;
035:
036: import com.mysql.jdbc.ConnectionImpl;
037: import com.mysql.jdbc.Constants;
038: import com.mysql.jdbc.SQLError;
039: import com.mysql.jdbc.exceptions.NotYetImplementedException;
040:
041: /**
042: * This class is used to wrap and return a physical connection within a logical
043: * handle. It also registers and notifies ConnectionEventListeners of any
044: * ConnectionEvents
045: *
046: * @see javax.sql.PooledConnection
047: * @see org.gjt.mm.mysql.jdbc2.optional.LogicalHandle
048: * @author Todd Wolff <todd.wolff_at_prodigy.net>
049: */
050: public class MysqlPooledConnection implements PooledConnection {
051:
052: /**
053: * The flag for an exception being thrown.
054: */
055: public static final int CONNECTION_ERROR_EVENT = 1;
056:
057: /**
058: * The flag for a connection being closed.
059: */
060: public static final int CONNECTION_CLOSED_EVENT = 2;
061:
062: // ~ Instance/static variables .............................................
063:
064: private Hashtable eventListeners;
065:
066: private Connection logicalHandle;
067:
068: private com.mysql.jdbc.Connection physicalConn;
069:
070: // ~ Constructors ..........................................................
071:
072: /**
073: * Construct a new MysqlPooledConnection and set instance variables
074: *
075: * @param connection
076: * physical connection to db
077: */
078: public MysqlPooledConnection(com.mysql.jdbc.Connection connection) {
079: this .logicalHandle = null;
080: this .physicalConn = connection;
081: this .eventListeners = new Hashtable(10);
082: }
083:
084: // ~ Methods ...............................................................
085:
086: /**
087: * Adds ConnectionEventListeners to a hash table to be used for notification
088: * of ConnectionEvents
089: *
090: * @param connectioneventlistener
091: * listener to be notified with ConnectionEvents
092: */
093: public synchronized void addConnectionEventListener(
094: ConnectionEventListener connectioneventlistener) {
095:
096: if (this .eventListeners != null) {
097: this .eventListeners.put(connectioneventlistener,
098: connectioneventlistener);
099: }
100: }
101:
102: /**
103: * Removes ConnectionEventListeners from hash table used for notification of
104: * ConnectionEvents
105: *
106: * @param connectioneventlistener
107: * listener to be removed
108: */
109: public synchronized void removeConnectionEventListener(
110: ConnectionEventListener connectioneventlistener) {
111:
112: if (this .eventListeners != null) {
113: this .eventListeners.remove(connectioneventlistener);
114: }
115: }
116:
117: /**
118: * Invoked by the container. Return a logicalHandle object that wraps a
119: * physical connection.
120: *
121: * @see java.sql.DataSource#getConnection()
122: */
123: public synchronized Connection getConnection() throws SQLException {
124: return getConnection(true, false);
125:
126: }
127:
128: protected synchronized Connection getConnection(
129: boolean resetServerState, boolean forXa)
130: throws SQLException {
131: if (this .physicalConn == null) {
132:
133: SQLException sqlException = SQLError
134: .createSQLException("Physical Connection doesn't exist");
135: callListener(CONNECTION_ERROR_EVENT, sqlException);
136:
137: throw sqlException;
138: }
139:
140: try {
141:
142: if (this .logicalHandle != null) {
143: ((ConnectionWrapper) this .logicalHandle).close(false);
144: }
145:
146: if (resetServerState) {
147: this .physicalConn.resetServerState();
148: }
149:
150: this .logicalHandle = ConnectionWrapper.getInstance(this ,
151: (ConnectionImpl) this .physicalConn, forXa);
152: } catch (SQLException sqlException) {
153: callListener(CONNECTION_ERROR_EVENT, sqlException);
154:
155: throw sqlException;
156: }
157:
158: return this .logicalHandle;
159: }
160:
161: /**
162: * Invoked by the container (not the client), and should close the physical
163: * connection. This will be called if the pool is destroyed or the
164: * connectionEventListener receives a connectionErrorOccurred event.
165: *
166: * @see java.sql.DataSource#close()
167: */
168: public synchronized void close() throws SQLException {
169: if (this .physicalConn != null) {
170: this .physicalConn.close();
171: }
172:
173: this .physicalConn = null;
174: }
175:
176: /**
177: * Notifies all registered ConnectionEventListeners of ConnectionEvents.
178: * Instantiates a new ConnectionEvent which wraps sqlException and invokes
179: * either connectionClose or connectionErrorOccurred on listener as
180: * appropriate.
181: *
182: * @param eventType
183: * value indicating whether connectionClosed or
184: * connectionErrorOccurred called
185: * @param sqlException
186: * the exception being thrown
187: */
188: protected synchronized void callListener(int eventType,
189: SQLException sqlException) {
190:
191: if (this .eventListeners == null) {
192:
193: return;
194: }
195:
196: Enumeration enumeration = this .eventListeners.keys();
197: ConnectionEvent connectionevent = new ConnectionEvent(this ,
198: sqlException);
199:
200: while (enumeration.hasMoreElements()) {
201:
202: ConnectionEventListener connectioneventlistener = (ConnectionEventListener) enumeration
203: .nextElement();
204: ConnectionEventListener connectioneventlistener1 = (ConnectionEventListener) this .eventListeners
205: .get(connectioneventlistener);
206:
207: if (eventType == CONNECTION_CLOSED_EVENT) {
208: connectioneventlistener1
209: .connectionClosed(connectionevent);
210: } else if (eventType == CONNECTION_ERROR_EVENT) {
211: connectioneventlistener1
212: .connectionErrorOccurred(connectionevent);
213: }
214: }
215: }
216:
217: // /**
218: // * Registers a <code>StatementEventListener</code> with this <code>PooledConnection</code> object. Components that
219: // * wish to be notified when <code>PreparedStatement</code>s created by the
220: // * connection are closed or are detected to be invalid may use this method
221: // * to register a <code>StatementEventListener</code> with this <code>PooledConnection</code> object.
222: // * <p>
223: // * @param listener an component which implements the <code>StatementEventListener</code>
224: // * interface that is to be registered with this <code>PooledConnection</code> object
225: // * <p>
226: // * @since 1.6
227: // */
228: // public void addStatementEventListener(StatementEventListener listener) {
229: // throw new NotYetImplementedException();
230: // }
231: //
232: // /**
233: // * Removes the specified <code>StatementEventListener</code> from the list of
234: // * components that will be notified when the driver detects that a
235: // * <code>PreparedStatement</code> has been closed or is invalid.
236: // * <p>
237: // * @param listener the component which implements the
238: // * <code>StatementEventListener</code> interface that was previously
239: // * registered with this <code>PooledConnection</code> object
240: // * <p>
241: // * @since 1.6
242: // */
243: // public void removeStatementEventListener(StatementEventListener listener) {
244: // throw new NotYetImplementedException();
245: // }
246:
247: }
|