sascha@372: package de.intevation.flys.artifacts.services.meta; sascha@372: sascha@372: import java.util.regex.Pattern; sascha@372: import java.util.regex.Matcher; sascha@372: sascha@372: import java.util.List; sascha@372: import java.util.Map; sascha@972: import java.util.TreeMap; sascha@372: import java.util.ArrayList; sascha@372: sascha@372: import java.sql.PreparedStatement; sascha@372: import java.sql.SQLException; sascha@372: import java.sql.Connection; sascha@372: import java.sql.ResultSet; sascha@372: sascha@972: import net.sf.ehcache.Cache; sascha@972: import net.sf.ehcache.Element; sascha@972: sascha@972: import de.intevation.flys.artifacts.cache.CacheFactory; sascha@972: sascha@372: public class CompiledStatement sascha@372: { sascha@972: public static final String DATACAGE_DB_CACHE = sascha@972: "datacage.db"; sascha@972: sascha@969: public static final Pattern VAR = sascha@969: Pattern.compile("\\$\\{([a-zA-Z0-9_-]+)\\}"); sascha@372: sascha@372: protected String original; sascha@372: protected String statement; sascha@372: sascha@372: protected Map> positions; sascha@372: sascha@372: protected PreparedStatement preparedStatement; sascha@372: sascha@972: protected int numVars; sascha@972: sascha@372: public CompiledStatement() { sascha@372: } sascha@372: sascha@372: public CompiledStatement(String original) { sascha@372: this.original = original; sascha@972: // TreeMap to ensure order sascha@972: positions = new TreeMap>(); sascha@372: compile(); sascha@372: } sascha@372: sascha@372: protected void compile() { sascha@372: sascha@372: StringBuffer sb = new StringBuffer(); sascha@372: sascha@372: Matcher m = VAR.matcher(original); sascha@372: sascha@972: int index = 0; sascha@372: sascha@372: while (m.find()) { sascha@372: String key = m.group(1); sascha@372: List indices = positions.get(key); sascha@372: if (indices == null) { sascha@372: indices = new ArrayList(); sascha@372: positions.put(key, indices); sascha@372: } sascha@372: indices.add(index); sascha@372: m.appendReplacement(sb, "?"); sascha@372: ++index; sascha@372: } sascha@372: sascha@372: m.appendTail(sb); sascha@372: sascha@972: numVars = index; sascha@972: sascha@372: statement = sb.toString(); sascha@372: } sascha@372: sascha@372: public String getStatement() { sascha@372: return statement; sascha@372: } sascha@372: sascha@972: protected ResultData executeCached( sascha@972: Cache cache, sascha@972: Connection connection, sascha@972: StackFrames frames sascha@972: ) sascha@972: throws SQLException sascha@972: { sascha@972: Object [] values = new Object[numVars]; sascha@972: sascha@972: StringBuilder sb = new StringBuilder(original); sascha@972: sascha@972: for (Map.Entry> entry: positions.entrySet()) { sascha@972: String key = entry.getKey(); sascha@972: Object value = frames.get(key); sascha@972: sb.append(';').append(key).append(':').append(value); sascha@972: for (Integer index: entry.getValue()) { sascha@972: values[index] = value; sascha@972: } sascha@972: } sascha@972: sascha@972: // XXX: Maybe too many collisions? sascha@972: // String key = original + Arrays.hashCode(values); sascha@972: String key = sb.toString(); sascha@972: sascha@972: Element element = cache.get(key); sascha@972: sascha@972: if (element != null) { sascha@972: return (ResultData)element.getValue(); sascha@972: } sascha@972: sascha@972: if (preparedStatement == null) { sascha@972: preparedStatement = connection.prepareStatement(statement); sascha@972: } sascha@972: sascha@972: for (int i = 0; i < values.length; ++i) { sascha@972: preparedStatement.setObject(i+1, values[i]); sascha@972: } sascha@972: sascha@972: ResultData data; sascha@972: sascha@972: ResultSet result = preparedStatement.executeQuery(); sascha@972: try { sascha@972: data = new ResultData(preparedStatement.getMetaData()) sascha@972: .addAll(result); sascha@972: } sascha@972: finally { sascha@972: result.close(); sascha@972: } sascha@972: sascha@972: element = new Element(key, data); sascha@972: cache.put(element); sascha@972: sascha@972: return data; sascha@972: } sascha@972: sascha@972: protected ResultData executeUncached( sascha@972: Connection connection, sascha@972: StackFrames frames sascha@972: ) sascha@372: throws SQLException sascha@372: { sascha@372: if (preparedStatement == null) { sascha@372: preparedStatement = connection.prepareStatement(statement); sascha@372: } sascha@372: sascha@372: for (Map.Entry> entry: positions.entrySet()) { sascha@372: Object value = frames.get(entry.getKey()); sascha@372: for (Integer index: entry.getValue()) { sascha@972: preparedStatement.setObject(index+1, value); sascha@372: } sascha@372: } sascha@372: sascha@372: ResultSet result = preparedStatement.executeQuery(); sascha@372: try { sascha@372: return new ResultData(preparedStatement.getMetaData()) sascha@372: .addAll(result); sascha@372: } sascha@372: finally { sascha@372: result.close(); sascha@372: } sascha@372: } sascha@372: sascha@972: public ResultData execute(Connection connection, StackFrames frames) sascha@972: throws SQLException sascha@972: { sascha@972: Cache cache = CacheFactory.getCache(DATACAGE_DB_CACHE); sascha@972: sascha@972: return cache != null sascha@972: ? executeCached(cache, connection, frames) sascha@972: : executeUncached(connection, frames); sascha@972: } sascha@972: sascha@372: public void close() { sascha@372: if (preparedStatement != null) { sascha@372: try { sascha@372: preparedStatement.close(); sascha@372: } sascha@372: catch (SQLException sqle) { sascha@372: } sascha@372: preparedStatement = null; sascha@372: } sascha@372: } sascha@372: } sascha@372: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :