diff options
Diffstat (limited to 'org/madore/damlengine')
-rw-r--r-- | org/madore/damlengine/DamlEngine.java | 6 | ||||
-rw-r--r-- | org/madore/damlengine/WeblogDatabaseConnection.java | 84 | ||||
-rw-r--r-- | org/madore/damlengine/WeblogServlet.java | 158 | ||||
-rw-r--r-- | org/madore/damlengine/WeblogSummary.java | 2 |
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(); |