001: /*
002: Copyright (C) 2002-2004 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: */
025: package com.mysql.jdbc.jdbc2.optional;
026:
027: import java.lang.reflect.InvocationHandler;
028: import java.lang.reflect.InvocationTargetException;
029: import java.lang.reflect.Method;
030: import java.lang.reflect.Proxy;
031: import java.sql.SQLException;
032: import java.util.Map;
033:
034: import com.mysql.jdbc.SQLError;
035:
036: /**
037: * Base class for all wrapped instances created by LogicalHandle
038: *
039: * @author Mark matthews
040: *
041: * @version $Id: WrapperBase.java 6407 2007-04-23 21:40:24Z mmatthews $
042: */
043: abstract class WrapperBase {
044: protected MysqlPooledConnection pooledConnection;
045:
046: /**
047: * Fires connection error event if required, before re-throwing exception
048: *
049: * @param sqlEx
050: * the SQLException that has ocurred
051: * @throws SQLException
052: * (rethrown)
053: */
054: protected void checkAndFireConnectionError(SQLException sqlEx)
055: throws SQLException {
056: if (this .pooledConnection != null) {
057: if (SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE
058: .equals(sqlEx.getSQLState())) {
059: this .pooledConnection.callListener(
060: MysqlPooledConnection.CONNECTION_ERROR_EVENT,
061: sqlEx);
062: }
063: }
064:
065: throw sqlEx;
066: }
067:
068: protected Map unwrappedInterfaces = null;
069:
070: protected class ConnectionErrorFiringInvocationHandler implements
071: InvocationHandler {
072: Object invokeOn = null;
073:
074: public ConnectionErrorFiringInvocationHandler(Object toInvokeOn) {
075: invokeOn = toInvokeOn;
076: }
077:
078: public Object invoke(Object proxy, Method method, Object[] args)
079: throws Throwable {
080: Object result = null;
081:
082: try {
083: result = method.invoke(invokeOn, args);
084:
085: if (result != null) {
086: result = proxyIfInterfaceIsJdbc(result, result
087: .getClass());
088: }
089: } catch (InvocationTargetException e) {
090: if (e.getTargetException() instanceof SQLException) {
091: checkAndFireConnectionError((SQLException) e
092: .getTargetException());
093: } else {
094: throw e;
095: }
096: }
097:
098: return result;
099: }
100:
101: /**
102: * Recursively checks for interfaces on the given object to determine
103: * if it implements a java.sql interface, and if so, proxies the
104: * instance so that we can catch and fire SQL errors.
105: * @param toProxy
106: * @param clazz
107: * @return
108: */
109: private Object proxyIfInterfaceIsJdbc(Object toProxy,
110: Class clazz) {
111: Class[] interfaces = clazz.getInterfaces();
112:
113: for (int i = 0; i < interfaces.length; i++) {
114: String packageName = interfaces[i].getPackage()
115: .getName();
116:
117: if ("java.sql".equals(packageName)
118: || "javax.sql".equals(packageName)) {
119: return Proxy.newProxyInstance(toProxy.getClass()
120: .getClassLoader(), interfaces,
121: new ConnectionErrorFiringInvocationHandler(
122: toProxy));
123: }
124:
125: return proxyIfInterfaceIsJdbc(toProxy, interfaces[i]);
126: }
127:
128: return toProxy;
129: }
130: }
131: }
|