001/* 002 * HA-JDBC: High-Availability JDBC 003 * Copyright (C) 2013 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; 019 020import java.sql.Connection; 021import java.sql.SQLException; 022import java.sql.Statement; 023import java.util.LinkedList; 024import java.util.List; 025import java.util.Map; 026import java.util.concurrent.locks.Lock; 027 028import net.sf.hajdbc.Database; 029import net.sf.hajdbc.invocation.Invoker; 030import net.sf.hajdbc.io.InputSinkRegistryImpl; 031import net.sf.hajdbc.io.InputSinkStrategy; 032import net.sf.hajdbc.logging.Level; 033import net.sf.hajdbc.util.Resources; 034 035/** 036 * 037 * @author Paul Ferraro 038 */ 039public abstract class AbstractStatementProxyFactory<Z, D extends Database<Z>, S extends Statement> extends AbstractInputSinkRegistryProxyFactory<Z, D, Connection, S> 040{ 041 private final List<Invoker<Z, D, S, ?, SQLException>> batchInvokers = new LinkedList<Invoker<Z, D, S, ?, SQLException>>(); 042 private final List<String> batch = new LinkedList<String>(); 043 044 protected AbstractStatementProxyFactory(Connection parent, ProxyFactory<Z, D, Connection, SQLException> parentFactory, Invoker<Z, D, Connection, S, SQLException> invoker, Map<D, S> map, TransactionContext<Z, D> context) 045 { 046 super(parent, parentFactory, invoker, map, context, new InputSinkRegistryImpl<Object>((InputSinkStrategy<Object>) parentFactory.getDatabaseCluster().getInputSinkStrategy())); 047 } 048 049 @Override 050 public Connection getConnection(D database) throws SQLException 051 { 052 return this.get(database).getConnection(); 053 } 054 055 public List<Lock> getBatchLocks() throws SQLException 056 { 057 return this.extractLocks(this.batch); 058 } 059 060 public void addBatchSQL(String sql) 061 { 062 this.batch.add(sql); 063 } 064 065 public List<String> getBatch() 066 { 067 return this.batch; 068 } 069 070 public void clearBatch() 071 { 072 this.batch.clear(); 073 } 074 075 public void addBatchInvoker(Invoker<Z, D, S, ?, SQLException> invoker) 076 { 077 this.batchInvokers.add(invoker); 078 } 079 080 public void clearBatchInvokers() 081 { 082 this.batchInvokers.clear(); 083 } 084 085 @Override 086 public void replay(D database, S object) throws SQLException 087 { 088 super.replay(database, object); 089 090 for (Invoker<Z, D, S, ?, SQLException> invoker: this.batchInvokers) 091 { 092 this.logger.log(Level.TRACE, "Replaying {1}.{2} against database {0}", database, object.getClass().getName(), invoker); 093 094 try 095 { 096 invoker.invoke(database, object); 097 } 098 catch (Throwable e) 099 { 100 this.getExceptionFactory().createException(e); 101 } 102 } 103 } 104 105 @Override 106 public void close(D database, S statement) 107 { 108 Resources.close(statement); 109 } 110}