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}