teichmann@5831: package org.dive4elements.river.artifacts.datacage.templating; sascha@998: sascha@998: import java.util.regex.Pattern; sascha@998: import java.util.regex.Matcher; sascha@998: sascha@998: import java.util.List; sascha@998: import java.util.Map; sascha@998: import java.util.TreeMap; sascha@998: import java.util.ArrayList; sascha@998: sascha@998: import java.sql.PreparedStatement; sascha@998: import java.sql.SQLException; sascha@998: import java.sql.Connection; sascha@998: import java.sql.ResultSet; sascha@998: sascha@998: import net.sf.ehcache.Cache; sascha@998: import net.sf.ehcache.Element; sascha@998: teichmann@5831: import org.dive4elements.river.artifacts.cache.CacheFactory; sascha@998: sascha@1023: import org.apache.log4j.Logger; sascha@1023: felix@4615: /** SQL Statement, create PreparedStatement. */ sascha@998: public class CompiledStatement sascha@998: { sascha@1023: private static Logger log = Logger.getLogger(CompiledStatement.class); sascha@1023: sascha@998: public static final String DATACAGE_DB_CACHE = sascha@998: "datacage.db"; sascha@998: sascha@998: public static final Pattern VAR = sascha@998: Pattern.compile("\\$\\{([a-zA-Z0-9_-]+)\\}"); sascha@998: sascha@998: protected String original; sascha@998: protected String statement; sascha@998: sascha@998: protected Map> positions; sascha@998: sascha@998: protected int numVars; sascha@998: sascha@998: public class Instance { sascha@998: sascha@998: protected PreparedStatement preparedStatement; sascha@998: sascha@998: public Instance() { sascha@998: } sascha@998: felix@4898: /** Executes a Statement. */ sascha@998: protected ResultData executeCached( sascha@998: Cache cache, sascha@998: Connection connection, sascha@998: StackFrames frames sascha@998: ) sascha@998: throws SQLException sascha@998: { sascha@1023: log.debug("executeCached"); sascha@998: Object [] values = new Object[numVars]; sascha@998: sascha@998: StringBuilder sb = new StringBuilder(original); sascha@998: sascha@998: for (Map.Entry> entry: positions.entrySet()) { sascha@998: String key = entry.getKey(); sascha@998: Object value = frames.get(key); sascha@998: sb.append(';').append(key).append(':').append(value); sascha@998: for (Integer index: entry.getValue()) { sascha@998: values[index] = value; sascha@998: } sascha@998: } sascha@998: sascha@998: // XXX: Maybe too many collisions? sascha@998: // String key = original + Arrays.hashCode(values); sascha@998: String key = sb.toString(); sascha@998: sascha@998: Element element = cache.get(key); sascha@998: sascha@998: if (element != null) { sascha@998: return (ResultData)element.getValue(); sascha@998: } sascha@998: sascha@998: if (preparedStatement == null) { sascha@998: preparedStatement = connection.prepareStatement(statement); sascha@998: } sascha@998: sascha@998: for (int i = 0; i < values.length; ++i) { sascha@998: preparedStatement.setObject(i+1, values[i]); sascha@998: } sascha@998: sascha@998: ResultData data; sascha@998: sascha@1097: if (log.isDebugEnabled()) { sascha@1097: log.debug("executing: " + statement); sascha@1097: } sascha@1097: sascha@998: ResultSet result = preparedStatement.executeQuery(); sascha@998: try { sascha@998: data = new ResultData(preparedStatement.getMetaData()) sascha@998: .addAll(result); sascha@998: } sascha@998: finally { sascha@998: result.close(); sascha@998: } sascha@998: sascha@998: element = new Element(key, data); sascha@998: cache.put(element); sascha@998: sascha@998: return data; sascha@998: } sascha@998: sascha@998: protected ResultData executeUncached( sascha@998: Connection connection, sascha@998: StackFrames frames sascha@3076: ) sascha@998: throws SQLException sascha@998: { sascha@1023: log.debug("executeUncached"); sascha@998: if (preparedStatement == null) { sascha@1023: if (log.isDebugEnabled()) { sascha@1023: log.debug("preparing statement: " + statement); sascha@1023: } sascha@998: preparedStatement = connection.prepareStatement(statement); sascha@998: } sascha@998: sascha@998: for (Map.Entry> entry: positions.entrySet()) { sascha@998: Object value = frames.get(entry.getKey()); sascha@998: for (Integer index: entry.getValue()) { sascha@998: preparedStatement.setObject(index+1, value); sascha@998: } sascha@998: } sascha@998: sascha@1097: if (log.isDebugEnabled()) { sascha@1097: log.debug("executing: " + statement); sascha@1097: } sascha@1097: sascha@998: ResultSet result = preparedStatement.executeQuery(); sascha@998: try { sascha@998: return new ResultData(preparedStatement.getMetaData()) sascha@998: .addAll(result); sascha@998: } sascha@998: finally { sascha@998: result.close(); sascha@998: } sascha@998: } sascha@998: sascha@1011: public ResultData execute( sascha@1011: Connection connection, sascha@1011: StackFrames frames, sascha@1011: boolean cached sascha@1011: ) sascha@998: throws SQLException sascha@998: { sascha@1011: if (!cached) { sascha@1011: return executeUncached(connection, frames); sascha@1011: } sascha@1011: sascha@998: Cache cache = CacheFactory.getCache(DATACAGE_DB_CACHE); sascha@998: sascha@998: return cache != null sascha@998: ? executeCached(cache, connection, frames) sascha@998: : executeUncached(connection, frames); sascha@998: } sascha@998: sascha@998: public void close() { sascha@998: if (preparedStatement != null) { sascha@998: try { sascha@998: preparedStatement.close(); sascha@998: } sascha@998: catch (SQLException sqle) { sascha@998: } sascha@998: preparedStatement = null; sascha@998: } sascha@998: } sascha@998: } // class Instance sascha@998: sascha@998: public CompiledStatement() { sascha@998: } sascha@998: sascha@998: public CompiledStatement(String original) { sascha@998: this.original = original; sascha@998: // TreeMap to ensure order sascha@998: positions = new TreeMap>(); sascha@998: compile(); sascha@998: } sascha@998: sascha@998: protected void compile() { sascha@998: sascha@998: StringBuffer sb = new StringBuffer(); sascha@998: sascha@998: Matcher m = VAR.matcher(original); sascha@998: sascha@998: int index = 0; sascha@998: felix@4805: // Find variables like ${varname}. sascha@998: while (m.find()) { sascha@1716: String key = m.group(1).toUpperCase(); sascha@998: List indices = positions.get(key); sascha@998: if (indices == null) { sascha@998: indices = new ArrayList(); sascha@998: positions.put(key, indices); sascha@998: } sascha@998: indices.add(index); sascha@998: m.appendReplacement(sb, "?"); sascha@998: ++index; sascha@998: } sascha@998: sascha@998: m.appendTail(sb); sascha@998: sascha@998: numVars = index; sascha@998: sascha@998: statement = sb.toString(); sascha@998: } sascha@998: sascha@998: public String getStatement() { sascha@998: return statement; sascha@998: } sascha@998: } sascha@998: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :