Print

Print


Author: [log in to unmask]
Date: Thu Aug 20 13:02:26 2015
New Revision: 3382

Log:
Checkpoint current version of run db web app.

Added:
    java/trunk/run-webapp/
    java/trunk/run-webapp/pom.xml
    java/trunk/run-webapp/src/
    java/trunk/run-webapp/src/main/
    java/trunk/run-webapp/src/main/java/
    java/trunk/run-webapp/src/main/java/org/
    java/trunk/run-webapp/src/main/java/org/hps/
    java/trunk/run-webapp/src/main/java/org/hps/run/
    java/trunk/run-webapp/src/main/java/org/hps/run/web/
    java/trunk/run-webapp/src/main/java/org/hps/run/web/DatabaseUtilities.java
    java/trunk/run-webapp/src/main/java/org/hps/run/web/EpicsDataServlet.java
    java/trunk/run-webapp/src/main/java/org/hps/run/web/RunSummaryServlet.java
    java/trunk/run-webapp/src/main/java/org/hps/run/web/RunsServlet.java
    java/trunk/run-webapp/src/main/java/org/hps/run/web/ScalerDataServlet.java
    java/trunk/run-webapp/src/main/resources/
    java/trunk/run-webapp/src/main/webapp/
    java/trunk/run-webapp/src/main/webapp/WEB-INF/
    java/trunk/run-webapp/src/main/webapp/WEB-INF/context.xml
    java/trunk/run-webapp/src/main/webapp/WEB-INF/web.xml
    java/trunk/run-webapp/src/main/webapp/css/
    java/trunk/run-webapp/src/main/webapp/css/style.css
    java/trunk/run-webapp/src/main/webapp/html/
    java/trunk/run-webapp/src/main/webapp/html/pager.html
    java/trunk/run-webapp/src/main/webapp/html/tablesorter.html
    java/trunk/run-webapp/src/main/webapp/images/
    java/trunk/run-webapp/src/main/webapp/javascript/
    java/trunk/run-webapp/src/main/webapp/runEpics.jsp
    java/trunk/run-webapp/src/main/webapp/runScalers.jsp
    java/trunk/run-webapp/src/main/webapp/runSummary.jsp
    java/trunk/run-webapp/src/main/webapp/runTable.jsp

Added: java/trunk/run-webapp/pom.xml
 =============================================================================
--- java/trunk/run-webapp/pom.xml	(added)
+++ java/trunk/run-webapp/pom.xml	Thu Aug 20 13:02:26 2015
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>hps-run-webapp</artifactId>
+    <name>run-webapp</name>
+    <description>run web app</description>
+    <packaging>war</packaging>
+    <parent>
+        <groupId>org.hps</groupId>
+        <artifactId>hps-parent</artifactId>
+        <relativePath>../parent/pom.xml</relativePath>
+        <version>3.4.0-SNAPSHOT</version>
+    </parent>
+    <scm>
+        <url>http://java.freehep.org/svn/repos/hps/list/java/trunk/run-web/</url>
+        <connection>scm:svn:svn://svn.freehep.org/hps/java/trunk/run-web/</connection>
+        <developerConnection>scm:svn:svn://svn.freehep.org/hps/java/trunk/run-web/</developerConnection>
+    </scm>
+    <dependencies>
+        <dependency>
+            <groupId>org.hps</groupId>
+            <artifactId>hps-record-util</artifactId>
+        </dependency>
+		<dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>servlet-api</artifactId>
+            <version>2.4</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <version>5.1.28</version>
+            <scope>provided</scope>
+        </dependency>        
+    </dependencies>
+    <build>
+        <finalName>hps-run-webapp</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.tomcat.maven</groupId>
+                <artifactId>tomcat7-maven-plugin</artifactId>
+                <version>2.2</version>
+                <configuration>
+                    <url>http://localhost:8080/manager/text</url>
+                    <server>local-tomcat-server</server>
+                    <path>/hps-run-webapp</path>
+		</configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>

Added: java/trunk/run-webapp/src/main/java/org/hps/run/web/DatabaseUtilities.java
 =============================================================================
--- java/trunk/run-webapp/src/main/java/org/hps/run/web/DatabaseUtilities.java	(added)
+++ java/trunk/run-webapp/src/main/java/org/hps/run/web/DatabaseUtilities.java	Thu Aug 20 13:02:26 2015
@@ -0,0 +1,23 @@
+package org.hps.run.web;
+
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.sql.DataSource;
+
+public final class DatabaseUtilities {
+
+    private static String DATASOURCE_CONTEXT = "java:comp/env/jdbc/hps_run_db_dev";
+    
+    public static DataSource getDataSource() {
+        DataSource dataSource = null;
+        try {
+            dataSource = (DataSource) new InitialContext().lookup(DATASOURCE_CONTEXT);
+        } catch (final NamingException e) {
+            throw new RuntimeException("Error creating data source.");
+        }
+        if (dataSource == null) {
+            throw new IllegalStateException("Data source not found");
+        }
+        return dataSource;
+    }
+}

Added: java/trunk/run-webapp/src/main/java/org/hps/run/web/EpicsDataServlet.java
 =============================================================================
--- java/trunk/run-webapp/src/main/java/org/hps/run/web/EpicsDataServlet.java	(added)
+++ java/trunk/run-webapp/src/main/java/org/hps/run/web/EpicsDataServlet.java	Thu Aug 20 13:02:26 2015
@@ -0,0 +1,71 @@
+package org.hps.run.web;
+
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.List;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.sql.DataSource;
+
+import org.hps.record.epics.EpicsData;
+import org.hps.record.run.EpicsDataDao;
+import org.hps.record.run.EpicsDataDaoImpl;
+
+/**
+ * @author Jeremy McCormick, SLAC
+ */
+@SuppressWarnings("serial")
+public class EpicsDataServlet extends HttpServlet {
+
+    private final DataSource dataSource;
+
+    public EpicsDataServlet() {
+        this.dataSource = DatabaseUtilities.getDataSource();
+    }
+
+    @Override
+    public void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException,
+    IOException {
+        if (!request.getParameterMap().containsKey("run")) {
+            throw new RuntimeException("Missing required run parameter.");
+        }
+        final Integer run = Integer.parseInt(request.getParameterValues("run")[0]);
+        EpicsDataDao epicsDataDao = null;
+        Connection connection = null;
+        List<EpicsData> epicsDataList = null;
+
+        String epicsBankType = "2s";
+        if (request.getParameterMap().containsKey("epicsBankType")) {
+            epicsBankType = request.getParameter("epicsBankType");
+            if (!epicsBankType.equals("2s") && !epicsBankType.equals("20s")) {
+                throw new IllegalArgumentException("bad epics bank type: " + epicsBankType);
+            }
+        }
+
+        // List<String> variableNames = null;
+        try {
+            connection = dataSource.getConnection();
+            epicsDataDao = new EpicsDataDaoImpl(connection);
+            epicsDataList = epicsDataDao.getEpicsData(run);
+        } catch (final SQLException e) {
+            throw new IllegalStateException("Failed to setup data source connection.", e);
+        } finally {
+            if (connection != null) {
+                try {
+                    connection.close();
+                } catch (final SQLException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+        request.setAttribute("EpicsDataList", epicsDataList);
+        request.setAttribute("EpicsBankType", epicsBankType);
+        final RequestDispatcher dispatcher = this.getServletContext().getRequestDispatcher("/runEpics.jsp");
+        dispatcher.forward(request, response);
+    }
+}

Added: java/trunk/run-webapp/src/main/java/org/hps/run/web/RunSummaryServlet.java
 =============================================================================
--- java/trunk/run-webapp/src/main/java/org/hps/run/web/RunSummaryServlet.java	(added)
+++ java/trunk/run-webapp/src/main/java/org/hps/run/web/RunSummaryServlet.java	Thu Aug 20 13:02:26 2015
@@ -0,0 +1,79 @@
+package org.hps.run.web;
+
+import java.io.IOException;
+import java.sql.Connection;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.sql.DataSource;
+
+import org.hps.record.run.RunManager;
+import org.hps.record.run.RunSummary;
+
+/**
+ * @author Jeremy McCormick, SLAC
+ */
+public class RunSummaryServlet extends HttpServlet {
+
+    /**
+     * JSP target page.
+     */
+    private static final String JSP_TARGET = "/runSummary.jsp";
+
+    /**
+     * Attribute in the request which will have the run summary object.
+     */
+    private static final String RUN_SUMMARY_ATTRIBUTE = "RunSummary";
+
+    /**
+     * The data source with the database connection.
+     */
+    private final DataSource dataSource;
+
+    /**
+     * Create a new runs servlet.
+     * <p>
+     * This will initialize the data source with the db connection.
+     */
+    public RunSummaryServlet() {
+        this.dataSource = DatabaseUtilities.getDataSource();
+    }
+
+    /**
+     * Setup servlet state by loading the run summaries and then forward to the JSP page for display.
+     */
+    @Override
+    public void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException,
+            IOException {
+        if (!request.getParameterMap().containsKey("run")) {
+            throw new RuntimeException("Missing required run parameter.");
+        }
+        final Integer run = Integer.parseInt(request.getParameterValues("run")[0]);
+        final RunSummary runSummary = this.getRunSummary(run);
+        request.setAttribute(RUN_SUMMARY_ATTRIBUTE, runSummary);
+        final RequestDispatcher dispatcher = this.getServletContext().getRequestDispatcher(JSP_TARGET);
+        dispatcher.forward(request, response);
+    }
+
+    /**
+     * Get a run summary for the given run number.
+     *
+     * @param run the run number
+     * @return the run summary
+     */
+    private RunSummary getRunSummary(final Integer run) {
+        final RunManager runManager = new RunManager();
+        RunSummary runSummary = null;
+        try (Connection connection = this.dataSource.getConnection()) {
+            runManager.setConnection(connection);
+            runManager.setRun(run);
+            runSummary = runManager.getRunSummary();
+        } catch (final Exception e) {
+            throw new RuntimeException(e);
+        }
+        return runSummary;
+    }
+}

Added: java/trunk/run-webapp/src/main/java/org/hps/run/web/RunsServlet.java
 =============================================================================
--- java/trunk/run-webapp/src/main/java/org/hps/run/web/RunsServlet.java	(added)
+++ java/trunk/run-webapp/src/main/java/org/hps/run/web/RunsServlet.java	Thu Aug 20 13:02:26 2015
@@ -0,0 +1,93 @@
+package org.hps.run.web;
+
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.sql.DataSource;
+
+import org.hps.record.run.RunSummary;
+import org.hps.record.run.RunSummaryDao;
+import org.hps.record.run.RunSummaryDaoImpl;
+
+/**
+ * Loads the list of {@link org.hps.record.run.RunSummary} objects to setup state for the <code>runTable.jsp</code>
+ * page.
+ *
+ * @author Jeremy McCormick, SLAC
+ */
+@SuppressWarnings("serial")
+public final class RunsServlet extends HttpServlet {
+
+    /**
+     * The JSP page to which the servlet will forward the request.
+     */
+    private static final String JSP_TARGET = "/runTable.jsp";
+
+    /**
+     * Attribute for list of run summaries that will set on the request object.
+     */
+    private static final String RUN_SUMMARIES_ATTRIBUTE = "RunSummaries";
+
+    /**
+     * The data source with the database connection.
+     */
+    private final DataSource dataSource;
+
+    /**
+     * Create a new runs servlet.
+     * <p>
+     * This will initialize the data source with the db connection.
+     */
+    public RunsServlet() {
+        this.dataSource = DatabaseUtilities.getDataSource();
+    }
+
+    /**
+     * Setup servlet state by loading the run summaries and then forward to the JSP page for display.
+     */
+    @Override
+    public void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException,
+    IOException {
+
+        final List<RunSummary> runSummaries = this.getRunSummaries();
+        request.setAttribute(RUN_SUMMARIES_ATTRIBUTE, runSummaries);
+        final RequestDispatcher dispatcher = this.getServletContext().getRequestDispatcher(JSP_TARGET);
+        dispatcher.forward(request, response);
+    }
+
+    /**
+     * Read the full list of run summaries from the db.
+     *
+     * @return the list of run summaries
+     */
+    private List<RunSummary> getRunSummaries() {
+        List<RunSummary> runSummaries = new ArrayList<RunSummary>();
+        Connection connection = null;
+        try {
+            connection = this.dataSource.getConnection();
+            final RunSummaryDao runSummaryDao = new RunSummaryDaoImpl(connection);
+
+            // This does a shallow read of all run summaries but does not load their complex state.
+            runSummaries = runSummaryDao.getRunSummaries();
+        } catch (final SQLException e) {
+            throw new RuntimeException(e);
+        } finally {
+            if (connection != null) {
+                try {
+                    connection.close();
+                } catch (final Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+        return runSummaries;
+    }
+}

Added: java/trunk/run-webapp/src/main/java/org/hps/run/web/ScalerDataServlet.java
 =============================================================================
--- java/trunk/run-webapp/src/main/java/org/hps/run/web/ScalerDataServlet.java	(added)
+++ java/trunk/run-webapp/src/main/java/org/hps/run/web/ScalerDataServlet.java	Thu Aug 20 13:02:26 2015
@@ -0,0 +1,70 @@
+package org.hps.run.web;
+
+import java.io.IOException;
+import java.sql.Connection;
+import java.util.List;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.sql.DataSource;
+
+import org.hps.record.run.ScalerDataDao;
+import org.hps.record.run.ScalerDataDaoImpl;
+import org.hps.record.scalers.ScalerData;
+
+/**
+ * @author Jeremy McCormick, SLAC
+ */
+@SuppressWarnings("serial")
+public class ScalerDataServlet extends HttpServlet {
+
+    /**
+     * JSP target page.
+     */
+    private static final String JSP_TARGET = "/runScalers.jsp";
+
+    /**
+     * Attribute in the request which will have the run summary object.
+     */
+    private static final String SCALAR_DATA_ATTRIBUTE = "ScalerDataList";
+
+    /**
+     * The data source with the database connection.
+     */
+    private final DataSource dataSource;
+
+    /**
+     * Create a new runs servlet.
+     * <p>
+     * This will initialize the data source with the db connection.
+     */
+    public ScalerDataServlet() {
+        this.dataSource = DatabaseUtilities.getDataSource();
+    }
+
+    /**
+     * Setup servlet state by loading the run summaries and then forward to the JSP page for display.
+     */
+    @Override
+    public void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException,
+            IOException {
+        if (!request.getParameterMap().containsKey("run")) {
+            throw new RuntimeException("Missing required run parameter.");
+        }
+        final Integer run = Integer.parseInt(request.getParameterValues("run")[0]);
+        List<ScalerData> scalerDataList = null;
+        try (Connection connection = this.dataSource.getConnection()) {
+            final ScalerDataDao scalarDataDao = new ScalerDataDaoImpl(connection);
+            scalerDataList = scalarDataDao.getScalerData(run);
+        } catch (final Exception e) {
+            throw new RuntimeException(e);
+        }
+        request.setAttribute(SCALAR_DATA_ATTRIBUTE, scalerDataList);
+        final RequestDispatcher dispatcher = this.getServletContext().getRequestDispatcher(JSP_TARGET);
+        dispatcher.forward(request, response);
+    }
+
+}

Added: java/trunk/run-webapp/src/main/webapp/WEB-INF/context.xml
 =============================================================================
--- java/trunk/run-webapp/src/main/webapp/WEB-INF/context.xml	(added)
+++ java/trunk/run-webapp/src/main/webapp/WEB-INF/context.xml	Thu Aug 20 13:02:26 2015
@@ -0,0 +1,33 @@
+<Context>
+
+    <!-- maxActive: Maximum number of database connections in pool. Make sure you
+         configure your mysqld max_connections large enough to handle
+         all of your db connections. Set to -1 for no limit.
+         -->
+
+    <!-- maxIdle: Maximum number of idle database connections to retain in pool.
+         Set to -1 for no limit.  See also the DBCP documentation on this
+         and the minEvictableIdleTimeMillis configuration parameter.
+         -->
+
+    <!-- maxWait: Maximum time to wait for a database connection to become available
+         in ms, in this example 10 seconds. An Exception is thrown if
+         this timeout is exceeded.  Set to -1 to wait indefinitely.
+         -->
+
+    <!-- username and password: MySQL username and password for database connections  -->
+
+    <!-- driverClassName: Class name for the old mm.mysql JDBC driver is
+         org.gjt.mm.mysql.Driver - we recommend using Connector/J though.
+         Class name for the official MySQL Connector/J driver is com.mysql.jdbc.Driver.
+         -->
+
+    <!-- url: The JDBC connection url for connecting to your MySQL database.
+         -->
+
+  <Resource name="jdbc/hps_run_db" auth="Container" type="javax.sql.DataSource"
+               maxActive="100" maxIdle="30" maxWait="10000"
+               username="hpsuser" password="darkphoton" driverClassName="com.mysql.jdbc.Driver"
+               url="jdbc:mysql://hpsdb.jlab.org/hps_run_db"/>
+
+</Context>

Added: java/trunk/run-webapp/src/main/webapp/WEB-INF/web.xml
 =============================================================================
--- java/trunk/run-webapp/src/main/webapp/WEB-INF/web.xml	(added)
+++ java/trunk/run-webapp/src/main/webapp/WEB-INF/web.xml	Thu Aug 20 13:02:26 2015
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+
+<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
+    version="2.4">
+
+    <display-name>HPS Run Web Application</display-name>
+
+    <resource-ref>
+        <description>DB Connection</description>
+        <res-ref-name>jdbc/hps_run_db</res-ref-name>
+        <res-type>javax.sql.DataSource</res-type>
+        <res-auth>Container</res-auth>
+    </resource-ref>
+    
+    <description>
+       Application for showing information about runs of the HPS experiment. 
+    </description>
+
+    <!-- Display full run table. -->
+            
+    <servlet>
+        <servlet-name>RunsServlet</servlet-name>
+        <servlet-class>org.hps.run.web.RunsServlet</servlet-class>
+    </servlet>
+
+    <servlet-mapping>
+        <servlet-name>RunsServlet</servlet-name>
+        <url-pattern>/runs</url-pattern>
+    </servlet-mapping>
+    
+    <!-- Display a run summary. -->
+    
+    <servlet>
+        <servlet-name>RunSummaryServlet</servlet-name>
+        <servlet-class>org.hps.run.web.RunSummaryServlet</servlet-class>
+    </servlet>
+
+    <servlet-mapping>
+        <servlet-name>RunSummaryServlet</servlet-name>
+        <url-pattern>/run</url-pattern>
+    </servlet-mapping>
+    
+    <!-- Display EPICS data -->
+    
+    <servlet>
+        <servlet-name>EpicsDataServlet</servlet-name>
+        <servlet-class>org.hps.run.web.EpicsDataServlet</servlet-class>
+    </servlet>
+
+    <servlet-mapping>
+        <servlet-name>EpicsDataServlet</servlet-name>
+        <url-pattern>/epics</url-pattern>
+    </servlet-mapping>
+    
+    <!-- Display scaler data -->
+    
+    <servlet>
+        <servlet-name>ScalerDataServlet</servlet-name>
+        <servlet-class>org.hps.run.web.ScalerDataServlet</servlet-class>
+    </servlet>
+    
+    <servlet-mapping>
+        <servlet-name>ScalerDataServlet</servlet-name>
+        <url-pattern>/scalers</url-pattern>
+    </servlet-mapping>
+        
+</web-app>     

Added: java/trunk/run-webapp/src/main/webapp/css/style.css
 =============================================================================
--- java/trunk/run-webapp/src/main/webapp/css/style.css	(added)
+++ java/trunk/run-webapp/src/main/webapp/css/style.css	Thu Aug 20 13:02:26 2015
@@ -0,0 +1,7 @@
+hr { 
+    border: 0; 
+    height: 0; 
+    border-top: 1px solid rgba(0, 0, 0, 0.1); 
+    border-bottom: 1px solid 
+    rgba(255, 255, 255, 0.3);
+}

Added: java/trunk/run-webapp/src/main/webapp/html/pager.html
 =============================================================================
--- java/trunk/run-webapp/src/main/webapp/html/pager.html	(added)
+++ java/trunk/run-webapp/src/main/webapp/html/pager.html	Thu Aug 20 13:02:26 2015
@@ -0,0 +1,17 @@
+<!-- pager -->
+<div id="pager" class="pager">
+    <form>
+        <img src="http://tablesorter.com/addons/pager/icons/first.png" class="first"/> 
+        <img src="http://tablesorter.com/addons/pager/icons/prev.png" class="prev"/> 
+        <input type="text" class="pagedisplay"/>
+        <img src="http://tablesorter.com/addons/pager/icons/next.png" class="next"/> 
+        <img src="http://tablesorter.com/addons/pager/icons/last.png" class="last"/> 
+        <select class="pagesize">
+            <option selected="selected" value="10">10</option>
+            <option value="20">20</option>
+            <option value="30">30</option>
+            <option value="40">40</option>
+            <option value="50">50</option>
+        </select>
+    </form>
+</div>

Added: java/trunk/run-webapp/src/main/webapp/html/tablesorter.html
 =============================================================================
--- java/trunk/run-webapp/src/main/webapp/html/tablesorter.html	(added)
+++ java/trunk/run-webapp/src/main/webapp/html/tablesorter.html	Thu Aug 20 13:02:26 2015
@@ -0,0 +1,4 @@
+<link rel="stylesheet" href="https://mottie.github.io/tablesorter/css/theme.blue.css" />
+<!cript type="text/javascript" src="http://code.jquery.com/jquery-1.11.3.js"></script>
+<!cript type="text/javascript" src="https://mottie.github.io/tablesorter/js/jquery.tablesorter.js"></script>
+<!cript type="text/javascript" src="https://mottie.github.io/tablesorter/addons/pager/jquery.tablesorter.pager.js"></script>

Added: java/trunk/run-webapp/src/main/webapp/runEpics.jsp
 =============================================================================
--- java/trunk/run-webapp/src/main/webapp/runEpics.jsp	(added)
+++ java/trunk/run-webapp/src/main/webapp/runEpics.jsp	Thu Aug 20 13:02:26 2015
@@ -0,0 +1,103 @@
+<%@ page contentType="text/html" import="java.util.*,java.text.SimpleDateFormat,org.hps.record.epics.*"%>
+<!DOCTYPE html>
+<html>
+<link rel="stylesheet" href="css/style.css" />
+
+<!-- include links and scripts for tablesorter jquery plugin -->
+<%@include file="html/tablesorter.html"%>
+
+<!-- sort the table after doc loads -->
+<!cript>
+	$(document).ready(function() {
+		$("#epics-table").tablesorter({
+			widthFixed : true,
+			widgets : [ 'zebra' ]
+		}).tablesorterPager({
+			container : $("#pager"),
+			size : 50
+		});
+	});
+</script>
+
+<body>
+    <%
+        // Get the run number.
+        int run = Integer.parseInt(request.getParameterValues("run")[0]);
+
+        // Get the EPICS variable names.
+        String epicsBankType = (String) request.getAttribute("EpicsBankType");
+        List<String> variableNames = null;
+        if (epicsBankType.equals("2s")) {
+            variableNames = new ArrayList<String>(Epics2sVariables.getVariables().keySet());
+        } else if (epicsBankType.equals("20s")) {
+            variableNames = new ArrayList<String>(Epics20sVariables.getVariables().keySet());
+        } else {
+            throw new RuntimeException("bad EpicsBankType attribute: " + request.getAttribute("EpicsBankType"));
+        }
+
+        // Get the list of EPICS data for this run.
+        List<EpicsData> epicsDataList = (List<EpicsData>) request.getAttribute("EpicsDataList");
+    %>
+    <h1>HPS Run <%= run %> - EPICS <%= epicsBankType %> Data</h1>
+    <hr />
+
+    <!--  
+        TODO: put summary table here showing
+        
+        -number of epics data blocks
+        -(last - first timestamp) = seconds
+        -min sequence number
+        -max sequence number
+        
+        -for each variable....
+        -variable name
+        -number of occurrences
+        -mean value
+    -->
+
+    <!-- EPICS data table -->
+    <table id="epics-table" class="tablesorter-blue">
+        <thead>
+            <tr>
+                <th>Sequence</th>
+                <th>Timestamp</th>
+                <%
+                    for (String variableName : variableNames) {
+                %>
+                <th><%= variableName %></th>
+                <%
+                    }
+                %>
+            </tr>
+        </thead>
+        <tbody>
+            <%
+                for (EpicsData epicsData : epicsDataList) {
+                    if (epicsData.hasKey(variableNames.get(0))) {
+            %>
+            <tr>
+                <td><%=epicsData.getEpicsHeader().getSequence()%></td>
+                <td><%=epicsData.getEpicsHeader().getTimestamp()%></td>
+                <%
+                    for (String variableName : variableNames) {
+                %>
+                <td><%=epicsData.getValue(variableName)%></td>
+                <%
+                    }
+                %>
+            </tr>
+            <%
+                }
+            %>
+            <%
+                }
+            %>
+        
+        <tbody>
+    </table>
+
+    <!-- tablesorter paging container -->
+    <%@include file="html/pager.html"%>
+
+</body>
+</html>

Added: java/trunk/run-webapp/src/main/webapp/runScalers.jsp
 =============================================================================
--- java/trunk/run-webapp/src/main/webapp/runScalers.jsp	(added)
+++ java/trunk/run-webapp/src/main/webapp/runScalers.jsp	Thu Aug 20 13:02:26 2015
@@ -0,0 +1,71 @@
+<%@ page contentType="text/html" import="java.util.*,java.text.SimpleDateFormat,org.hps.record.scalers.*"%>
+<!DOCTYPE html>
+<html>
+<link rel="stylesheet" href="css/style.css" />
+
+<!-- include links and scripts for tablesorter jquery plugin -->
+<%@include file="html/tablesorter.html"%>
+
+<!-- sort the table after doc loads -->
+<!cript>
+    $(document).ready(function() {
+        $("#scalers-table").tablesorter({
+            widthFixed : true,
+            widgets : [ 'zebra' ]
+        }).tablesorterPager({
+            container : $("#pager"),
+            size : 50
+        });
+    });
+</script>
+
+<body>
+    <%
+        // Get the run number.
+        int run = Integer.parseInt(request.getParameterValues("run")[0]);
+
+        // Get the list of EPICS data for this run.
+        List<ScalerData> scalerDataList = (List<ScalerData>) request.getAttribute("ScalerDataList");
+    %>
+    <h1>HPS Run <%= run %> - Scaler Data</h1>
+    <hr />
+
+    <!-- scaler data table -->
+    <table id="scalers-table" class="tablesorter-blue">
+        <thead>
+            <tr>
+                <th>Event ID</th>
+                <%
+                    for (ScalerDataIndex index : ScalerDataIndex.values()) {
+                %>
+                <th><%= index.toString().replace("_", " ") %></th>
+                <%
+                    }
+                %>
+            </tr>
+        </thead>
+        <tbody>
+            <%
+                for (ScalerData scalerData : scalerDataList) {
+            %>
+            <tr>
+                <td><%= scalerData.getEventId() %>            
+                <%
+                    for (ScalerDataIndex index : ScalerDataIndex.values()) {
+                %>
+                <td><%= scalerData.getValue(index.index()) %></td>
+                <%
+                    }
+                %>
+            </tr>
+            <%
+                }
+            %>        
+        <tbody>
+    </table>
+
+    <!-- tablesorter paging container -->
+    <%@include file="html/pager.html"%>
+
+</body>
+</html>

Added: java/trunk/run-webapp/src/main/webapp/runSummary.jsp
 =============================================================================
--- java/trunk/run-webapp/src/main/webapp/runSummary.jsp	(added)
+++ java/trunk/run-webapp/src/main/webapp/runSummary.jsp	Thu Aug 20 13:02:26 2015
@@ -0,0 +1,33 @@
+<%@ page contentType="text/html" import="java.util.*,org.hps.record.run.RunSummary,java.text.SimpleDateFormat"%>
+<!DOCTYPE html>
+<html>
+<link rel="stylesheet" href="css/style.css" />
+<body>
+    <h1>HPS Run Summary</h1>
+    <hr />
+    <%
+        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
+        dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+        RunSummary runSummary = (RunSummary) request.getAttribute("RunSummary"); 
+    %>
+    <p>run: <%= runSummary.getRun() %></p>
+    <p>start: <%= dateFormat.format(runSummary.getStartDate()) %></p>
+    <p>end: <%= dateFormat.format(runSummary.getEndDate()) %></p>
+    <p>events: <%= runSummary.getTotalEvents() %></p>
+    <p>files: <%= runSummary.getTotalFiles() %></p>
+    <p>end okay: <%= runSummary.getEndOkay() %></p>
+    <p>run okay: <%= runSummary.getRunOkay() %></p>
+    <p>updated: <%= dateFormat.format(runSummary.getUpdated()) %></p>
+    <p>created: <%= dateFormat.format(runSummary.getCreated()) %></p>	
+    <hr/>	
+    <p>
+        <a href="epics?run=<%= runSummary.getRun() %>&epicsBankType=2s">EPICS 2s Data</a>        
+    </p>		
+    <p>
+        <a href="epics?run=<%= runSummary.getRun() %>&epicsBankType=20s">EPICS 20s Data</a>
+    </p>
+    <p>
+        <a href="scalers?run=<%= runSummary.getRun() %>">Scaler Data</a>
+    </p>
+</body>
+</html>

Added: java/trunk/run-webapp/src/main/webapp/runTable.jsp
 =============================================================================
--- java/trunk/run-webapp/src/main/webapp/runTable.jsp	(added)
+++ java/trunk/run-webapp/src/main/webapp/runTable.jsp	Thu Aug 20 13:02:26 2015
@@ -0,0 +1,69 @@
+<%@ page contentType="text/html" import="java.util.*,org.hps.record.run.RunSummary,java.text.SimpleDateFormat"%>
+<!DOCTYPE html>
+<html>
+
+<!-- application stylesheet -->
+<link rel="stylesheet" href="css/style.css" />
+
+<!-- include links and scripts for tablesorter jquery plugin -->
+<%@include file="html/tablesorter.html" %>
+
+<!-- sort the table after doc loads -->
+<!cript>
+    $(document).ready(function() 
+        { 
+            $("#run-table")
+            .tablesorter({widthFixed: true, widgets: ['zebra']})
+            .tablesorterPager({container: $("#pager"), size: 20});
+        }
+    );
+</script>
+
+<body>
+	<h1>HPS Run Table</h1>
+	<hr/>
+	
+	<!-- full run table with tablesorter theme, sorting and pagination -->
+	<table id="run-table" class="tablesorter-blue">
+		<thead>
+			<tr>
+				<th>Run</th>
+				<th>Start Time UTC</th>
+				<th>End Time UTC</th>
+				<th>Events</th>
+				<th>Files</th>
+				<th>End Okay</th>
+				<th>Run Okay</th>
+				<th>Updated</th>
+				<th>Created</th>
+			</tr>
+		</thead>
+		<tbody>
+		    <!-- get the list of run summaries from the request and create a table row for each one -->
+			<% 
+                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+                dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+                List<RunSummary> runSummaries = (List<RunSummary>) request.getAttribute("RunSummaries");
+                for (RunSummary runSummary : runSummaries) { 
+            %>
+            <!-- table row links to its run summary page -->
+			<tr onclick="document.location.href='run?run=<%= runSummary.getRun() %>';">
+				<td><%= runSummary.getRun() %></td>
+				<td><%= dateFormat.format(runSummary.getStartDate()) %></td>
+				<td><%= dateFormat.format(runSummary.getEndDate()) %></td>
+				<td><%= runSummary.getTotalEvents() %></td>
+				<td><%= runSummary.getTotalFiles() %></td>
+				<td><%= runSummary.getEndOkay() %></td>
+				<td><%= runSummary.getRunOkay() %></td>
+				<td><%= dateFormat.format(runSummary.getUpdated()) %></td>
+				<td><%= dateFormat.format(runSummary.getCreated()) %></td>
+			</tr>
+			<% } %>		
+		<tbody>
+	</table>
+	
+	<!-- tablesorter paging container -->
+    <%@include file="html/pager.html" %>
+    
+</body>
+</html>