diff options
Diffstat (limited to 'org/madore/damlengine/WeblogServlet.java')
-rw-r--r-- | org/madore/damlengine/WeblogServlet.java | 158 |
1 files changed, 158 insertions, 0 deletions
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; + } +} |