/* Copyright (c) 2008-2009 HomeAway, Inc. * All rights reserved. http://www.perf4j.org * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.perf4j.servlet; import org.perf4j.chart.StatisticsChartGenerator; import org.perf4j.helpers.MiscUtils; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Arrays; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; /** * This servlet class serves as the base class for displaying performance charts in a web environment. This class sets * up the framework for sending the HTML response. Subclasses are only responsible for determining how to find the * graphs to display by implementing the <tt>getGraphByName</tt> and <tt>getAllKnownGraphNames</tt> methods. * * @author Alex Devine */ public abstract class AbstractGraphingServlet extends HttpServlet { private static final long serialVersionUID = 7877125631806499443L; /** * Setting an init parameter "graphNames" to a comma-separated list of the names of graphs to display by default * sets this member variable. Subclass implementations determine how graphs are named. For example, the * {@link org.perf4j.log4j.servlet.GraphingServlet} uses the names of * {@link org.perf4j.log4j.GraphingStatisticsAppender}s to determine which graphs to show. */ protected List<String> graphNames; public void init() throws ServletException { String graphNamesString = getInitParameter("graphNames"); if (graphNamesString != null) { graphNames = Arrays.asList(MiscUtils.splitAndTrim(graphNamesString, ",")); } } public void destroy() { graphNames = null; } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Map<String, StatisticsChartGenerator> chartsByName = getChartGeneratorsToDisplay(request); response.setContentType("text/html;charset=utf-8"); writeHeader(request, response); for (Map.Entry<String, StatisticsChartGenerator> nameAndChart : chartsByName.entrySet()) { writeChart(nameAndChart.getKey(), nameAndChart.getValue(), request, response); } writeFooter(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } /** * Helper method writes the HTML header, everything up to the opening body tag. Subclasses may wish to override. */ protected void writeHeader(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.getWriter().println("<html>"); response.getWriter().println("<head>"); response.getWriter().println("<title>Perf4J Performance Graphs</title>"); if (request.getParameter("refreshRate") != null) { int refreshRate = Integer.parseInt(request.getParameter("refreshRate")); response.getWriter().println("<meta http-equiv=\"refresh\" content=\"" + refreshRate + "\">"); } response.getWriter().println("<head>"); response.getWriter().println("<body>"); } /** * Helper method writes the chart to the page using an img tag. Subclasses may wish to override. * * @param name the name of the chart to write * @param chartGenerator the chart generator responsible for creating the chart URL * @param request the incoming servlet request * @param response the servlet respone */ protected void writeChart(String name, StatisticsChartGenerator chartGenerator, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.getWriter().println("<br><br>"); String chartUrl = (chartGenerator == null) ? null : chartGenerator.getChartUrl(); if (chartUrl != null) { response.getWriter().println("<b>" + name + "</b><br>"); response.getWriter().println("<img src=\"" + chartUrl + "\">"); } else { response.getWriter().println("<b>Unknown graph name: " + name + "</b><br>"); } } /** * Helper method writes the HTML footer, closing the body and HTML tags. Subclasses may wish to override. */ protected void writeFooter(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.getWriter().println("</body>"); response.getWriter().println("</html>"); response.getWriter().flush(); } /** * Helper method generates the list of charts that are to be displayed in this call to the servlet. In general * subclasses should not need to override this method. * * @param request The incoming request, which may contain a list of "graphName" parameters, in which case those * graphs will be displayed * @return A map of graph name to the chart generator capable of creating the URL for the graph. */ protected Map<String, StatisticsChartGenerator> getChartGeneratorsToDisplay(HttpServletRequest request) { // find the names of the graphs to be displayed List<String> graphsToDisplay; if (request.getParameter("graphName") != null) { // option 1 - passed in on the request graphsToDisplay = Arrays.asList(request.getParameterValues("graphName")); } else if (graphNames != null) { // option 2 - specified as an init parameter graphsToDisplay = graphNames; } else { // option 3 - no graphs specified, return all known graphs graphsToDisplay = getAllKnownGraphNames(); } Map<String, StatisticsChartGenerator> retVal = new LinkedHashMap<String, StatisticsChartGenerator>(); for (String graphName : graphsToDisplay) { retVal.put(graphName, getGraphByName(graphName)); } return retVal; } /** * Subclasses should implement this method to return a chart generator by its name. Subclasses may use any method * necessary to find the underlying repository of charts. * * @param name the name of the graph to return * @return the chart generator capable of creating the requested chart. */ protected abstract StatisticsChartGenerator getGraphByName(String name); /** * Subclasses should implement this method to return a list of all possible known graph names. * * @return The list of possible graph names for which <tt>getGraphByName</tt> will return a valid chart generator. */ protected abstract List<String> getAllKnownGraphNames(); }