summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--org/madore/damlengine/DamlEngine.java6
-rw-r--r--org/madore/damlengine/WeblogDatabaseConnection.java84
-rw-r--r--org/madore/damlengine/WeblogServlet.java158
-rw-r--r--org/madore/damlengine/WeblogSummary.java2
4 files changed, 214 insertions, 36 deletions
diff --git a/org/madore/damlengine/DamlEngine.java b/org/madore/damlengine/DamlEngine.java
index a0299ad..cffd589 100644
--- a/org/madore/damlengine/DamlEngine.java
+++ b/org/madore/damlengine/DamlEngine.java
@@ -81,8 +81,10 @@ public final class DamlEngine {
}
public static final class IncantDOM {
- static DOMImplementation domi;
+ static ThreadLocal<DOMImplementation> pdomi
+ = new ThreadLocal<DOMImplementation>();
public static DOMImplementation getDOMI() {
+ DOMImplementation domi = pdomi.get();
if ( domi == null ) {
DOMImplementationSource source
= new DOMImplementationSourceImpl();
@@ -90,6 +92,7 @@ public final class DamlEngine {
if ( domi == null )
throw new MissingResourceException("failed to obtain DOM implementation",
"org.w3c.dom.ls.DOMImplementationLS", "");
+ pdomi.set(domi);
}
return domi;
}
@@ -153,6 +156,7 @@ public final class DamlEngine {
fullProcess(in, out, null);
}
+ public static boolean runAsServlet = false;
public static Properties appProps;
public static Path basePath;
public static Path templatePath;
diff --git a/org/madore/damlengine/WeblogDatabaseConnection.java b/org/madore/damlengine/WeblogDatabaseConnection.java
index 900f3a0..16d0973 100644
--- a/org/madore/damlengine/WeblogDatabaseConnection.java
+++ b/org/madore/damlengine/WeblogDatabaseConnection.java
@@ -15,73 +15,88 @@ public final class WeblogDatabaseConnection {
throw new AssertionError("WeblogDatabaseConnection cannot be instantiated");
}
- public static Connection conn;
+ public static ThreadLocal<Connection> pconn
+ = new ThreadLocal<Connection>();
public static Connection getConnection()
throws SQLException {
+ Connection conn = pconn.get();
if ( conn == null ) {
- String dbHost = System.getenv("DAMLENGINE_PGHOST");
+ String dbHost = null;
+ if ( ! DamlEngine.runAsServlet )
+ dbHost = System.getenv("DAMLENGINE_PGHOST");
if ( dbHost == null )
dbHost = DamlEngine.appProps.getProperty("pghost");
- if ( dbHost == null )
+ if ( dbHost == null && ! DamlEngine.runAsServlet )
dbHost = System.getenv("PGHOST");
if ( dbHost == null )
dbHost = "localhost";
- String dbPort = System.getenv("DAMLENGINE_PGPORT");
+ String dbPort = null;
+ if ( ! DamlEngine.runAsServlet )
+ dbPort = System.getenv("DAMLENGINE_PGPORT");
if ( dbPort == null )
dbPort = DamlEngine.appProps.getProperty("pgport");
- if ( dbPort == null )
+ if ( dbPort == null && ! DamlEngine.runAsServlet )
dbPort = System.getenv("PGPORT");
if ( dbPort == null )
dbPort = "5432";
- String dbName = System.getenv("DAMLENGINE_DBNAME");
+ String dbName = null;
+ if ( ! DamlEngine.runAsServlet )
+ dbName = System.getenv("DAMLENGINE_DBNAME");
if ( dbName == null )
dbName = DamlEngine.appProps.getProperty("dbname");
if ( dbName == null )
dbName = "weblog";
- String dbUser = System.getenv("DAMLENGINE_PGUSER");
+ String dbUser = null;
+ if ( ! DamlEngine.runAsServlet )
+ dbUser = System.getenv("DAMLENGINE_PGUSER");
if ( dbUser == null )
dbUser = DamlEngine.appProps.getProperty("pguser");
- if ( dbUser == null )
+ if ( dbUser == null && ! DamlEngine.runAsServlet )
dbUser = System.getenv("PGUSER");
- if ( dbUser == null )
+ if ( dbUser == null && ! DamlEngine.runAsServlet )
dbUser = System.getenv("USER");
if ( dbUser == null )
dbUser = System.getProperty("user.name");
if ( dbUser == null )
dbUser = dbName;
- String dbPass = System.getenv("DAMLENGINE_PGPASSWORD");
+ String dbPass = null;
+ if ( ! DamlEngine.runAsServlet )
+ dbPass = System.getenv("DAMLENGINE_PGPASSWORD");
if ( dbPass == null )
dbPass = DamlEngine.appProps.getProperty("pgpassword");
- if ( dbPass == null )
+ if ( dbPass == null && ! DamlEngine.runAsServlet )
dbPass = System.getenv("PGPASSWORD");
- if ( dbPass == null )
- try {
- String dbPassFile = System.getenv("DAMLENGINE_PGPASSFILE");
- if ( dbPassFile == null )
- dbPassFile = DamlEngine.appProps.getProperty("pgpassfile");
- if ( dbPassFile == null )
- dbPassFile = System.getenv("PGPASSFILE");
- if ( dbPassFile == null )
- dbPassFile = System.getProperty("user.home")
- + "/.pgpass";
+ if ( dbPass == null ) {
+ String dbPassFile = null;
+ if ( ! DamlEngine.runAsServlet )
+ dbPassFile = System.getenv("DAMLENGINE_PGPASSFILE");
+ if ( dbPassFile == null )
+ dbPassFile = DamlEngine.appProps.getProperty("pgpassfile");
+ if ( dbPassFile == null && ! DamlEngine.runAsServlet )
+ dbPassFile = System.getenv("PGPASSFILE");
+ if ( dbPassFile == null && ! DamlEngine.runAsServlet )
+ dbPassFile = System.getProperty("user.home")
+ + "/.pgpass";
+ if ( dbPassFile != null ) try {
BufferedReader buf
= new BufferedReader(new InputStreamReader(new FileInputStream(dbPassFile)));
- String line;
- while ( ( line = buf.readLine() ) != null ) {
- String[] elts = line.split(":");
- if ( elts.length == 5
- && ( elts[0].equals("*") || elts[0].equals(dbHost) )
- && ( elts[1].equals("*") || elts[1].equals(dbPort) )
- && ( elts[2].equals("*") || elts[2].equals(dbName) )
- && ( elts[3].equals("*") || elts[3].equals(dbUser) ) ) {
- dbPass = elts[4];
- break;
+ String line;
+ while ( ( line = buf.readLine() ) != null ) {
+ String[] elts = line.split(":");
+ if ( elts.length == 5
+ && ( elts[0].equals("*") || elts[0].equals(dbHost) )
+ && ( elts[1].equals("*") || elts[1].equals(dbPort) )
+ && ( elts[2].equals("*") || elts[2].equals(dbName) )
+ && ( elts[3].equals("*") || elts[3].equals(dbUser) ) ) {
+ dbPass = elts[4];
+ break;
+ }
}
+ } catch (IOException e) {
+ // Ignore
}
- } catch (IOException e) {
- // Ignore
- }
+ }
if ( dbPass == null )
dbPass = "";
final String dbUrl
@@ -93,6 +108,7 @@ public final class WeblogDatabaseConnection {
dbProps.setProperty("sslfactory", "org.postgresql.ssl.NonValidatingFactory");
conn = (new Driver()).connect(dbUrl, dbProps);
conn.createStatement().execute("SET TIME ZONE 0");
+ pconn.set(conn);
}
return conn;
}
diff --git a/org/madore/damlengine/WeblogServlet.java b/org/madore/damlengine/WeblogServlet.java
new file mode 100644
index 0000000..d3b2523
--- /dev/null
+++ b/org/madore/damlengine/WeblogServlet.java
@@ -0,0 +1,158 @@
+package org.madore.damlengine;
+
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+import java.util.Properties;
+import java.util.Enumeration;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.file.Paths;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/* Thinkos about the mess that is tomcat:
+
+ * - Make sure that /usr/share/java/postgresql-jdbc3.jar (or whatever
+ * contains the class org.postgresql.Driver) is symlinked from
+ * /var/lib/tomcat7/common (or some path listed in the common.loader
+ * property of the catalina.properties file). Similarly,
+ * xercesImpl.jar and probably xml-resolver.jar need to be linked.
+
+ * - The following parameters need to be defined in <init-param> tags
+ * inside the <servlet> block: base_path, template_path, pghost,
+ * pgport, dbname, pguser and pgpass or pgpassfile.
+
+ */
+
+public class WeblogServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 2014100704L;
+
+ @Override
+ public void init(ServletConfig cfg)
+ throws ServletException
+ {
+ super.init(cfg); // Important!
+ synchronized ( DamlEngine.class ) { if ( DamlEngine.appProps == null ) {
+ DamlEngine.runAsServlet = true;
+ DamlEngine.appProps = new Properties();
+ for (Enumeration<String> e = cfg.getInitParameterNames() ; e.hasMoreElements() ; ) {
+ String k = e.nextElement();
+ DamlEngine.appProps.setProperty(k, cfg.getInitParameter(k));
+ }
+ if ( DamlEngine.appProps.getProperty("base_path") != null )
+ DamlEngine.basePath = Paths.get(DamlEngine.appProps.getProperty("base_path"));
+ if ( DamlEngine.basePath == null )
+ DamlEngine.basePath = Paths.get(getServletContext().getRealPath("/"));
+ if ( DamlEngine.appProps.getProperty("template_path") != null )
+ DamlEngine.templatePath = Paths.get(DamlEngine.appProps.getProperty("template_path"));
+ if ( DamlEngine.templatePath == null )
+ DamlEngine.templatePath = DamlEngine.basePath.resolve("templates");
+ } }
+ }
+
+ static abstract class RequestPath {
+ public static RequestPath parsePath(String pathInfo)
+ throws ServletException {
+ Matcher matcher;
+ if ( pathInfo == null )
+ return new NoSuchPath();
+ if ( (matcher=Pattern.compile("/(\\d{1,7})").matcher(pathInfo)).matches() ) {
+ final int number;
+ try {
+ number = Integer.parseInt(matcher.group(1));
+ } catch (NumberFormatException e) {
+ return new NoSuchPath();
+ }
+ try {
+ final Connection conn = WeblogDatabaseConnection.getConnection();
+ final PreparedStatement selSt
+ = conn.prepareStatement("SELECT id , extract(epoch from mdate) FROM entries WHERE id=?");
+ selSt.setInt(1,number);
+ final ResultSet selRes = selSt.executeQuery();
+ if ( selRes.next() ) {
+ int id = selRes.getInt(1);
+ double mdate = selRes.getDouble(2);
+ if ( id != number )
+ throw new ServletException("this cannot happen");
+ long lastModified = (long)(mdate*1000);
+ long thisLastModified;
+ try {
+ // Attempts to detect when *this* class was last modified.
+ thisLastModified = WeblogServlet.class.getResource("WeblogServlet.class").openConnection().getLastModified();
+ } catch (Exception e) {
+ thisLastModified = 0;
+ }
+ if ( thisLastModified > lastModified )
+ lastModified = thisLastModified;
+ // O'Reilly recommends not using milliseconds part:
+ lastModified = (lastModified/1000)*1000;
+ return new SingleBlogEntryPath(number, lastModified);
+ } else
+ return new NoSuchPath();
+ } catch (SQLException e) {
+ throw new ServletException(e);
+ }
+ }
+ return new NoSuchPath();
+ }
+ }
+
+ static final class NoSuchPath extends RequestPath { }
+
+ static final class SingleBlogEntryPath extends RequestPath {
+ public int number;
+ public long lastModified;
+ public SingleBlogEntryPath(int number, long lastModified) {
+ this.number = number;
+ this.lastModified = lastModified;
+ }
+ }
+
+ @Override
+ public void doGet(HttpServletRequest request,
+ HttpServletResponse response)
+ throws IOException, ServletException
+ {
+ final RequestPath rp = RequestPath.parsePath(request.getPathInfo());
+ if ( rp instanceof NoSuchPath ) {
+ response.sendError(HttpServletResponse.SC_NOT_FOUND);
+ return;
+ }
+ if ( ! (rp instanceof SingleBlogEntryPath) )
+ throw new ServletException("this cannot happen");
+ final int number = ((SingleBlogEntryPath)rp).number;
+ response.setContentType("text/html; charset=utf-8");
+ response.setCharacterEncoding("UTF-8");
+ OutputStream out = response.getOutputStream();
+ try {
+ WeblogSelect.fullProcess(new Context.WeblogSingleSelectionContext(number),
+ out);
+ } catch (Exception e) {
+ throw new ServletException("exception during WeblogSelect.fullProcess()", e);
+ }
+ }
+
+ @Override
+ public long getLastModified(HttpServletRequest request) {
+ final RequestPath rp;
+ try {
+ rp = RequestPath.parsePath(request.getPathInfo());
+ } catch (Exception e) {
+ return -1;
+ }
+ if ( rp instanceof SingleBlogEntryPath ) {
+ final long lastModified = ((SingleBlogEntryPath)rp).lastModified;
+ return lastModified;
+ }
+ return -1;
+ }
+}
diff --git a/org/madore/damlengine/WeblogSummary.java b/org/madore/damlengine/WeblogSummary.java
index 50ab143..b067987 100644
--- a/org/madore/damlengine/WeblogSummary.java
+++ b/org/madore/damlengine/WeblogSummary.java
@@ -37,7 +37,7 @@ public final class WeblogSummary {
this.entries = new HashMap<Integer,EntrySummary>();
}
- public static WeblogSummary getSummary() {
+ public static synchronized WeblogSummary getSummary() {
if ( singleton != null )
return singleton;
singleton = new WeblogSummary();