/*
* Sun Public License
*
* The contents of this file are subject to the Sun Public License Version
* 1.0 (the "License"). You may not use this file except in compliance with
* the License. A copy of the License is available at http://www.sun.com/
*
* The Original Code is the SLAMD Distributed Load Generation Engine.
* The Initial Developer of the Original Code is Neil A. Wilson.
* Portions created by Neil A. Wilson are Copyright (C) 2004-2010.
* Some preexisting portions Copyright (C) 2002-2006 Sun Microsystems, Inc.
* All Rights Reserved.
*
* Contributor(s): Neil A. Wilson
*/
package com.slamd.admin;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import com.slamd.asn1.ASN1Element;
import com.slamd.common.Constants;
import com.slamd.job.JobClass;
import static com.slamd.admin.AdminServlet.*;
import static com.slamd.admin.AdminUI.*;
/**
* This class provides a set of methods for providing debug access to the
* administrative interface.
*/
public class AdminDebug
{
/**
* Handles the work of generating debug information about all thread groups
* and threads defined in the JVM.
*
* @param requestInfo The state information for this request.
*/
static void handleDebugThreads(RequestInfo requestInfo)
{
logMessage(requestInfo, "In handleDebugThreads()");
// The user must have full administrative rights to see anything here.
if (! requestInfo.hasFullAccess)
{
logMessage(requestInfo, "No hasFullAccess permission granted");
generateAccessDeniedBody(requestInfo, "You do not have permission to " +
"view debug information.");
return;
}
// Get the important state variables for this request.
StringBuilder htmlBody = requestInfo.htmlBody;
// Find the root thread group for the JVM.
ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
ThreadGroup parentGroup = threadGroup.getParent();
while (parentGroup != null)
{
threadGroup = parentGroup;
parentGroup = threadGroup.getParent();
}
// Next, get all the threads defined in the JVM.
int numThreads = threadGroup.activeCount();
Thread[] activeThreads = new Thread[numThreads];
threadGroup.enumerate(activeThreads);
// Display all this information to the user.
htmlBody.append("<SPAN CLASS=\"" + Constants.STYLE_MAIN_HEADER +
"\">JVM Thread Debug Information</SPAN>" + EOL);
htmlBody.append("<BR><BR>" + EOL);
htmlBody.append("The following threads are currently defined in the JVM:" +
EOL);
htmlBody.append("<TABLE BORDER=\"1\">" + EOL);
htmlBody.append(" <TR>" + EOL);
htmlBody.append(" <TD><B>Thread Group</B></TD>" + EOL);
htmlBody.append(" <TD><B>Thread Name</B></TD>" + EOL);
htmlBody.append(" <TD><B>Priority</B></TD>" + EOL);
htmlBody.append(" <TD><B>Is Alive</B></TD>" + EOL);
htmlBody.append(" <TD><B>Is Interrupted</B></TD>" + EOL);
htmlBody.append(" <TD><B>Is Daemon</B></TD>" + EOL);
htmlBody.append(" </TR>" + EOL);
for (int i=0; i < numThreads; i++)
{
if (activeThreads[i] == null)
{
continue;
}
ThreadGroup group = activeThreads[i].getThreadGroup();
String groupName = (group == null) ? "N/A" : group.getName();
htmlBody.append(" <TR>" + EOL);
htmlBody.append(" <TD>" + groupName + "</TD>" + EOL);
htmlBody.append(" <TD>" + activeThreads[i].getName() + "</TD>" + EOL);
htmlBody.append(" <TD>" + activeThreads[i].getPriority() + "</TD>" +
EOL);
htmlBody.append(" <TD>" + activeThreads[i].isAlive() + "</TD>" + EOL);
htmlBody.append(" <TD>" + activeThreads[i].isInterrupted() + "</TD>" +
EOL);
htmlBody.append(" <TD>" + activeThreads[i].isDaemon() + "</TD>" + EOL);
htmlBody.append(" </TR>" + EOL);
}
htmlBody.append("</TABLE>" + EOL);
}
/**
* Handles the work of generating debug information including a full stack
* trace for all threads in the JVM.
*
* @param requestInfo The state information for this request.
*/
static void handleDebugStackTrace(RequestInfo requestInfo)
{
logMessage(requestInfo, "In handleDebugStackTrace()");
// The user must have full administrative rights to see anything here.
if (! requestInfo.hasFullAccess)
{
logMessage(requestInfo, "No hasFullAccess permission granted");
generateAccessDeniedBody(requestInfo, "You do not have permission to " +
"view debug information.");
return;
}
// Get the important state variables for this request.
StringBuilder htmlBody = requestInfo.htmlBody;
StringBuilder infoMessage = requestInfo.infoMessage;
Map threadMap = null;
try
{
Class<?> threadClass = Constants.classForName("java.lang.Thread");
Method stackTracesMethod = threadClass.getMethod("getAllStackTraces");
threadMap = (Map) stackTracesMethod.invoke(null);
htmlBody.append("<SPAN CLASS=\"" + Constants.STYLE_MAIN_HEADER +
"\">SLAMD Server JVM Stack Trace</SPAN>" + EOL);
htmlBody.append("<BR><BR>" + EOL);
Iterator iterator = threadMap.entrySet().iterator();
while (iterator.hasNext())
{
Map.Entry entry = (Map.Entry) iterator.next();
Thread thread = (Thread) entry.getKey();
StackTraceElement[] stack = (StackTraceElement[]) entry.getValue();
htmlBody.append("Thread \"" + thread.getName() + "\" Stack:" + EOL);
htmlBody.append("<PRE>" + EOL);
for (int i=0; i < stack.length; i++)
{
htmlBody.append(" " + stack[i].getClassName() + '.' +
stack[i].getMethodName() + '(');
if (stack[i].isNativeMethod())
{
htmlBody.append("native method");
}
else
{
htmlBody.append(stack[i].getFileName() + ':' +
stack[i].getLineNumber());
}
htmlBody.append(')' + EOL);
}
htmlBody.append("</PRE>" + EOL);
if (iterator.hasNext())
{
htmlBody.append("<BR><HR><BR>" + EOL);
}
}
}
catch (Exception e)
{
infoMessage.append("Stack trace information is not available.<BR>" + EOL);
htmlBody.append("<BR><BR>" + EOL);
htmlBody.append("An error occurred that prevented the thread " +
"stack trace information from being retrieved: " +
e + EOL);
htmlBody.append("<BR><BR>" + EOL);
htmlBody.append("Note that this capability is only allowed for Java 5 " +
"and higher versions of the JVM." + EOL);
return;
}
}
/**
* Handles the work of generating debug information about all system
* properties defined in the JVM.
*
* @param requestInfo The state information for this request.
*/
static void handleDebugSystemProperties(RequestInfo requestInfo)
{
logMessage(requestInfo, "In handleDebugSystemProperties()");
// The user must have full administrative rights to see anything here.
if (! requestInfo.hasFullAccess)
{
logMessage(requestInfo, "No hasFullAccess permission granted");
generateAccessDeniedBody(requestInfo, "You do not have permission to " +
"view debug information.");
return;
}
// Get the important state variables for this request.
StringBuilder htmlBody = requestInfo.htmlBody;
// Get the set of system properties defined in the JVM.
Properties systemProperties = System.getProperties();
Enumeration propertyNames = systemProperties.propertyNames();
// Display this information to the user.
htmlBody.append("<SPAN CLASS=\"" + Constants.STYLE_MAIN_HEADER +
"\">JVM System Properties Debug Information</SPAN>" + EOL);
htmlBody.append("<BR><BR>" + EOL);
htmlBody.append("The following system properties are currently defined " +
"in the JVM:" + EOL);
htmlBody.append("<TABLE BORDER=\"1\">" + EOL);
htmlBody.append(" <TR>" + EOL);
htmlBody.append(" <TD><B>Property Name</B></TD>" + EOL);
htmlBody.append(" <TD><B>Property Value</B></TD>" + EOL);
htmlBody.append(" </TR>" + EOL);
while (propertyNames.hasMoreElements())
{
String name = (String) propertyNames.nextElement();
String value = System.getProperty(name, " ");
htmlBody.append(" <TR>" + EOL);
htmlBody.append(" <TD>" + name + "</TD>" + EOL);
htmlBody.append(" <TD>" + value + "</TD>" + EOL);
htmlBody.append(" </TR>" + EOL);
}
htmlBody.append("</TABLE>" + EOL);
}
/**
* Handles the work of generating debug information about the request
* information provided by the client.
*
* @param requestInfo The state information for this request.
*/
static void handleDebugRequest(RequestInfo requestInfo)
{
logMessage(requestInfo, "In handleDebugRequest()");
// The user must have full administrative rights to see anything here.
if (! requestInfo.hasFullAccess)
{
logMessage(requestInfo, "No hasFullAccess permission granted");
generateAccessDeniedBody(requestInfo, "You do not have permission to " +
"view debug information.");
return;
}
// Get the important state variables for this request.
HttpServletRequest request = requestInfo.request;
StringBuilder htmlBody = requestInfo.htmlBody;
// Display information about the request to the user.
htmlBody.append("<SPAN CLASS=\"" + Constants.STYLE_MAIN_HEADER +
"\">Servlet Request Information</SPAN>" + EOL);
htmlBody.append("<BR><BR>" + EOL);
htmlBody.append("The following information is available about the " +
"request sent to SLAMD:" + EOL);
// General request information.
htmlBody.append("<BR><BR>");
htmlBody.append("<SPAN CLASS=\"" + Constants.STYLE_MAIN_HEADER +
"\">General Request Information</SPAN>" + EOL);
htmlBody.append("<TABLE BORDER=\"1\">" + EOL);
htmlBody.append(" <TR>" + EOL);
htmlBody.append(" <TD>Request URL</TD>" + EOL);
htmlBody.append(" <TD>" + request.getRequestURL() + "</TD>" + EOL);
htmlBody.append(" </TR>" + EOL);
htmlBody.append(" <TR>" + EOL);
htmlBody.append(" <TD>Request Method</TD>" + EOL);
htmlBody.append(" <TD>" + request.getMethod() + "</TD>" + EOL);
htmlBody.append(" </TR>" + EOL);
htmlBody.append(" <TR>" + EOL);
htmlBody.append(" <TD>Request Protocol</TD>" + EOL);
htmlBody.append(" <TD>" + request.getProtocol() + "</TD>" + EOL);
htmlBody.append(" </TR>" + EOL);
htmlBody.append(" <TR>" + EOL);
htmlBody.append(" <TD>Authentication Type</TD>" + EOL);
htmlBody.append(" <TD>" + request.getAuthType() + "</TD>" + EOL);
htmlBody.append(" </TR>" + EOL);
htmlBody.append(" <TR>" + EOL);
htmlBody.append(" <TD>Remote User</TD>" + EOL);
htmlBody.append(" <TD>" + request.getRemoteUser() + "</TD>" + EOL);
htmlBody.append(" </TR>" + EOL);
htmlBody.append(" <TR>" + EOL);
htmlBody.append(" <TD>Remote Host</TD>" + EOL);
htmlBody.append(" <TD>" + request.getRemoteHost() + "</TD>" + EOL);
htmlBody.append(" </TR>" + EOL);
htmlBody.append(" <TR>" + EOL);
htmlBody.append(" <TD>Server Host</TD>" + EOL);
htmlBody.append(" <TD>" + request.getServerName() + "</TD>" + EOL);
htmlBody.append(" </TR>" + EOL);
htmlBody.append(" <TR>" + EOL);
htmlBody.append(" <TD>Server Port</TD>" + EOL);
htmlBody.append(" <TD>" + request.getServerPort() + "</TD>" + EOL);
htmlBody.append(" </TR>" + EOL);
htmlBody.append(" <TR>" + EOL);
htmlBody.append(" <TD>Content Type</TD>" + EOL);
htmlBody.append(" <TD>" + request.getContentType() + "</TD>" + EOL);
htmlBody.append(" </TR>" + EOL);
htmlBody.append(" <TR>" + EOL);
htmlBody.append(" <TD>Content Length</TD>" + EOL);
htmlBody.append(" <TD>" + request.getContentLength() + "</TD>" + EOL);
htmlBody.append(" </TR>" + EOL);
htmlBody.append(" <TR>" + EOL);
htmlBody.append(" <TD>Character Encoding</TD>" + EOL);
htmlBody.append(" <TD>" + request.getCharacterEncoding() + "</TD>" +
EOL);
htmlBody.append(" </TR>" + EOL);
htmlBody.append("</TABLE>" + EOL);
// Request header information.
htmlBody.append("<BR><BR>");
htmlBody.append("<SPAN CLASS=\"" + Constants.STYLE_MAIN_HEADER +
"\">Request Headers</SPAN>" + EOL);
htmlBody.append("<TABLE BORDER=\"1\">" + EOL);
htmlBody.append(" <TR>" + EOL);
htmlBody.append(" <TD><B>Header Name</B></TD>" + EOL);
htmlBody.append(" <TD><B>Header Value</B></TD>" + EOL);
htmlBody.append(" </TR>" + EOL);
Enumeration headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements())
{
String name = (String) headerNames.nextElement();
Enumeration values = request.getHeaders(name);
if ((values != null) && (values.hasMoreElements()))
{
while (values.hasMoreElements())
{
String value = (String) values.nextElement();
htmlBody.append(" <TR>" + EOL);
htmlBody.append(" <TD>" + name + "</TD>" + EOL);
htmlBody.append(" <TD>" + value + "</TD>" + EOL);
htmlBody.append(" </TR>" + EOL);
}
}
else
{
htmlBody.append(" <TR>" + EOL);
htmlBody.append(" <TD>" + name + "</TD>" + EOL);
htmlBody.append(" <TD>N/A</TD>" + EOL);
htmlBody.append(" </TR>" + EOL);
}
}
htmlBody.append("</TABLE>" + EOL);
// Request parameter information.
htmlBody.append("<BR><BR>");
htmlBody.append("<SPAN CLASS=\"" + Constants.STYLE_MAIN_HEADER +
"\">Request Parameters</SPAN>" + EOL);
htmlBody.append("<TABLE BORDER=\"1\">" + EOL);
htmlBody.append(" <TR>" + EOL);
htmlBody.append(" <TD><B>Parameter Name</B></TD>" + EOL);
htmlBody.append(" <TD><B>Parameter Value</B></TD>" + EOL);
htmlBody.append(" </TR>" + EOL);
Enumeration parameterNames = request.getParameterNames();
while (parameterNames.hasMoreElements())
{
String name = (String) parameterNames.nextElement();
String[] values = request.getParameterValues(name);
if ((values == null) || (values.length == 0))
{
htmlBody.append(" <TR>" + EOL);
htmlBody.append(" <TD>" + name + "</TD>" + EOL);
htmlBody.append(" <TD>N/A</TD>" + EOL);
htmlBody.append(" </TR>" + EOL);
}
else
{
for (int i=0; i < values.length; i++)
{
htmlBody.append(" <TR>" + EOL);
htmlBody.append(" <TD>" + name + "</TD>" + EOL);
htmlBody.append(" <TD>" + values[i] + "</TD>" + EOL);
htmlBody.append(" </TR>" + EOL);
}
}
}
htmlBody.append("</TABLE>" + EOL);
// Request attribute information.
htmlBody.append("<BR><BR>");
htmlBody.append("<SPAN CLASS=\"" + Constants.STYLE_MAIN_HEADER +
"\">Request Attributes</SPAN>" + EOL);
htmlBody.append("<TABLE BORDER=\"1\">" + EOL);
htmlBody.append(" <TR>" + EOL);
htmlBody.append(" <TD><B>Attribute Name</B></TD>" + EOL);
htmlBody.append(" <TD><B>Attribute Type</B></TD>" + EOL);
htmlBody.append(" <TD><B>String Representation</B></TD>" + EOL);
htmlBody.append(" </TR>" + EOL);
Enumeration attributeNames = request.getAttributeNames();
while (attributeNames.hasMoreElements())
{
String name = (String) attributeNames.nextElement();
Object value = request.getAttribute(name);
if (value == null)
{
htmlBody.append(" <TR>" + EOL);
htmlBody.append(" <TD>" + name + "</TD>" + EOL);
htmlBody.append(" <TD>N/A</TD>" + EOL);
htmlBody.append(" <TD>N/A</TD>" + EOL);
htmlBody.append(" </TR>" + EOL);
}
else
{
htmlBody.append(" <TR>" + EOL);
htmlBody.append(" <TD>" + name + "</TD>" + EOL);
htmlBody.append(" <TD>" + value.getClass().getName() + "</TD>" +
EOL);
htmlBody.append(" <TD>" + value.toString() + "</TD>" + EOL);
htmlBody.append(" </TR>" + EOL);
}
}
htmlBody.append("</TABLE>" + EOL);
// Request cookie information.
htmlBody.append("<BR><BR>");
htmlBody.append("<SPAN CLASS=\"" + Constants.STYLE_MAIN_HEADER +
"\">Request Cookies</SPAN>" + EOL);
htmlBody.append("<TABLE BORDER=\"1\">" + EOL);
htmlBody.append(" <TR>" + EOL);
htmlBody.append(" <TD><B>Cookie Name</B></TD>" + EOL);
htmlBody.append(" <TD><B>Cookie Domain</B></TD>" + EOL);
htmlBody.append(" <TD><B>Cookie Path</B></TD>" + EOL);
htmlBody.append(" <TD><B>Cookie Max Age</B></TD>" + EOL);
htmlBody.append(" <TD><B>Cookie Version</B></TD>" + EOL);
htmlBody.append(" <TD><B>Is Secure</B></TD>" + EOL);
htmlBody.append(" <TD><B>Cookie Value</B></TD>" + EOL);
htmlBody.append(" <TD><B>Cookie Comment</B></TD>" + EOL);
htmlBody.append(" </TR>" + EOL);
Cookie[] cookies = request.getCookies();
for (int i=0; ((cookies != null) && (i < cookies.length)); i++)
{
htmlBody.append(" <TR>" + EOL);
htmlBody.append(" <TD>" + cookies[i].getName() + "</TD>" + EOL);
htmlBody.append(" <TD>" + cookies[i].getDomain() + "</TD>" + EOL);
htmlBody.append(" <TD>" + cookies[i].getPath() + "</TD>" + EOL);
htmlBody.append(" <TD>" + cookies[i].getVersion() + "</TD>" + EOL);
htmlBody.append(" <TD>" + cookies[i].getMaxAge() + "</TD>" + EOL);
htmlBody.append(" <TD>" + cookies[i].getSecure() + "</TD>" + EOL);
htmlBody.append(" <TD>" + cookies[i].getValue() + "</TD>" + EOL);
htmlBody.append(" <TD>" + cookies[i].getComment() + "</TD>" + EOL);
htmlBody.append(" </TR>" + EOL);
}
htmlBody.append("</TABLE>" + EOL);
}
/**
* Handles the work of displaying debug information from the SLAMD
* configuration database.
*
* @param requestInfo The state information for this request.
*/
static void handleDebugDatabase(RequestInfo requestInfo)
{
logMessage(requestInfo, "In handleDebugDatabase()");
// The user must have full administrative rights to see anything here.
if (! requestInfo.hasFullAccess)
{
logMessage(requestInfo, "No hasFullAccess permission granted");
generateAccessDeniedBody(requestInfo, "You do not have permission to " +
"view debug information.");
return;
}
// Get the important state variables for this request.
HttpServletRequest request = requestInfo.request;
String servletBaseURI = requestInfo.servletBaseURI;
StringBuilder htmlBody = requestInfo.htmlBody;
StringBuilder infoMessage = requestInfo.infoMessage;
// First, print out a really hideous warning message to the user.
infoMessage.append("<B>WARNING: This information is provided for " +
"debugging purposes only, and any changes made " +
"through this interface can cause serious damage to " +
"the database. Use it at your own risk.</B>" + EOL);
// See if the user has specified a database name. If not, then present a
// form to request one.
String dbName = request.getParameter(Constants.SERVLET_PARAM_DB_NAME);
if ((dbName == null) || (dbName.length() == 0))
{
try
{
String[] dbNames = configDB.getDBNames();
htmlBody.append("<SPAN CLASS=\"" + Constants.STYLE_MAIN_HEADER +
"\">SLAMD Database Debug Information</SPAN>" + EOL);
htmlBody.append("<BR><BR>" + EOL);
htmlBody.append("<FORM METHOD=\"POST\" ACTION=\"" + servletBaseURI +
"\">" + EOL);
htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SECTION,
Constants.SERVLET_SECTION_DEBUG) +
EOL);
htmlBody.append(" " +
generateHidden(Constants.SERVLET_PARAM_SUBSECTION,
Constants.SERVLET_SECTION_DEBUG_DB) + EOL);
htmlBody.append(" " +
generateHidden(Constants.SERVLET_PARAM_HTML_DEBUG,
"1") + EOL);
htmlBody.append(" Choose the database you wish to access:" + EOL);
htmlBody.append(" <SELECT NAME=\"" + Constants.SERVLET_PARAM_DB_NAME +
"\">" + EOL);
for (int i=0; i < dbNames.length; i++)
{
htmlBody.append(" <OPTION VALUE=\"" + dbNames[i] + "\">" +
dbNames[i] + EOL);
}
htmlBody.append(" </SELECT>" + EOL);
htmlBody.append(" <BR><BR>" + EOL);
htmlBody.append(" <INPUT TYPE=\"SUBMIT\" VALUE=\"Next >\">" + EOL);
htmlBody.append("</FORM>" + EOL);
}
catch (Exception e)
{
htmlBody.append("<PRE>" + EOL);
htmlBody.append(JobClass.stackTraceToString(e) + EOL);
htmlBody.append("</PRE>" + EOL);
}
return;
}
// The user has specified a database name, so see if they have given a key
// name. If not, then present a list of the keys in that database.
String dbKey = request.getParameter(Constants.SERVLET_PARAM_DB_KEY);
if ((dbKey == null) || (dbKey.length() == 0))
{
try
{
htmlBody.append("<SPAN CLASS=\"" + Constants.STYLE_MAIN_HEADER +
"\">SLAMD Debug Information for Database " + dbName +
"</SPAN>" + EOL);
htmlBody.append("<BR><BR>" + EOL);
String[] keyNames = configDB.getDBKeys(dbName);
htmlBody.append("The following keys have been defined in the " +
dbName + " database:" + EOL);
htmlBody.append("<BR><BR>" + EOL);
for (int i=0; i < keyNames.length; i++)
{
htmlBody.append(generateLink(requestInfo,
Constants.SERVLET_SECTION_DEBUG,
Constants.SERVLET_SECTION_DEBUG_DB,
Constants.SERVLET_PARAM_DB_NAME, dbName,
Constants.SERVLET_PARAM_DB_KEY,
keyNames[i], keyNames[i]));
htmlBody.append("<BR>" + EOL);
}
htmlBody.append("<BR>" + EOL);
htmlBody.append("<FORM METHOD=\"POST\" ACTION=\"" + servletBaseURI +
"\">" + EOL);
htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SECTION,
Constants.SERVLET_SECTION_DEBUG) +
EOL);
htmlBody.append(" " +
generateHidden(Constants.SERVLET_PARAM_SUBSECTION,
Constants.SERVLET_SECTION_DEBUG_DB) + EOL);
htmlBody.append(" " +
generateHidden(Constants.SERVLET_PARAM_HTML_DEBUG,
"1") + EOL);
htmlBody.append(" <INPUT TYPE=\"SUBMIT\" VALUE=\"< Back\">" + EOL);
htmlBody.append("</FORM>" + EOL);
}
catch (Exception e)
{
htmlBody.append("<PRE>" + EOL);
htmlBody.append(JobClass.stackTraceToString(e) + EOL);
htmlBody.append("</PRE>" + EOL);
}
return;
}
// The user has specified a specific key. Display the data associated with
// that key in both hex and ASCII forms.
try
{
htmlBody.append("<SPAN CLASS=\"" + Constants.STYLE_MAIN_HEADER +
"\">SLAMD Debug Information for Database " + dbName +
" Key " + dbKey + "</SPAN>" + EOL);
htmlBody.append("<BR><BR>" + EOL);
byte[] data = configDB.getDBData(dbName, dbKey);
String hexData = ASN1Element.byteArrayToStringWithASCII(data);
hexData = replaceText(hexData, "<", "<");
hexData = replaceText(hexData, ">", ">");
htmlBody.append("<B>Hexadecimal Representation</B>" + EOL);
htmlBody.append("<PRE>" + EOL);
htmlBody.append(hexData + EOL);
htmlBody.append("</PRE>" + EOL);
String dataString = new String(data, "UTF-8");
dataString = replaceText(dataString, "<", "<");
dataString = replaceText(dataString, ">", ">");
htmlBody.append("<BR><BR>" + EOL);
htmlBody.append("<B>String Representation</B>" + EOL);
htmlBody.append("<PRE>" + EOL);
htmlBody.append(dataString + EOL);
htmlBody.append("</PRE>" + EOL);
htmlBody.append("<BR><BR>" + EOL);
htmlBody.append("<FORM METHOD=\"POST\" ACTION=\"" + servletBaseURI +
"\">" + EOL);
htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SECTION,
Constants.SERVLET_SECTION_DEBUG) +
EOL);
htmlBody.append(" " +
generateHidden(Constants.SERVLET_PARAM_SUBSECTION,
Constants.SERVLET_SECTION_DEBUG_DB) + EOL);
htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_DB_NAME,
dbName) + EOL);
htmlBody.append(" " +
generateHidden(Constants.SERVLET_PARAM_HTML_DEBUG,
"1") + EOL);
htmlBody.append(" <INPUT TYPE=\"SUBMIT\" VALUE=\"< Back\">" + EOL);
htmlBody.append("</FORM>" + EOL);
}
catch (Exception e)
{
htmlBody.append("<PRE>" + EOL);
htmlBody.append(JobClass.stackTraceToString(e) + EOL);
htmlBody.append("</PRE>" + EOL);
}
return;
}
/**
* Handles the work of requesting that the JVM perform garbage collection.
*
* @param requestInfo The state information for this request.
*/
static void handleDebugGC(RequestInfo requestInfo)
{
logMessage(requestInfo, "In handleDebugGC()");
// The user must have full administrative rights to see anything here.
if (! requestInfo.hasFullAccess)
{
logMessage(requestInfo, "No hasFullAccess permission granted");
generateAccessDeniedBody(requestInfo, "You do not have permission to " +
"view debug information.");
return;
}
// Get the important state variables for this request.
StringBuilder htmlBody = requestInfo.htmlBody;
// Request that the JVM perform garbage collection.
System.gc();
// Display a message to the user indicating that the request was performed.
htmlBody.append("<SPAN CLASS=\"" + Constants.STYLE_MAIN_HEADER +
"\">JVM Garbage Collection Requested</SPAN>" + EOL);
htmlBody.append("<BR><BR>" + EOL);
htmlBody.append("A request has been sent to the JVM to perform garbage " +
"collection." + EOL);
htmlBody.append("Note that this request will not have any effect if the " +
"JVM has been configured to ignore garbage collection " +
"requests." + EOL);
}
/**
* Handles the work of requesting that the JVM enable instruction tracing.
*
* @param requestInfo The state information for this request.
*/
static void handleDebugEnableInstructionTrace(RequestInfo requestInfo)
{
logMessage(requestInfo, "In handleDebugEnableInstructionTrace()");
// The user must have full administrative rights to see anything here.
if (! requestInfo.hasFullAccess)
{
logMessage(requestInfo, "No hasFullAccess permission granted");
generateAccessDeniedBody(requestInfo, "You do not have permission to " +
"view debug information.");
return;
}
// Get the important state variables for this request.
StringBuilder htmlBody = requestInfo.htmlBody;
// Request that the JVM enable instruction tracing.
Runtime.getRuntime().traceInstructions(true);
// Display a message to the user indicating that the request was performed.
htmlBody.append("<SPAN CLASS=\"" + Constants.STYLE_MAIN_HEADER +
"\">JVM Instruction Tracing Requested</SPAN>" + EOL);
htmlBody.append("<BR><BR>" + EOL);
htmlBody.append("A request has been sent to the JVM to enable " +
"instruction tracing." + EOL);
htmlBody.append("A few things to note about this tracing:" + EOL);
htmlBody.append("<UL>" + EOL);
htmlBody.append(" <LI>Tracing may not be supported on all platforms " +
"or JVMs.</LI>" + EOL);
htmlBody.append(" <LI>Tracing may require the use of a debug version of " +
"the JVM or invoking the JVM with debugging " +
"parameters.</LI>" + EOL);
htmlBody.append(" <LI>If tracing is supported, then the format, output " +
"location, and other details may vary by " +
"implementation.</LI>" + EOL);
htmlBody.append(" <LI>Tracing may impose a severe performance penalty " +
"and may generate a great deal of output. It is " +
"strongly recommended that it be used only when " +
"necessary for debugging purposes.</LI>" + EOL);
htmlBody.append("</UL>" + EOL);
}
/**
* Handles the work of requesting that the JVM disable instruction tracing.
*
* @param requestInfo The state information for this request.
*/
static void handleDebugDisableInstructionTrace(RequestInfo requestInfo)
{
logMessage(requestInfo, "In handleDebugDisableInstructionTrace()");
// The user must have full administrative rights to see anything here.
if (! requestInfo.hasFullAccess)
{
logMessage(requestInfo, "No hasFullAccess permission granted");
generateAccessDeniedBody(requestInfo, "You do not have permission to " +
"view debug information.");
return;
}
// Get the important state variables for this request.
StringBuilder htmlBody = requestInfo.htmlBody;
// Request that the JVM disable instruction tracing.
Runtime.getRuntime().traceInstructions(false);
// Display a message to the user indicating that the request was performed.
htmlBody.append("<SPAN CLASS=\"" + Constants.STYLE_MAIN_HEADER +
"\">JVM Instruction Tracing Stopped</SPAN>" + EOL);
htmlBody.append("<BR><BR>" + EOL);
htmlBody.append("A request has been sent to the JVM to disable " +
"instruction tracing." + EOL);
}
/**
* Handles the work of requesting that the JVM enable method call tracing.
*
* @param requestInfo The state information for this request.
*/
static void handleDebugEnableMethodTrace(RequestInfo requestInfo)
{
logMessage(requestInfo, "In handleDebugEnableMethodTrace()");
// The user must have full administrative rights to see anything here.
if (! requestInfo.hasFullAccess)
{
logMessage(requestInfo, "No hasFullAccess permission granted");
generateAccessDeniedBody(requestInfo, "You do not have permission to " +
"view debug information.");
return;
}
// Get the important state variables for this request.
StringBuilder htmlBody = requestInfo.htmlBody;
// Request that the JVM enable method call tracing.
Runtime.getRuntime().traceMethodCalls(true);
// Display a message to the user indicating that the request was performed.
htmlBody.append("<SPAN CLASS=\"" + Constants.STYLE_MAIN_HEADER +
"\">JVM Method Call Tracing Requested</SPAN>" + EOL);
htmlBody.append("<BR><BR>" + EOL);
htmlBody.append("A request has been sent to the JVM to enable method " +
"call tracing." + EOL);
htmlBody.append("A few things to note about this tracing:" + EOL);
htmlBody.append("<UL>" + EOL);
htmlBody.append(" <LI>Tracing may not be supported on all platforms " +
"or JVMs.</LI>" + EOL);
htmlBody.append(" <LI>Tracing may require the use of a debug version of " +
"the JVM or invoking the JVM with debugging " +
"parameters.</LI>" + EOL);
htmlBody.append(" <LI>If tracing is supported, then the format, output " +
"location, and other details may vary by " +
"implementation.</LI>" + EOL);
htmlBody.append(" <LI>Tracing may impose a severe performance penalty " +
"and may generate a great deal of output. It is " +
"strongly recommended that it be used only when " +
"necessary for debugging purposes.</LI>" + EOL);
htmlBody.append("</UL>" + EOL);
}
/**
* Handles the work of requesting that the JVM disable method call tracing.
*
* @param requestInfo The state information for this request.
*/
static void handleDebugDisableMethodTrace(RequestInfo requestInfo)
{
logMessage(requestInfo, "In handleDebugDisableMethodTrace()");
// The user must have full administrative rights to see anything here.
if (! requestInfo.hasFullAccess)
{
logMessage(requestInfo, "No hasFullAccess permission granted");
generateAccessDeniedBody(requestInfo, "You do not have permission to " +
"view debug information.");
return;
}
// Get the important state variables for this request.
StringBuilder htmlBody = requestInfo.htmlBody;
// Request that the JVM disable method call tracing.
Runtime.getRuntime().traceMethodCalls(false);
// Display a message to the user indicating that the request was performed.
htmlBody.append("<SPAN CLASS=\"" + Constants.STYLE_MAIN_HEADER +
"\">JVM Method Call Tracing Stopped</SPAN>" + EOL);
htmlBody.append("<BR><BR>" + EOL);
htmlBody.append("A request has been sent to the JVM to disable " +
"method call tracing." + EOL);
}
/**
* Extracts information from the HTTP request that may be used for debugging
* purposes.
*
* @param requestInfo The state information for this request.
*
* @return The debug information that may be added to the page.
*/
static String debugRequestInfo(RequestInfo requestInfo)
{
StringBuilder buf = new StringBuilder();
StringBuilder urlBuf = new StringBuilder();
HttpServletRequest request = requestInfo.request;
buf.append(EOL);
buf.append("<!-- Request URI: ");
buf.append(requestInfo.servletBaseURI);
buf.append(" -->");
buf.append(EOL);
buf.append("<!-- Request Method: ");
buf.append(request.getMethod());
buf.append(" -->");
buf.append(EOL);
buf.append("<!-- Remote User: ");
buf.append(request.getRemoteUser());
buf.append(" -->");
buf.append(EOL);
buf.append("<!-- Remote Addr: ");
buf.append(request.getRemoteAddr());
buf.append(" -->");
buf.append(EOL);
buf.append("<!-- Remote Host: ");
buf.append(request.getRemoteHost());
buf.append(" -->");
buf.append(EOL);
buf.append("<!-- Begin Request Headers -->");
buf.append(EOL);
Enumeration headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements())
{
String headerName = (String) headerNames.nextElement();
buf.append("<!-- ");
buf.append(headerName);
buf.append(" -->");
buf.append(EOL);
Enumeration headerValues = request.getHeaders(headerName);
while (headerValues.hasMoreElements())
{
buf.append("<!-- ");
buf.append((String) headerValues.nextElement());
buf.append(" -->");
buf.append(EOL);
}
}
buf.append("<!-- End Request Headers -->");
buf.append(EOL);
urlBuf.append(request.getRequestURL());
String separator = "?";
buf.append("<!-- Begin Request Parameters -->");
buf.append(EOL);
Enumeration parameterNames = request.getParameterNames();
while (parameterNames.hasMoreElements())
{
String parameterName = (String) parameterNames.nextElement();
if (parameterName.equals(Constants.SERVLET_PARAM_HTML_DEBUG))
{
continue;
}
buf.append("<!-- ");
buf.append(parameterName);
buf.append(" -->");
buf.append(EOL);
String[] parameterValues = request.getParameterValues(parameterName);
for (int i=0; ((parameterValues != null) && (i < parameterValues.length));
i++)
{
buf.append("<!-- ");
buf.append(parameterValues[i]);
buf.append(" -->");
buf.append(EOL);
urlBuf.append(separator);
urlBuf.append(parameterName);
urlBuf.append('=');
urlBuf.append(parameterValues[i]);
}
if ((parameterValues == null) || (parameterValues.length == 0))
{
urlBuf.append(separator);
urlBuf.append(parameterName);
urlBuf.append('=');
}
separator = "&";
}
buf.append("<!-- End Request Parameters -->");
buf.append(EOL);
buf.append("<!-- HTTP GET URL: ");
final String getURL = replaceText(urlBuf.toString(), " ", "%20");
requestInfo.setGETURL(getURL);
buf.append(getURL);
buf.append(" -->" + EOL);
buf.append(EOL);
buf.append(EOL);
return buf.toString();
}
}