/* * eXist Open Source Native XML Database * Copyright (C) 2001-10 The eXist Project * http://exist-db.org * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * $Id$ */ package org.exist.management.client; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.Writer; import java.util.Properties; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.xml.transform.OutputKeys; import javax.xml.transform.TransformerException; import org.exist.util.serializer.DOMSerializer; import org.w3c.dom.Element; /** * A servlet to monitor the database. It returns status information for the database based * on the JMX interface. For simplicity, the JMX beans provided by eXist * are organized into categories. One calls the servlet with one or more * categories in parameter "c", e.g.: * * /exist/jmx?c=instances&c=memory * * If no parameter is specified, all categories will be returned. Valid * categories are "memory", "instances", "disk", "system", "caches", * "locking", "processes", "sanity", "all". * * The servlet can also be used to test if the database is responsive by * using parameter "operation=ping" and a timeout (t=timeout-in-milliseconds). * For example, the following call * * /exist/jmx?operation=ping&t=1000 * * will wait for a response within 1000ms. If the ping returns within the * specified timeout, the servlet returns the attributes of the SanityReport * JMX bean, which will include an element <jmx:Status>PING_OK</jmx:Status>. * If the ping takes longer than the timeout, you'll instead find an element * <jmx:error> in the returned XML. In this case, additional information on * running queries, memory consumption and database locks will be provided. * * @author wolf * */ public class JMXServlet extends HttpServlet { private final static Properties defaultProperties = new Properties(); static { defaultProperties.setProperty(OutputKeys.INDENT, "yes"); defaultProperties.setProperty(OutputKeys.OMIT_XML_DECLARATION, "no"); } private JMXtoXML client; public JMXServlet() { } protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { Element root = null; String operation = req.getParameter("operation"); if (operation != null && "ping".equals(operation)) { long timeout = 5000; String timeoutParam = req.getParameter("t"); if (timeoutParam != null) { try { timeout = Long.parseLong(timeoutParam); } catch (NumberFormatException e) { throw new ServletException("timeout parameter needs to be a number. Got: " + timeoutParam); } } long responseTime = client.ping("exist", timeout); if (responseTime == JMXtoXML.PING_TIMEOUT) root = client.generateXMLReport("no response on ping after " + timeout + "ms", new String[] { "sanity", "locking", "processes", "instances", "memory" }); else root = client.generateXMLReport(null, new String[] { "sanity" }); } else { String[] categories = req.getParameterValues("c"); if (categories == null) categories = new String[] { "all" }; root = client.generateXMLReport(null, categories); } resp.setContentType("application/xml"); Object useAttribute = req.getAttribute("jmx.attribute"); if (useAttribute != null) req.setAttribute(useAttribute.toString(), root); else { Writer writer = new OutputStreamWriter(resp.getOutputStream(), "UTF-8"); DOMSerializer streamer = new DOMSerializer(writer, defaultProperties); try { streamer.serialize(root); } catch (TransformerException e) { throw new ServletException("Error while serializing result: " + e.getMessage(), e); } writer.flush(); } } public void init(ServletConfig config) throws ServletException { super.init(config); client = new JMXtoXML(); client.connect(); } }