sascha@4068: package de.intevation.db; sascha@4068: sascha@4068: import java.util.Properties; sascha@4068: sascha@4068: import java.io.IOException; sascha@4068: import java.io.InputStream; sascha@4068: sascha@4068: import org.apache.log4j.Logger; sascha@4068: sascha@4069: import java.util.List; sascha@4069: import java.util.ArrayList; sascha@4069: import java.util.Map; sascha@4069: import java.util.HashMap; sascha@4069: import java.util.Enumeration; sascha@4069: sascha@4069: import java.sql.Connection; sascha@4069: import java.sql.SQLException; sascha@4069: import java.sql.PreparedStatement; sascha@4069: import java.sql.Timestamp; sascha@4069: sascha@4069: import java.util.regex.Matcher; sascha@4069: import java.util.regex.Pattern; sascha@4069: sascha@4068: public class Statements sascha@4068: { sascha@4069: public static final Pattern VAR = Pattern.compile(":([a-zA-Z0-9_]+)"); sascha@4069: sascha@4069: public static class SymbolicStatement { sascha@4069: sascha@4069: protected String statement; sascha@4069: protected String compiled; sascha@4069: protected Map> positions; sascha@4069: sascha@4069: public class Instance { sascha@4069: sascha@4069: /** TODO: Support more types. */ sascha@4069: sascha@4069: protected PreparedStatement stmnt; sascha@4069: sascha@4069: public Instance(Connection connection) throws SQLException { sascha@4069: stmnt = connection.prepareStatement(compiled); sascha@4069: } sascha@4069: sascha@4069: public void close() { sascha@4069: try { sascha@4069: stmnt.close(); sascha@4069: } sascha@4069: catch (SQLException sqle) { sascha@4069: log.error("cannot close statement", sqle); sascha@4069: } sascha@4069: } sascha@4069: sascha@4069: public void setInt(String key, int value) sascha@4069: throws SQLException sascha@4069: { sascha@4069: List pos = positions.get(key.toLowerCase()); sascha@4069: if (pos != null) { sascha@4069: for (Integer p: pos) { sascha@4069: stmnt.setInt(p, value); sascha@4069: } sascha@4069: } sascha@4069: } sascha@4069: sascha@4069: public void setString(String key, String value) sascha@4069: throws SQLException sascha@4069: { sascha@4069: List pos = positions.get(key.toLowerCase()); sascha@4069: if (pos != null) { sascha@4069: for (Integer p: pos) { sascha@4069: stmnt.setString(p, value); sascha@4069: } sascha@4069: } sascha@4069: } sascha@4069: sascha@4069: public void setObject(String key, Object value) sascha@4069: throws SQLException sascha@4069: { sascha@4069: List pos = positions.get(key.toLowerCase()); sascha@4069: if (pos != null) { sascha@4069: for (Integer p: pos) { sascha@4069: stmnt.setObject(p, value); sascha@4069: } sascha@4069: } sascha@4069: } sascha@4069: sascha@4069: public void setTimestamp(String key, Timestamp value) sascha@4069: throws SQLException sascha@4069: { sascha@4069: List pos = positions.get(key.toLowerCase()); sascha@4069: if (pos != null) { sascha@4069: for (Integer p: pos) { sascha@4069: stmnt.setTimestamp(p, value); sascha@4069: } sascha@4069: } sascha@4069: } sascha@4069: sascha@4069: public void setDouble(String key, int value) sascha@4069: throws SQLException sascha@4069: { sascha@4069: List pos = positions.get(key.toLowerCase()); sascha@4069: if (pos != null) { sascha@4069: for (Integer p: pos) { sascha@4069: stmnt.setDouble(p, value); sascha@4069: } sascha@4069: } sascha@4069: } sascha@4069: sascha@4069: public void setNull(String key, int sqlType) sascha@4069: throws SQLException sascha@4069: { sascha@4069: List pos = positions.get(key.toLowerCase()); sascha@4069: if (pos != null) { sascha@4069: for (Integer p: pos) { sascha@4069: stmnt.setNull(p, sqlType); sascha@4069: } sascha@4069: } sascha@4069: } sascha@4069: sascha@4069: public void set(Map map) throws SQLException { sascha@4069: for (Map.Entry entry: map.entrySet()) { sascha@4069: setObject(entry.getKey(), entry.getValue()); sascha@4069: } sascha@4069: } sascha@4069: sascha@4069: } // class Instance sascha@4069: sascha@4069: public SymbolicStatement(String statement) { sascha@4069: this.statement = statement; sascha@4069: compile(); sascha@4069: } sascha@4069: sascha@4069: public String getStatement() { sascha@4069: return statement; sascha@4069: } sascha@4069: sascha@4069: protected void compile() { sascha@4069: positions = new HashMap>(); sascha@4069: sascha@4069: StringBuffer sb = new StringBuffer(); sascha@4069: Matcher m = VAR.matcher(statement); sascha@4069: int index = 1; sascha@4069: while (m.find()) { sascha@4069: String key = m.group(1).toLowerCase(); sascha@4069: List list = positions.get(key); sascha@4069: if (list == null) { sascha@4069: list = new ArrayList(); sascha@4069: positions.put(key, list); sascha@4069: } sascha@4069: list.add(index++); sascha@4069: m.appendReplacement(sb, "?"); sascha@4069: } sascha@4069: m.appendTail(sb); sascha@4069: compiled = sb.toString(); sascha@4069: } sascha@4069: } // class SymbolicStatement sascha@4069: sascha@4069: sascha@4068: private static Logger log = Logger.getLogger(Statements.class); sascha@4068: sascha@4068: public static final String RESOURCE_PATH = "/sql/"; sascha@4068: public static final String COMMON_PROPERTIES = "-common.properties"; sascha@4068: sascha@4068: protected String type; sascha@4068: protected String driver; sascha@4068: sascha@4069: protected Map statements; sascha@4068: sascha@4068: public Statements(String type, String driver) { sascha@4068: this.type = type; sascha@4068: this.driver = driver; sascha@4068: } sascha@4068: sascha@4069: public SymbolicStatement getStatement(String key) { sascha@4069: if (statements == null) { sascha@4069: statements = loadStatements(); sascha@4069: } sascha@4069: return statements.get(key); sascha@4069: } sascha@4069: sascha@4069: protected Map loadStatements() { sascha@4069: Map statements = sascha@4069: new HashMap(); sascha@4069: sascha@4069: Properties properties = loadProperties(); sascha@4069: sascha@4069: for (Enumeration e = properties.propertyNames(); e.hasMoreElements();) { sascha@4069: String key = (String)e.nextElement(); sascha@4069: String value = properties.getProperty(key); sascha@4069: SymbolicStatement symbolic = new SymbolicStatement(value); sascha@4069: statements.put(key, symbolic); sascha@4069: } sascha@4069: sascha@4069: return statements; sascha@4069: } sascha@4069: sascha@4068: protected String driverToProperties() { sascha@4068: return sascha@4068: type + "-" + sascha@4068: driver.replace('.', '-').toLowerCase() + ".properties"; sascha@4068: } sascha@4068: sascha@4068: protected Properties loadCommon() { sascha@4068: Properties common = new Properties(); sascha@4068: sascha@4068: String path = RESOURCE_PATH + type + COMMON_PROPERTIES; sascha@4068: sascha@4068: InputStream in = Statements.class.getResourceAsStream(path); sascha@4068: sascha@4068: if (in != null) { sascha@4068: try { sascha@4068: common.load(in); sascha@4068: } sascha@4068: catch (IOException ioe) { sascha@4068: log.error("cannot load defaults: " + path, ioe); sascha@4068: } sascha@4068: finally { sascha@4068: try { sascha@4068: in.close(); sascha@4068: } sascha@4068: catch (IOException ioe) { sascha@4068: } sascha@4068: } sascha@4068: } sascha@4068: else { sascha@4068: log.warn("cannot find: " + path); sascha@4068: } sascha@4068: sascha@4068: return common; sascha@4068: } sascha@4068: sascha@4069: protected Properties loadProperties() { sascha@4068: sascha@4068: Properties common = loadCommon(); sascha@4068: sascha@4069: Properties properties = new Properties(common); sascha@4068: sascha@4068: String path = RESOURCE_PATH + driverToProperties(); sascha@4068: sascha@4068: InputStream in = Statements.class.getResourceAsStream(path); sascha@4068: sascha@4068: if (in != null) { sascha@4068: try { sascha@4068: properties.load(in); sascha@4068: } sascha@4068: catch (IOException ioe) { sascha@4068: log.error("cannot load statements: " + path, ioe); sascha@4068: } sascha@4068: finally { sascha@4068: try { sascha@4068: in.close(); sascha@4068: } sascha@4068: catch (IOException ioe) { sascha@4068: } sascha@4068: } sascha@4068: } sascha@4068: else { sascha@4068: log.warn("cannot find: " + path); sascha@4068: } sascha@4068: sascha@4068: return properties; sascha@4068: } sascha@4068: } sascha@4068: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :