001/* 002 * HA-JDBC: High-Availability JDBC 003 * Copyright (C) 2012 Paul Ferraro 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU Lesser General Public License as published by 007 * the Free Software Foundation, either version 3 of the License, or 008 * (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public License 016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 017 */ 018package net.sf.hajdbc.sql.pool; 019 020import java.lang.reflect.Method; 021import java.sql.SQLException; 022import java.util.Arrays; 023import java.util.HashSet; 024import java.util.Set; 025 026import javax.sql.ConnectionEventListener; 027import javax.sql.PooledConnection; 028import javax.sql.StatementEventListener; 029 030import net.sf.hajdbc.Database; 031import net.sf.hajdbc.invocation.InvocationStrategies; 032import net.sf.hajdbc.invocation.InvocationStrategy; 033import net.sf.hajdbc.invocation.Invoker; 034import net.sf.hajdbc.sql.ChildInvocationHandler; 035import net.sf.hajdbc.sql.ConnectionProxyFactoryFactory; 036import net.sf.hajdbc.sql.ProxyFactoryFactory; 037import net.sf.hajdbc.util.reflect.Methods; 038 039/** 040 * @author Paul Ferraro 041 * @param <D> 042 * @param <C> 043 */ 044@SuppressWarnings("nls") 045public abstract class AbstractPooledConnectionInvocationHandler<Z, D extends Database<Z>, C extends PooledConnection, F extends AbstractPooledConnectionProxyFactory<Z, D, C>> extends ChildInvocationHandler<Z, D, Z, SQLException, C, SQLException, F> 046{ 047 private static final Method addConnectionEventListenerMethod = Methods.getMethod(PooledConnection.class, "addConnectionEventListener", ConnectionEventListener.class); 048 private static final Method addStatementEventListenerMethod = Methods.getMethod(PooledConnection.class, "addStatementEventListener", StatementEventListener.class); 049 private static final Method removeConnectionEventListenerMethod = Methods.getMethod(PooledConnection.class, "removeConnectionEventListener", ConnectionEventListener.class); 050 private static final Method removeStatementEventListenerMethod = Methods.getMethod(PooledConnection.class, "removeStatementEventListener", StatementEventListener.class); 051 052 private static final Set<Method> eventListenerMethodSet = new HashSet<Method>(Arrays.asList(addConnectionEventListenerMethod, addStatementEventListenerMethod, removeConnectionEventListenerMethod, removeStatementEventListenerMethod)); 053 054 private static final Method getConnectionMethod = Methods.getMethod(PooledConnection.class, "getConnection"); 055 private static final Method closeMethod = Methods.getMethod(PooledConnection.class, "close"); 056 057 public AbstractPooledConnectionInvocationHandler(Class<C> proxyClass, F proxyFactory) 058 { 059 super(proxyClass, proxyFactory, null); 060 } 061 062 @Override 063 protected ProxyFactoryFactory<Z, D, C, SQLException, ?, ? extends Exception> getProxyFactoryFactory(C object, Method method, Object... parameters) throws SQLException 064 { 065 if (method.equals(getConnectionMethod)) 066 { 067 return new ConnectionProxyFactoryFactory<Z, D, C>(this.getProxyFactory().getTransactionContext()); 068 } 069 070 return super.getProxyFactoryFactory(object, method, parameters); 071 } 072 073 /** 074 * {@inheritDoc} 075 * @see net.sf.hajdbc.sql.AbstractInvocationHandler#getInvocationStrategy(java.lang.Object, java.lang.reflect.Method, java.lang.Object[]) 076 */ 077 @Override 078 protected InvocationStrategy getInvocationStrategy(C connection, Method method, Object... parameters) throws SQLException 079 { 080 if (eventListenerMethodSet.contains(method)) 081 { 082 return InvocationStrategies.INVOKE_ON_EXISTING; 083 } 084 085 return super.getInvocationStrategy(connection, method, parameters); 086 } 087 088 @Override 089 protected <R> void postInvoke(Invoker<Z, D, C, R, SQLException> invoker, C proxy, Method method, Object... parameters) 090 { 091 super.postInvoke(invoker, proxy, method, parameters); 092 093 if (method.equals(closeMethod)) 094 { 095 this.getProxyFactory().remove(); 096 } 097 else if (method.equals(addConnectionEventListenerMethod)) 098 { 099 this.getProxyFactory().addConnectionEventListener((ConnectionEventListener) parameters[0], invoker); 100 } 101 else if (method.equals(removeConnectionEventListenerMethod)) 102 { 103 this.getProxyFactory().removeConnectionEventListener((ConnectionEventListener) parameters[0]); 104 } 105 else if (method.equals(addStatementEventListenerMethod)) 106 { 107 this.getProxyFactory().addStatementEventListener((StatementEventListener) parameters[0], invoker); 108 } 109 else if (method.equals(removeStatementEventListenerMethod)) 110 { 111 this.getProxyFactory().removeStatementEventListener((StatementEventListener) parameters[0]); 112 } 113 } 114}