package no.priv.garshol.duke.server; import java.util.Date; import java.io.InputStream; import java.io.IOException; import java.io.PrintWriter; import java.util.Properties; import java.text.SimpleDateFormat; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import no.priv.garshol.duke.Duke; import no.priv.garshol.duke.DukeException; import no.priv.garshol.duke.utils.ObjectUtils; // we use this to make it easier to deal with properties import static no.priv.garshol.duke.utils.PropertyUtils.get; /** * Starts up Duke processing, and provides a web interface containing * some minimal information about the status of the service. */ public class StatusServlet extends HttpServlet { private SimpleDateFormat format; private static DukeController controller; private static DukeTimer timer; private int check_interval; // in seconds private static String DEFAULT_TIMER = "no.priv.garshol.duke.server.BasicTimer"; public StatusServlet() { this.format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); } public void init(ServletConfig config) throws ServletException { super.init(config); // load properties Properties props = loadPropertiesFromClassPath("duke.properties"); if (props == null) throw new DukeException("Cannot find 'duke.properties' on classpath"); check_interval = Integer.parseInt(get(props, "duke.check-interval")); // instantiate main objects this.controller = new DukeController(props); String val = get(props, "duke.timer-implementation", DEFAULT_TIMER); this.timer = (DukeTimer) ObjectUtils.instantiate(val); timer.init(props); // start thread automatically if configured to do so String autostart = get(props, "duke.autostart", "false"); if (autostart.trim().equalsIgnoreCase("true")) timer.spawnThread(controller, check_interval); } protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { if (req.getParameter("nagios") != null) { doNagios(req, resp); return; } resp.setContentType("text/html"); PrintWriter out = resp.getWriter(); out.write("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" "); out.write("\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n"); out.write("<html xmlns='http://www.w3.org/1999/xhtml'>\n"); out.write("<head>"); out.write("<title>DukeThread status</title>"); out.write("</head>"); out.write("<body>"); out.write("<h1>DukeThread status</h1>"); out.write("<table>"); out.write("<tr><td>Status: </td><td>" + controller.getStatus() + "</td></tr>"); out.write("<tr><td>Last check at: </td><td>" + format(controller.getLastCheck()) + "</td></tr>"); out.write("<tr><td>Last new record at: </td><td>" + format(controller.getLastRecord()) + "</td></tr>"); out.write("<tr><td>Records processed: </td><td>" + controller.getRecordCount() + "</td></tr>"); out.write("</table>"); out.write("<p></p><form method='post' action=''>"); if (timer.isRunning()) out.write("<input type='submit' name='stop' value='Stop'/>"); else out.write("<input type='submit' name='start' value='Start'/>"); out.write("</form>"); out.write("<p>Duke version " + Duke.getVersionString() + "</p>"); out.write("</body></html>"); } private void doNagios(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { if (controller == null) { resp.sendError(500, "No controller; Duke not running"); return; } if (controller.isErrorBlocked()) { resp.sendError(500, controller.getStatus()); return; } PrintWriter out = resp.getWriter(); out.write(controller.getStatus() + ", last check: " + format(controller.getLastCheck()) + ", last record: " + format(controller.getLastRecord()) + ", records: " + controller.getRecordCount()); } protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { if (req.getParameter("start") != null) timer.spawnThread(controller, check_interval); else timer.stop(); resp.sendRedirect(""); } private String format(long time) { return format.format(new Date(time)); } public void destroy() { try { if (controller != null) controller.close(); if (timer != null) timer.stop(); } catch (Exception e) { throw new DukeException(e); } } private static Properties loadPropertiesFromClassPath(String name) { ClassLoader cloader = Thread.currentThread().getContextClassLoader(); Properties properties = new Properties(); InputStream istream = cloader.getResourceAsStream(name); if (istream == null) return null; try { properties.load(istream); } catch (IOException e) { throw new RuntimeException(e); } return properties; } }