001/* 002 * HA-JDBC: High-Availability JDBC 003 * Copyright (c) 2004-2007 Paul Ferraro 004 * 005 * This library is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU Lesser General Public License as published by the 007 * Free Software Foundation; either version 2.1 of the License, or (at your 008 * option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, but WITHOUT 011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License 013 * for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public License 016 * along with this library; if not, write to the Free Software Foundation, 017 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 018 * 019 * Contact: ferraro@users.sourceforge.net 020 */ 021package net.sf.hajdbc.sql; 022 023import java.lang.reflect.InvocationTargetException; 024import java.lang.reflect.Method; 025import java.util.LinkedList; 026import java.util.List; 027import java.util.Map; 028import java.util.Set; 029 030import net.sf.hajdbc.Database; 031import net.sf.hajdbc.util.reflect.Methods; 032 033/** 034 * @author Paul Ferraro 035 * @param <D> 036 * @param <P> 037 * @param <E> 038 */ 039public abstract class LocatorInvocationHandler<D, P, E> extends AbstractChildInvocationHandler<D, P, E> 040{ 041 private final Method freeMethod; 042 private final List<Invoker<D, E, ?>> invokerList = new LinkedList<Invoker<D, E, ?>>(); 043 044 /** 045 * @param parent 046 * @param proxy 047 * @param invoker 048 * @param proxyClass 049 * @param objectMap 050 * @throws Exception 051 */ 052 protected LocatorInvocationHandler(P parent, SQLProxy<D, P> proxy, Invoker<D, P, E> invoker, Class<E> proxyClass, Map<Database<D>, E> objectMap) throws Exception 053 { 054 super(parent, proxy, invoker, proxyClass, objectMap); 055 056 this.freeMethod = Methods.findMethod(proxyClass, "free"); 057 } 058 059 /** 060 * @see net.sf.hajdbc.sql.AbstractChildInvocationHandler#getInvocationStrategy(java.lang.Object, java.lang.reflect.Method, java.lang.Object[]) 061 */ 062 @Override 063 protected InvocationStrategy<D, E, ?> getInvocationStrategy(E object, Method method, Object[] parameters) throws Exception 064 { 065 if (this.getDatabaseReadMethodSet().contains(method)) 066 { 067 return new DatabaseReadInvocationStrategy<D, E, Object>(); 068 } 069 070 return super.getInvocationStrategy(object, method, parameters); 071 } 072 073 protected abstract Set<Method> getDatabaseReadMethodSet(); 074 075 /** 076 * @see net.sf.hajdbc.sql.AbstractChildInvocationHandler#postInvoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[]) 077 */ 078 @SuppressWarnings("nls") 079 @Override 080 protected void postInvoke(E object, Method method, Object[] parameters) 081 { 082 if ((this.freeMethod != null) && method.equals(this.freeMethod)) 083 { 084 this.getParentProxy().removeChild(this); 085 } 086 } 087 088 /** 089 * @see net.sf.hajdbc.sql.AbstractChildInvocationHandler#close(java.lang.Object, java.lang.Object) 090 */ 091 @SuppressWarnings("nls") 092 @Override 093 protected void close(P parent, E locator) 094 { 095 if (this.freeMethod != null) 096 { 097 try 098 { 099 // free() is a Java 1.6 method - so invoke reflectively 100 this.freeMethod.invoke(locator); 101 } 102 catch (IllegalAccessException e) 103 { 104 this.logger.warn(e.getMessage(), e); 105 } 106 catch (InvocationTargetException e) 107 { 108 this.logger.warn(e.toString(), e.getTargetException()); 109 } 110 } 111 } 112 113 /** 114 * @see net.sf.hajdbc.sql.AbstractInvocationHandler#record(net.sf.hajdbc.sql.Invoker, java.lang.reflect.Method, java.lang.Object[]) 115 */ 116 @Override 117 protected void record(Invoker<D, E, ?> invoker, Method method, Object[] parameters) 118 { 119 if (this.isRecordable(method)) 120 { 121 synchronized (this.invokerList) 122 { 123 this.invokerList.add(invoker); 124 } 125 } 126 } 127}