395574 port jetty-runner and StatisticsServlet to jetty-9

This commit is contained in:
Jan Bartel 2012-12-04 18:22:26 +11:00
parent 89e5fc93dc
commit 6bc507c3af
4 changed files with 468 additions and 257 deletions

View File

@ -80,6 +80,16 @@
<artifactId>jetty-annotations</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-jaas</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-server</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-jndi</artifactId>
@ -89,13 +99,6 @@
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-jsp</artifactId>
<version>${project.version}</version>
<exclusions>
<!-- tlds must be found in jar on path, not inside runner jar -->
<exclusion>
<groupId>org.eclipse.jetty.orbit</groupId>
<artifactId>org.apache.taglibs.standard.glassfish</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>

View File

@ -18,40 +18,33 @@
package org.eclipse.jetty.runner;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Properties;
import java.util.Random;
import javax.transaction.UserTransaction;
import org.eclipse.jetty.util.security.Constraint;
import org.eclipse.jetty.plus.jndi.Transaction;
import org.eclipse.jetty.security.ConstraintMapping;
import org.eclipse.jetty.security.ConstraintSecurityHandler;
import org.eclipse.jetty.security.HashLoginService;
import org.eclipse.jetty.security.authentication.BasicAuthenticator;
import org.eclipse.jetty.server.AbstractConnector;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.ConnectorStatistics;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.NCSARequestLog;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.server.handler.DefaultHandler;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.server.handler.RequestLogHandler;
import org.eclipse.jetty.server.handler.StatisticsHandler;
import org.eclipse.jetty.server.SelectChannelConnector;
import org.eclipse.jetty.server.session.SessionHandler;
import org.eclipse.jetty.security.ConstraintMapping;
import org.eclipse.jetty.security.ConstraintSecurityHandler;
import org.eclipse.jetty.security.HashLoginService;
import org.eclipse.jetty.security.authentication.BasicAuthenticator;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.servlet.StatisticsServlet;
@ -59,11 +52,18 @@ import org.eclipse.jetty.util.RolloverFileOutputStream;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.security.Constraint;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.xml.XmlConfiguration;
/**
* Runner
*
* Combine jetty classes into a single executable jar and run webapps based on the args to it.
*
*/
public class Runner
{
private static final Logger LOG = Log.getLogger(Runner.class);
@ -79,36 +79,99 @@ public class Runner
org.eclipse.jetty.webapp.JettyWebXmlConfiguration.class.getCanonicalName(),
org.eclipse.jetty.webapp.TagLibConfiguration.class.getCanonicalName()
};
public static final String __containerIncludeJarPattern = ".*/jetty-runner-[^/]*\\.jar$";
public static final String __defaultContextPath = "/";
public static final int __defaultPort = 8080;
protected Server _server;
protected Monitor _monitor;
protected URLClassLoader _classLoader;
protected List<URL> _classpath=new ArrayList<URL>();
protected Classpath _classpath = new Classpath();
protected ContextHandlerCollection _contexts;
protected RequestLogHandler _logHandler;
protected String _logFile;
protected String _configFile;
protected UserTransaction _ut;
protected String _utId;
protected String _txMgrPropertiesFile;
protected Random _random = new Random();
protected boolean _isTxServiceAvailable=false;
protected boolean _enableStatsGathering=false;
protected ArrayList<String> _configFiles;
protected boolean _enableStats=false;
protected String _statsPropFile;
protected boolean _clusteredSessions=true;
/**
* Classpath
*
*
*/
public class Classpath
{
private List<URL> _classpath = new ArrayList<URL>();
public void addJars (Resource lib) throws MalformedURLException, IOException
{
if (lib == null || !lib.exists())
throw new IllegalStateException ("No such lib: "+lib);
String[] list = lib.list();
if (list==null)
return;
for (String path : list)
{
if (".".equals(path) || "..".equals(path))
continue;
Resource item = lib.addPath(path);
if (item.isDirectory())
addJars(item);
else
{
if (path.toLowerCase().endsWith(".jar") ||
path.toLowerCase().endsWith(".zip"))
{
URL url = item.getURL();
_classpath.add(url);
}
}
}
}
public void addPath (Resource path)
{
if (path == null || !path.exists())
throw new IllegalStateException ("No such path: "+path);
_classpath.add(path.getURL());
}
public URL[] asArray ()
{
return _classpath.toArray(new URL[_classpath.size()]);
}
}
/**
*
*/
public Runner()
{
}
/**
* Generate helpful usage message and exit
*
* @param error
*/
public void usage(String error)
{
if (error!=null)
System.err.println("ERROR: "+error);
System.err.println("Usage: java [-DDEBUG] [-Djetty.home=dir] -jar jetty-runner.jar [--help|--version] [ server opts] [[ context opts] context ...] ");
System.err.println("Usage: java [-Djetty.home=dir] -jar jetty-runner.jar [--help|--version] [ server opts] [[ context opts] context ...] ");
System.err.println("Server Options:");
System.err.println(" --version - display version and exit");
System.err.println(" --log file - request log filename (with optional 'yyyy_mm_dd' wildcard");
@ -117,48 +180,59 @@ public class Runner
System.err.println(" --stop-port n - port to listen for stop command");
System.err.println(" --stop-key n - security string for stop command (required if --stop-port is present)");
System.err.println(" --jar file - a jar to be added to the classloader");
System.err.println(" --jdbc classname properties jndiname - classname of XADataSource or driver; properties string; name to register in jndi");
System.err.println(" --lib dir - a directory of jars to be added to the classloader");
System.err.println(" --classes dir - a directory of classes to be added to the classloader");
System.err.println(" --txFile - override properties file for Atomikos");
System.err.println(" --stats [unsecure|realm.properties] - enable stats gathering servlet context");
System.err.println(" --config file - a jetty xml config file to use instead of command line options");
System.err.println(" [--config file]*n - each --config parameter specifies the name of a jetty xml config file to apply (in the order defined)");
System.err.println("Context Options:");
System.err.println(" --path /path - context path (default /)");
System.err.println(" context - WAR file, web app dir or context.xml file");
System.err.println(" context - WAR file, web app dir or context xml file");
System.exit(1);
}
/**
* Generate version message and exit
*/
public void version ()
{
System.err.println("org.eclipse.jetty.runner.Runner: "+Server.getVersion());
System.exit(1);
}
/**
* Configure a jetty instance and deploy the webapps presented as args
*
* @param args
* @throws Exception
*/
public void configure(String[] args) throws Exception
{
// handle classpath bits first so we can initialize the log mechanism.
for (int i=0;i<args.length;i++)
{
if ("--version".equals(args[i]))
{
}
if ("--lib".equals(args[i]))
{
Resource lib = Resource.newResource(args[++i]);
if (!lib.exists() || !lib.isDirectory())
usage("No such lib directory "+lib);
expandJars(lib);
_classpath.addJars(lib);
}
else if ("--jar".equals(args[i]))
{
Resource jar = Resource.newResource(args[++i]);
if (!jar.exists() || jar.isDirectory())
usage("No such jar "+jar);
_classpath.add(jar.getURL());
_classpath.addPath(jar);
}
else if ("--classes".equals(args[i]))
{
Resource classes = Resource.newResource(args[++i]);
if (!classes.exists() || !classes.isDirectory())
usage("No such classes directory "+classes);
_classpath.add(classes.getURL());
_classpath.addPath(classes);
}
else if (args[i].startsWith("--"))
i++;
@ -166,28 +240,15 @@ public class Runner
initClassLoader();
try
{
if (Thread.currentThread().getContextClassLoader().loadClass("com.atomikos.icatch.jta.UserTransactionImp")!=null)
_isTxServiceAvailable=true;
}
catch (ClassNotFoundException e)
{
_isTxServiceAvailable=false;
}
if (System.getProperties().containsKey("DEBUG"))
Log.getLog().setDebugEnabled(true);
LOG.info("Runner");
LOG.debug("Runner classpath {}",_classpath);
String contextPath="/";
boolean contextPathSet=false;
int port=8080;
int stopPort=0;
String stopKey=null;
String contextPath = __defaultContextPath;
boolean contextPathSet = false;
int port = __defaultPort;
int stopPort = 0;
String stopKey = null;
boolean transactionManagerProcessed = false;
boolean runnerServerInitialized = false;
for (int i=0;i<args.length;i++)
@ -215,7 +276,9 @@ public class Runner
}
else if ("--config".equals(args[i]))
{
_configFile=args[++i];
if (_configFiles == null)
_configFiles = new ArrayList<String>();
_configFiles.add(args[++i]);
}
else if ("--lib".equals(args[i]))
{
@ -231,41 +294,29 @@ public class Runner
}
else if ("--stats".equals( args[i]))
{
_enableStatsGathering = true;
_enableStats = true;
_statsPropFile = args[++i];
_statsPropFile = ("unsecure".equalsIgnoreCase(_statsPropFile)?null:_statsPropFile);
}
else if ("--txFile".equals(args[i]))
{
_txMgrPropertiesFile=args[++i];
}
else if ("--jdbc".equals(args[i]))
{
i=configJDBC(args,i);
}
else // process contexts
{
if ( !transactionManagerProcessed ) // to be executed once upon starting to process contexts
{
processTransactionManagement();
transactionManagerProcessed = true;
}
if (!runnerServerInitialized) // log handlers not registered, server maybe not created, etc
{
if (_server == null) // server not initialized yet
{
// build the server
_server = new Server();
}
//apply a config file if there is one
if (_configFile != null)
//apply jetty config files if there are any
if (_configFiles != null)
{
XmlConfiguration xmlConfiguration = new XmlConfiguration(Resource.newResource(_configFile).getURL());
for (String cfg:_configFiles)
{
XmlConfiguration xmlConfiguration = new XmlConfiguration(Resource.newResource(cfg).getURL());
xmlConfiguration.configure(_server);
}
}
//check that everything got configured, and if not, make the handlers
HandlerCollection handlers = (HandlerCollection) _server.getChildHandlerByClass(HandlerCollection.class);
@ -284,14 +335,19 @@ public class Runner
}
if (_enableStatsGathering)
if (_enableStats)
{
//if no stats handler already configured
if (handlers.getChildHandlerByClass(StatisticsHandler.class) == null)
{
StatisticsHandler statsHandler = new StatisticsHandler();
prependHandler(statsHandler,handlers);
Handler oldHandler = _server.getHandler();
statsHandler.setHandler(oldHandler);
_server.setHandler(statsHandler);
ServletContextHandler statsContext = new ServletContextHandler(_contexts, "/stats");
statsContext.addServlet(new ServletHolder(new StatisticsServlet()), "/");
statsContext.setSessionHandler(new SessionHandler());
@ -335,19 +391,19 @@ public class Runner
Connector[] connectors = _server.getConnectors();
if (connectors == null || connectors.length == 0)
{
Connector connector = new SelectChannelConnector();
ServerConnector connector = new ServerConnector(_server);
connector.setPort(port);
_server.addConnector(connector);
if (_enableStatsGathering)
connector.setStatsOn(true);
if (_enableStats)
connector.addBean(new ConnectorStatistics());
}
else
{
if (_enableStatsGathering)
if (_enableStats)
{
for (int j=0; j<connectors.length; j++)
{
connectors[j].setStatsOn(true);
((AbstractConnector)connectors[j]).addBean(new ConnectorStatistics());
}
}
}
@ -360,6 +416,9 @@ public class Runner
if (!ctx.exists())
usage("Context '"+ctx+"' does not exist");
if (contextPathSet && !(contextPath.startsWith("/")))
contextPath = "/"+contextPath;
// Configure the context
if (!ctx.isDirectory() && ctx.toString().toLowerCase().endsWith(".xml"))
{
@ -367,25 +426,23 @@ public class Runner
XmlConfiguration xmlConfiguration=new XmlConfiguration(ctx.getURL());
xmlConfiguration.getIdMap().put("Server",_server);
ContextHandler handler=(ContextHandler)xmlConfiguration.configure();
_contexts.addHandler(handler);
if (contextPathSet)
handler.setContextPath(contextPath);
handler.setAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern",
".*/.*jsp-api-[^/]*\\.jar$|.*/.*jsp-[^/]*\\.jar$|.*/.*taglibs[^/]*\\.jar$");
_contexts.addHandler(handler);
handler.setAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern", __containerIncludeJarPattern);
}
else
{
// assume it is a WAR file
if (contextPathSet && !(contextPath.startsWith("/")))
contextPath = "/"+contextPath;
LOG.info("Deploying "+ctx.toString()+" @ "+contextPath);
WebAppContext webapp = new WebAppContext(_contexts,ctx.toString(),contextPath);
webapp.setConfigurationClasses(__plusConfigurationClasses);
webapp.setAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern",
".*/.*jsp-api-[^/]*\\.jar$|.*/.*jsp-[^/]*\\.jar$|.*/.*taglibs[^/]*\\.jar$");
System.err.println(Arrays.asList(_contexts.getHandlers()));
__containerIncludeJarPattern);
}
//reset
contextPathSet = false;
contextPath = __defaultContextPath;
}
}
@ -418,6 +475,10 @@ public class Runner
}
/**
* @param handler
* @param handlers
*/
protected void prependHandler (Handler handler, HandlerCollection handlers)
{
if (handler == null || handlers == null)
@ -433,71 +494,9 @@ public class Runner
protected int configJDBC(String[] args,int i) throws Exception
{
String jdbcClass=null;
String jdbcProperties=null;
String jdbcJndiName=null;
if (!_isTxServiceAvailable)
{
LOG.warn("JDBC TX support not found on classpath");
i+=3;
}
else
{
jdbcClass=args[++i];
jdbcProperties=args[++i];
jdbcJndiName=args[++i];
//check for jdbc resources to register
if (jdbcClass!=null)
{
if (isXADataSource(jdbcClass))
{
Class simpleDataSourceBeanClass = Thread.currentThread().getContextClassLoader().loadClass("com.atomikos.jdbc.SimpleDataSourceBean");
Object o = simpleDataSourceBeanClass.newInstance();
simpleDataSourceBeanClass.getMethod("setXaDataSourceClassName", new Class[] {String.class}).invoke(o, new Object[] {jdbcClass});
simpleDataSourceBeanClass.getMethod("setXaDataSourceProperties", new Class[] {String.class}).invoke(o, new Object[] {jdbcProperties});
simpleDataSourceBeanClass.getMethod("setUniqueResourceName", new Class[] {String.class}).invoke(o, new Object[] {jdbcJndiName});
org.eclipse.jetty.plus.jndi.Resource jdbcResource = new org.eclipse.jetty.plus.jndi.Resource(jdbcJndiName, o);
}
else
{
String[] props = jdbcProperties.split(";");
String user=null;
String password=null;
String url=null;
for (int j=0;props!=null && j<props.length;j++)
{
String[] pair = props[j].split("=");
if (pair!=null && pair[0].equalsIgnoreCase("user"))
user=pair[1];
else if (pair!=null && pair[0].equalsIgnoreCase("password"))
password=pair[1];
else if (pair!=null && pair[0].equalsIgnoreCase("url"))
url=pair[1];
}
Class nonXADataSourceBeanClass = Thread.currentThread().getContextClassLoader().loadClass("com.atomikos.jdbc.nonxa.NonXADataSourceBean");
Object o = nonXADataSourceBeanClass.newInstance();
nonXADataSourceBeanClass.getMethod("setDriverClassName", new Class[] {String.class}).invoke(o, new Object[] {jdbcClass});
nonXADataSourceBeanClass.getMethod("setUniqueResourceName", new Class[] {String.class}).invoke(o, new Object[] {jdbcJndiName});
nonXADataSourceBeanClass.getMethod("setUrl", new Class[] {String.class}).invoke(o, new Object[] {url});
nonXADataSourceBeanClass.getMethod("setUser", new Class[] {String.class}).invoke(o, new Object[] {user});
nonXADataSourceBeanClass.getMethod("setPassword", new Class[] {String.class}).invoke(o, new Object[] {password});
org.eclipse.jetty.plus.jndi.Resource jdbcResource = new org.eclipse.jetty.plus.jndi.Resource(jdbcJndiName, o);
}
}
}
return i;
}
/**
* @throws Exception
*/
public void run() throws Exception
{
if (_monitor != null)
@ -509,106 +508,33 @@ public class Runner
_server.join();
}
protected void expandJars(Resource lib) throws IOException
{
String[] list = lib.list();
if (list==null)
return;
for (String path : list)
{
if (".".equals(path) || "..".equals(path))
continue;
Resource item = lib.addPath(path);
if (item.isDirectory())
expandJars(item);
else
{
if (path.toLowerCase().endsWith(".jar") ||
path.toLowerCase().endsWith(".zip"))
{
URL url = item.getURL();
_classpath.add(url);
}
}
}
}
/**
* Establish a classloader with custom paths (if any)
*/
protected void initClassLoader()
{
if (_classLoader==null && _classpath!=null && _classpath.size()>0)
URL[] paths = _classpath.asArray();
if (_classLoader==null && paths !=null && paths.length > 0)
{
ClassLoader context=Thread.currentThread().getContextClassLoader();
if (context==null)
_classLoader=new URLClassLoader(_classpath.toArray(new URL[_classpath.size()]));
_classLoader=new URLClassLoader(paths);
else
_classLoader=new URLClassLoader(_classpath.toArray(new URL[_classpath.size()]),context);
_classLoader=new URLClassLoader(paths, context);
Thread.currentThread().setContextClassLoader(_classLoader);
}
}
protected boolean isXADataSource (String classname)
throws Exception
{
Class clazz = Thread.currentThread().getContextClassLoader().loadClass(classname);
boolean isXA=false;
while (!isXA && clazz!=null)
{
Class[] interfaces = clazz.getInterfaces();
for (int i=0;interfaces!=null &&!isXA && i<interfaces.length; i++)
{
if (interfaces[i].getCanonicalName().equals("javax.sql.XADataSource"))
isXA=true;
}
clazz=clazz.getSuperclass();
}
LOG.debug(isXA?"XA":"!XA");
return isXA;
}
private void processTransactionManagement() throws Exception
{
//set up a transaction manager
if (!_isTxServiceAvailable)
{
LOG.warn("No tx manager found");
}
else
{
//this invocation of jetty needs a unique random number to identify the tx manager
_utId = Integer.toHexString(_random.nextInt());
if (_txMgrPropertiesFile == null)
{
//Use system properties to config atomikos
System.setProperty("com.atomikos.icatch.no_file", "true");
//create a directory for the tx mgr log and console files to go into that will be unique
File tmpDir = new File(System.getProperty("java.io.tmpdir"));
tmpDir = new File(tmpDir, _utId);
tmpDir.mkdir();
LOG.debug("Made " + tmpDir.getAbsolutePath());
System.setProperty("com.atomikos.icatch.log_base_dir ", tmpDir.getCanonicalPath());
System.setProperty("com.atomikos.icatch.console_file_name", "tm-debug.log");
System.setProperty("com.atomikos.icatch.output_dir", tmpDir.getCanonicalPath());
System.setProperty("com.atomikos.icatch.tm_unique_name", _utId);
}
else
{
System.setProperty("com.atomikos.icatch.file", _txMgrPropertiesFile);
}
//create UserTransaction
Class utsClass = Thread.currentThread().getContextClassLoader().loadClass("com.atomikos.icatch.jta.UserTransactionImp");
//register in JNDI
Transaction txMgrResource = new Transaction((UserTransaction)utsClass.newInstance());
}
}
/**
* @param args
*/
public static void main(String[] args)
{
Runner runner = new Runner();
@ -621,13 +547,13 @@ public class Runner
}
else if (args.length>0&&args[0].equalsIgnoreCase("--version"))
{
System.err.println("org.mortbay.jetty.Runner: "+Server.getVersion());
System.exit(1);
runner.version();
}
else
{
runner.configure(args);
runner.run();
}
}
catch (Exception e)
{

View File

@ -0,0 +1,282 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.AbstractConnector;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.ConnectorStatistics;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.StatisticsHandler;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
/**
* StatisticsServlet
*
*
*/
public class StatisticsServlet extends HttpServlet
{
private static final Logger LOG = Log.getLogger(StatisticsServlet.class);
boolean _restrictToLocalhost = true; // defaults to true
private StatisticsHandler _statsHandler;
private MemoryMXBean _memoryBean;
private Connector[] _connectors;
/**
* @see javax.servlet.GenericServlet#init()
*/
public void init() throws ServletException
{
ServletContext context = getServletContext();
ContextHandler.Context scontext = (ContextHandler.Context) context;
Server _server = scontext.getContextHandler().getServer();
Handler handler = _server.getChildHandlerByClass(StatisticsHandler.class);
if (handler != null)
{
_statsHandler = (StatisticsHandler) handler;
}
else
{
LOG.warn("Statistics Handler not installed!");
return;
}
_memoryBean = ManagementFactory.getMemoryMXBean();
_connectors = _server.getConnectors();
if (getInitParameter("restrictToLocalhost") != null)
{
_restrictToLocalhost = "true".equals(getInitParameter("restrictToLocalhost"));
}
}
/**
* @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
public void doPost(HttpServletRequest sreq, HttpServletResponse sres) throws ServletException, IOException
{
doGet(sreq, sres);
}
/**
* @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
{
if (_statsHandler == null)
{
LOG.warn("Statistics Handler not installed!");
resp.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
return;
}
if (_restrictToLocalhost)
{
if (!"127.0.0.1".equals(req.getRemoteAddr()))
{
resp.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
return;
}
}
String wantXml = req.getParameter("xml");
if (wantXml == null)
wantXml = req.getParameter("XML");
if (wantXml != null && "true".equalsIgnoreCase(wantXml))
{
sendXmlResponse(resp);
}
else
{
sendTextResponse(resp);
}
}
/**
* @param response
* @throws IOException
*/
private void sendXmlResponse(HttpServletResponse response) throws IOException
{
StringBuilder sb = new StringBuilder();
sb.append("<statistics>\n");
sb.append(" <requests>\n");
sb.append(" <statsOnMs>").append(_statsHandler.getStatsOnMs()).append("</statsOnMs>\n");
sb.append(" <requests>").append(_statsHandler.getRequests()).append("</requests>\n");
sb.append(" <requestsActive>").append(_statsHandler.getRequestsActive()).append("</requestsActive>\n");
sb.append(" <requestsActiveMax>").append(_statsHandler.getRequestsActiveMax()).append("</requestsActiveMax>\n");
sb.append(" <requestsTimeTotal>").append(_statsHandler.getRequestTimeTotal()).append("</requestsTimeTotal>\n");
sb.append(" <requestsTimeMean>").append(_statsHandler.getRequestTimeMean()).append("</requestsTimeMean>\n");
sb.append(" <requestsTimeMax>").append(_statsHandler.getRequestTimeMax()).append("</requestsTimeMax>\n");
sb.append(" <requestsTimeStdDev>").append(_statsHandler.getRequestTimeStdDev()).append("</requestsTimeStdDev>\n");
sb.append(" <dispatched>").append(_statsHandler.getDispatched()).append("</dispatched>\n");
sb.append(" <dispatchedActive>").append(_statsHandler.getDispatchedActive()).append("</dispatchedActive>\n");
sb.append(" <dispatchedActiveMax>").append(_statsHandler.getDispatchedActiveMax()).append("</dispatchedActiveMax>\n");
sb.append(" <dispatchedTimeTotalMs>").append(_statsHandler.getDispatchedTimeTotal()).append("</dispatchedTimeTotalMs>\n");
sb.append(" <dispatchedTimeMeanMs>").append(_statsHandler.getDispatchedTimeMean()).append("</dispatchedTimeMeanMs>\n");
sb.append(" <dispatchedTimeMaxMs>").append(_statsHandler.getDispatchedTimeMax()).append("</dispatchedTimeMaxMs>\n");
sb.append(" <dispatchedTimeStdDevMs>").append(_statsHandler.getDispatchedTimeStdDev()).append("</dispatchedTimeStdDevMs>\n");
sb.append(" <asyncRequests>").append(_statsHandler.getAsyncRequests()).append("</asyncRequests>\n");
sb.append(" <requestsSuspended>").append(_statsHandler.getAsyncRequestsWaiting()).append("</requestsSuspended>\n");
sb.append(" <requestsSuspendedMax>").append(_statsHandler.getAsyncRequestsWaitingMax()).append("</requestsSuspendedMax>\n");
sb.append(" <requestsResumed>").append(_statsHandler.getAsyncDispatches()).append("</requestsResumed>\n");
sb.append(" <requestsExpired>").append(_statsHandler.getExpires()).append("</requestsExpired>\n");
sb.append(" </requests>\n");
sb.append(" <responses>\n");
sb.append(" <responses1xx>").append(_statsHandler.getResponses1xx()).append("</responses1xx>\n");
sb.append(" <responses2xx>").append(_statsHandler.getResponses2xx()).append("</responses2xx>\n");
sb.append(" <responses3xx>").append(_statsHandler.getResponses3xx()).append("</responses3xx>\n");
sb.append(" <responses4xx>").append(_statsHandler.getResponses4xx()).append("</responses4xx>\n");
sb.append(" <responses5xx>").append(_statsHandler.getResponses5xx()).append("</responses5xx>\n");
sb.append(" <responsesBytesTotal>").append(_statsHandler.getResponsesBytesTotal()).append("</responsesBytesTotal>\n");
sb.append(" </responses>\n");
sb.append(" <connections>\n");
for (Connector connector : _connectors)
{
sb.append(" <connector>\n");
sb.append(" <name>").append(connector.getClass().getName()).append("@").append(connector.hashCode()).append("</name>\n");
sb.append(" <protocols>\n");
for (String protocol:connector.getProtocols())
sb.append(" <protocol>").append(protocol).append("</protocol>\n");
sb.append(" </protocols>\n");
ConnectorStatistics connectorStats = null;
if (connector instanceof AbstractConnector)
connectorStats = ((AbstractConnector)connector).getBean(ConnectorStatistics.class);
if (connectorStats == null)
sb.append(" <statsOn>false</statsOn>\n");
else
{
sb.append(" <statsOn>true</statsOn>\n");
sb.append(" <connections>").append(connectorStats.getConnections()).append("</connections>\n");
sb.append(" <connectionsOpen>").append(connectorStats.getConnectionsOpen()).append("</connectionsOpen>\n");
sb.append(" <connectionsOpenMax>").append(connectorStats.getConnectionsOpenMax()).append("</connectionsOpenMax>\n");
sb.append(" <connectionsDurationTotal>").append(connectorStats.getConnectionsDurationTotal()).append("</connectionsDurationTotal>\n");
sb.append(" <connectionsDurationMean>").append(connectorStats.getConnectionsDurationMean()).append("</connectionsDurationMean>\n");
sb.append(" <connectionsDurationMax>").append(connectorStats.getConnectionsDurationMax()).append("</connectionsDurationMax>\n");
sb.append(" <connectionsDurationStdDev>").append(connectorStats.getConnectionsDurationStdDev()).append("</connectionsDurationStdDev>\n");
sb.append(" <messagesIn>").append(connectorStats.getMessagesIn()).append("</messagesIn>\n");
sb.append(" <messagesOut>").append(connectorStats.getMessagesIn()).append("</messagesOut>\n");
sb.append(" <elapsedMs>").append(connectorStats.getStartedMillis()).append("</elapsedMs>\n");
}
sb.append(" </connector>\n");
}
sb.append(" </connections>\n");
sb.append(" <memory>\n");
sb.append(" <heapMemoryUsage>").append(_memoryBean.getHeapMemoryUsage().getUsed()).append("</heapMemoryUsage>\n");
sb.append(" <nonHeapMemoryUsage>").append(_memoryBean.getNonHeapMemoryUsage().getUsed()).append("</nonHeapMemoryUsage>\n");
sb.append(" </memory>\n");
sb.append("</statistics>\n");
response.setContentType("text/xml");
PrintWriter pout = response.getWriter();
pout.write(sb.toString());
}
/**
* @param response
* @throws IOException
*/
private void sendTextResponse(HttpServletResponse response) throws IOException
{
StringBuilder sb = new StringBuilder();
sb.append(_statsHandler.toStatsHTML());
sb.append("<h2>Connections:</h2>\n");
for (Connector connector : _connectors)
{
sb.append("<h3>").append(connector.getClass().getName()).append("@").append(connector.hashCode()).append("</h3>");
sb.append("Protocols:");
for (String protocol:connector.getProtocols())
sb.append(protocol).append("&nbsp;");
sb.append(" <br />\n");
ConnectorStatistics connectorStats = null;
if (connector instanceof AbstractConnector)
connectorStats = ((AbstractConnector)connector).getBean(ConnectorStatistics.class);
if (connectorStats != null)
{
sb.append("Statistics gathering started ").append(connectorStats.getStartedMillis()).append("ms ago").append("<br />\n");
sb.append("Total connections: ").append(connectorStats.getConnections()).append("<br />\n");
sb.append("Current connections open: ").append(connectorStats.getConnectionsOpen()).append("<br />\n");;
sb.append("Max concurrent connections open: ").append(connectorStats.getConnectionsOpenMax()).append("<br />\n");
sb.append("Total connections duration: ").append(connectorStats.getConnectionsDurationTotal()).append("<br />\n");
sb.append("Mean connection duration: ").append(connectorStats.getConnectionsDurationMean()).append("<br />\n");
sb.append("Max connection duration: ").append(connectorStats.getConnectionsDurationMax()).append("<br />\n");
sb.append("Connection duration standard deviation: ").append(connectorStats.getConnectionsDurationStdDev()).append("<br />\n");
sb.append("Total messages in: ").append(connectorStats.getMessagesIn()).append("<br />\n");
sb.append("Total messages out: ").append(connectorStats.getMessagesOut()).append("<br />\n");
}
else
{
sb.append("Statistics gathering off.\n");
}
}
sb.append("<h2>Memory:</h2>\n");
sb.append("Heap memory usage: ").append(_memoryBean.getHeapMemoryUsage().getUsed()).append(" bytes").append("<br />\n");
sb.append("Non-heap memory usage: ").append(_memoryBean.getNonHeapMemoryUsage().getUsed()).append(" bytes").append("<br />\n");
response.setContentType("text/html");
PrintWriter pout = response.getWriter();
pout.write(sb.toString());
}
}

View File

@ -414,11 +414,11 @@
<module>tests</module>
<module>aggregates/jetty-all</module>
<module>jetty-distribution</module>
<module>jetty-runner</module>
<!-- modules that need fixed and added back, or simply dropped and not maintained
<module>tests</module>
<module>jetty-runner</module>
<module>jetty-rhttp</module>
<module>jetty-http-spi</module>
-->