summaryrefslogtreecommitdiffstats
path: root/org/madore/damlengine/WeblogServlet.java
diff options
context:
space:
mode:
Diffstat (limited to 'org/madore/damlengine/WeblogServlet.java')
-rw-r--r--org/madore/damlengine/WeblogServlet.java163
1 files changed, 163 insertions, 0 deletions
diff --git a/org/madore/damlengine/WeblogServlet.java b/org/madore/damlengine/WeblogServlet.java
new file mode 100644
index 0000000..b68f114
--- /dev/null
+++ b/org/madore/damlengine/WeblogServlet.java
@@ -0,0 +1,163 @@
+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 = 2014100902L;
+
+ @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\\.(\\d{4}-\\d{2}-\\d{2})\\.(\\d{4})\\.html").matcher(pathInfo)).matches() ) {
+ final String date;
+ final int number;
+ try {
+ date = matcher.group(1);
+ number = Integer.parseInt(matcher.group(2));
+ } 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 edate=? AND id=?");
+ selSt.setString(1,date);
+ selSt.setInt(2,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 {
+ Context.DynamicContext dc = new Context.DynamicContext();
+ dc.modTime = ((SingleBlogEntryPath)rp).lastModified;
+ 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;
+ }
+}