<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!--
  SessionSnooper.jsp

  Copyright 2005-2009 Chris Schultz - www.christopherschultz.net

  Please see the Creative Commons license at the end of this file
  for licensing information. The plain-English version of the license
  is "do whatever you want with this, just give me some credit".

  Enjoy!

  Changes:

  2007-05-08 Added request parameters and request attributes to display.

  2008-03-24 Improved memory info display.

  2008-08-20 Fixed XHTML and CSS compliance.
-->
<%@ page
    pageEncoding="UTF-8"
    session="false"
    language="java"
    import="
	java.lang.Runtime,
	java.net.InetAddress,
	java.util.Collections,
	java.util.Date,
	java.util.Enumeration,
	java.util.ArrayList,
	java.util.List,
	java.util.Iterator,
	java.lang.reflect.Array,
	java.util.Map,
	java.util.HashMap,
    java.text.NumberFormat
    "
%>
<%@ include file="htmlescape.jsp" %>
<%@ include file="httpheaderreferences.jsp" %>
<%@ include file="util.jsp" %>
<%!
    String CREATE_SESSION     = "createSession";
    String INVALIDATE_SESSION = "invalidateSession";
    String MEMORY_INFO        = "memoryinfo";
%>
<!--
<rdf:RDF xmlns="http://web.resource.org/cc/"
    xmlns:dc="http://purl.org/dc/elements/1.1/"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<Work rdf:about="">
   <dc:title>SessionSnooper.jsp</dc:title>
   <dc:date>2003</dc:date>
   <dc:description>A server&#45;side JSP which allows users to browse request headers and attributes defined in the request, session, and application scope.
</dc:description>
   <dc:creator><Agent>
      <dc:title>Christopher Schultz</dc:title>
   </Agent></dc:creator>
   <dc:rights><Agent>
      <dc:title>Christopher Schultz</dc:title>
   </Agent></dc:rights>
   <dc:type rdf:resource="http://purl.org/dc/dcmitype/Interactive" />
   <license rdf:resource="http://creativecommons.org/licenses/by-sa/2.0/" />
</Work>

<License rdf:about="http://creativecommons.org/licenses/by-sa/2.0/">
   <permits rdf:resource="http://web.resource.org/cc/Reproduction" />
   <permits rdf:resource="http://web.resource.org/cc/Distribution" />
   <requires rdf:resource="http://web.resource.org/cc/Notice" />
   <requires rdf:resource="http://web.resource.org/cc/Attribution" />
   <permits rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
   <requires rdf:resource="http://web.resource.org/cc/ShareAlike" />
</License>

</rdf:RDF>
-->
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<%
    boolean createSession   = request.getParameter(CREATE_SESSION) != null;
    boolean deleteSession   = request.getParameter(INVALIDATE_SESSION) != null;
    boolean countMemory	    = request.getParameter(MEMORY_INFO) != null;

    HttpSession session = request.getSession(createSession);

    if(null != session && deleteSession)
    {
	session.invalidate();
	session = null;
    }

    Runtime runtime = Runtime.getRuntime();
    if("Request Garbage Collection".equals(request.getParameter("request_garbage_collection")))
    {
	    runtime.gc();
	    Thread.sleep(500); // Wait just a second for GC to happen.
    }
%>
<head>
    <title>
	SessionSnooper - <%=InetAddress.getLocalHost().getHostName()%>
    </title>

    <style type="text/css"><!--
	body { font-family:sans-serif; }
	h1 { text-align:center; font-size:x-large; }
	h2 { font-size:large; }
	fieldset { margin-bottom:2em; }
	fieldset legend { font-size:large; font-weight:bold; }
	label { cursor:pointer; }
	table { border-collapse:collapse; }
	table td { border:1px solid #f0f0f0; vertical-align:top; }
	.buttons { text-align:center; }
	td.attribute-checkbox { font-size:small; }
	td.attribute-name { font-size:small; }
	td.attribute-class { font-size:small; }
	td.attribute-value { font-size:small; }
    table.memory { width:50px; border-collapse: collapse; }
    table.memory td { text-align:center; padding:0.25em 0.5em 0.25em 0.5em; }
    .total { background-color:#993366; }
    td.total { width:25px; }
    p.total { padding:0.5em 1em 0.5em 1em; }
    .unused { background-color:silver; }
    td.unused { }
    p.unused { padding:0.5em 1em 0.5em 1em; }
    .free { background-color:#66ff33; }
    td.free { width:25px; }
    p.free { padding:0.5em 1em 0.5em 1em; }
    .used { background-color:#ff3333; }
    td.used { width:25px; }
    p.used { padding:0.5em 1em 0.5em 1em; }
    .allocated { background-color:#cc3399; }
    td.allocated { width:25px; }
    p.allocated { padding:0.5em 1em 0.5em 1em; }
--></style>
</head>
<body>
    <h1><%= new Date() %></h1>
    <h1><%=InetAddress.getLocalHost().getHostName()%></h1>

<form method="get" action="<%= response.encodeURL(request.getRequestURI())%>">

<fieldset>
    <legend>
	JVM Memory Info
    </legend>

    <p>
        <input type="checkbox" id="<%=MEMORY_INFO%>" name="<%=MEMORY_INFO%>" value="true" <%=(countMemory ? "checked=\"checked\"" : "")%> />
	<label for="<%=MEMORY_INFO%>">Get Memory Info For JVM</label>
    </p>

<% if(countMemory) { %>

<table>
<%
    long totalMemory = 0;
    long freeMemory  = 0;
    long usedMemory  = 0;
    long maxMemory   = 0;
    long unusedMemory = 0;

    if(countMemory)
    {
        maxMemory = runtime.maxMemory();
        totalMemory = runtime.totalMemory();
        freeMemory = runtime.freeMemory();
        usedMemory = totalMemory - freeMemory;
        unusedMemory = maxMemory - totalMemory;
    }

    double usedPercent = (double) usedMemory / (double)maxMemory;
    double freePercent = (double) freeMemory / (double)maxMemory;
    double unusedPercent = (double) unusedMemory / (double)maxMemory;

    int tableHeight = 300;
    int unusedHeight = (int)(unusedPercent * (double)tableHeight);
    int usedHeight = (int)(usedPercent * (double)tableHeight);
    int freeHeight = (int)(freePercent * (double)tableHeight);

    NumberFormat pf = NumberFormat.getPercentInstance();
    pf.setMinimumFractionDigits(1);
    pf.setMaximumFractionDigits(1);
%>
<tr valign="middle">
    <td>
	<table class="memory">
    <tr>
        <td class="unused" colspan="2" style="height:<%= unusedHeight %>px;"><%= unusedMemory / (1024 * 1024) %> MiB Unallocated</td>
        <td class="total" rowspan="3"><%= maxMemory / (1024 * 1024) %> MiB Maximum</td>
    </tr>
	<tr>
	    <td class="free" style="height:<%= freeHeight %>px"><%= pf.format(new Double((double)freeMemory / (double)totalMemory)) %> Free</td>
        <td class="allocated" rowspan="2" style="height:<%= freeHeight + usedHeight %>px;"><%= totalMemory / (1024 * 1024) %> MiB Allocated</td>
	</tr>
	<tr>
	    <td class="used" style="height:<%= usedHeight %>px"><%= pf.format(new Double((double)usedMemory / (double)totalMemory)) %> Used</td>
	</tr>
	</table>
        <p>
<% if ("Request Garbage Collection".equals(request.getParameter("request_garbage_collection"))) { %>
	        <input type="submit" name="request_garbage_collection" value="Stop Garbage Collection" />
<% } else { %>
	        <input type="submit" name="request_garbage_collection" value="Request Garbage Collection" />
<% } %>
        </p>
    </td>
    <td>
    <p class="total">Maximum Memory JVM will use: <%= maxMemory %> bytes (<%= maxMemory / 1024 %> KiB, <%= maxMemory / (1024 * 1024) %> MiB)</p>

    <p class="unused">Memory Not yet Allocated to JVM: <%= unusedMemory %> bytes (<%= unusedMemory / 1024 %> KiB, <%= unusedMemory / (1024*1024) %> MiB)</p>

	<p class="allocated">Total Memory Allocated to JVM: <%= totalMemory %> bytes (<%= (totalMemory / 1024) %> KiB, <%= (totalMemory/(1024*1024)) %> MiB)</p>

	<p class="free">Free Memory: <%= freeMemory %> (<%= (freeMemory / 1024) %> KiB, <%= (freeMemory/(1024*1024)) %> MiB)</p>

	<p class="used">Memory Used by JVM: <%= usedMemory %> (<%= (usedMemory / 1024) %> KiB, <%= (usedMemory/(1024*1024)) %> MiB)</p>
    </td>
</tr>
</table>

<% } //if(countMemory) %>
</fieldset>
<div class="buttons">
    <input type="submit" name="submit" value="Submit" />
</div>

<!-- ======================== -->
<!--      Request Headers     -->
<!-- ======================== -->
<fieldset>
    <legend>
	HTTP Request Headers
    </legend>

<%
    Enumeration e = request.getHeaderNames();

    if(e.hasMoreElements())
    {
%>
<table id="request-headers">
<tr>
    <th>
	Name
    </th>
    <th>
	Value
    </th>
</tr>
<%
	while(e.hasMoreElements())
	{
	    String name = (String)e.nextElement();

%>
<tr>
    <td><a title="Lookup reference for '<%= htmlescape(name) %>'" href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#<%= getHeaderSection(name) %>"><%= htmlescape(name) %></a></td>
    <td>
<%
	    for(Enumeration hs = request.getHeaders(name); hs.hasMoreElements(); )
	    {
%>
	<%= htmlescape(String.valueOf(hs.nextElement())) %><br />
<%
	    }
%>
    </td>
</tr>
<%
	}
%>
</table>
<%
    }
%>
</fieldset>

<!-- ======================== -->
<!--    Request Parameters    -->
<!-- ======================== -->
<fieldset>
    <legend>
	Request Parameters
    </legend>
<%
    List names = new ArrayList();

    for(e = request.getParameterNames(); e.hasMoreElements(); )
        names.add(e.nextElement());

    Collections.sort(names);

    if(0 <= names.size())
    {
%>
   <table id="request-parameters">
   <tr>
	<th></th><!-- For the "value" checkbox -->
	<th>
	    Name
	</th>
	<th>
	    Value(s)
	</th>
    </tr>
<%
    for(Iterator i=names.iterator(); i.hasNext(); )
    {
        String name = (String)i.next();
        String[] values = request.getParameterValues(name);
%>
    <tr>
    <td></td><!-- To match other tables -->
	<td class="attribute-name">
	    <%= htmlescape(name) %>
	</td>
	<td class="attribute-value">
<%
        for(int j=0; j<values.length; ++j)
        {
%>
	    <%= htmlescape(values[j]) %><br />
<%
        }
%>
	</td>
    </tr>
<%
    } //foreach(request attribute)
%>
    </table>
<%
    } // if(0 < names.size())
%>
</fieldset>

<!-- ======================== -->
<!--    Request Attributes    -->
<!-- ======================== -->
<fieldset>
    <legend>
	Request Attributes
    </legend>
<%
    if(null == names)
        names = new ArrayList();
    else
        names.clear();

    for(e = request.getAttributeNames(); e.hasMoreElements(); )
        names.add(e.nextElement());

    Collections.sort(names);

    if(0 <= names.size())
    {
%>
   <table id="request-attributes">
   <tr>
	<th></th><!-- For the "value" checkbox -->
	<th>
	    Name
	</th>
	<th>
	    Class
	</th>
	<th>
	    Value
	</th>
    </tr>
<%
    for(Iterator i=names.iterator(); i.hasNext(); )
    {
        String name = (String)i.next();
        Object value = request.getAttribute(name);
        String className = this.getClassName(value);
        String reqName = "request_" + name;
        boolean checked = request.getParameter(reqName) != null;
%>
    <tr>
	<td>
	    <input type="checkbox" id="<%= reqName %>" name="<%=reqName%>" value="true" <%=(checked ? "checked=\"checked\"" : "")%> title="<%= (checked ? "Suppress the value of this attribute" : "Display the value of this attribute") %>" />
	</td>
	<td class="attribute-name">
	    <label for="<%= reqName %>" title="<%= (checked ? "Suppress the value of this attribute" : "Display the value of this attribute") %>"><%= htmlescape(name) %></label>
	</td>
	<td class="attribute-class">
	    <%= className %>
	</td>
	<td class="attribute-value">
	    <%= (checked ? htmlescape(String.valueOf(this.getValue(value))) : "") %>
	</td>
    </tr>
<%
    } //foreach(request attribute)
%>
    </table>
<%
    } // if(0 < names.size())
%>
</fieldset>

<!-- ======================== -->
<!--           Session        -->
<!-- ======================== -->
<fieldset>
    <legend>
	Session
    </legend>
<%
    if(null == session)
    {
%>
    <input type="checkbox" id="<%=CREATE_SESSION%>" name="<%=CREATE_SESSION%>" value="true" />
    <label for="<%= CREATE_SESSION %>">Create Session</label>.
<%
    }
    else
    {
%>

<p>
    <b>Session ID:</b> <%=session.getId()%>
</p>

<p>
    <input type="checkbox" id="<%=INVALIDATE_SESSION%>" name="<%=INVALIDATE_SESSION%>" value="true" />
    <label for="<%=INVALIDATE_SESSION%>">Invalidate Session</label>
</p>

<%
    if(null == names)
        names = new ArrayList();
    else
        names.clear();

    for(e = session.getAttributeNames(); e.hasMoreElements(); )
	names.add(e.nextElement());

    Collections.sort(names);

    if(0 <= names.size())
    {
%>
   <table id="session-attributes">
   <tr>
	<th></th><!-- For the "value" checkbox -->
	<th>
	    Name
	</th>
	<th>
	    Class
	</th>
	<th>
	    Value
	</th>
    </tr>
<%
    for(Iterator i=names.iterator(); i.hasNext(); )
    {
	String name = (String)i.next();
        Object value = session.getAttribute(name);
	String className = this.getClassName(value);
	String reqName = "session_" + name;
	boolean checked = request.getParameter(reqName) != null;
%>
    <tr>
	<td>
	    <input type="checkbox" id="<%= reqName %>" name="<%=reqName%>" value="true" <%=(checked ? "checked=\"checked\"" : "")%> title="<%= (checked ? "Suppress the value of this attribute" : "Display the value of this attribute") %>" />
	</td>
	<td class="attribute-name">
	    <label for="<%= reqName %>" title="<%= (checked ? "Suppress the value of this attribute" : "Display the value of this attribute") %>"><%= htmlescape(name) %></label>
	</td>
	<td class="attribute-class">
	    <%= className %>
	</td>
	<td class="attribute-value">
	    <%= (checked ? htmlescape(String.valueOf(this.getValue(value))) : "") %>
	</td>
    </tr>
<%
    } //foreach(session attribute)
%>
    </table>
<%
    } // if(session attributes)
    } // if(session)
%>
</fieldset>

<div class="buttons">
    <input type="submit" name="submit" value="Submit" />
</div>

<fieldset>
    <legend>
	Application
    </legend>

<%
    if(null == names)
        names = new ArrayList();
    else
        names.clear();

    for(e = application.getAttributeNames(); e.hasMoreElements(); )
        names.add(e.nextElement());

    Collections.sort(names);

    if(0 < names.size())
    {
%>
    <table id="application-attributes">
    <tr>
	<th></th><!-- For the "value" checkbox -->
	<th>
	    Name
	</th>
	<th>
	    Class
	</th>
	<th>
	    Value
	</th>
    </tr>
<%
    for(Iterator i=names.iterator(); i.hasNext(); )
    {
	String name = (String)i.next();
	Object value = application.getAttribute(name);
	String className = this.getClassName(value);
	String reqName = "application_" + name;
	boolean checked = request.getParameter(reqName) != null;
%>
    <tr>
	<td class="attribute-checkbox">
	    <input type="checkbox" id="<%= reqName %>" name="<%= reqName %>" value="true" <%= (checked ? "checked=\"checked\"" : "") %> />
	</td>
	<td class="attribute-name">
	    <label for="<%= reqName %>"><%= htmlescape(name) %></label>
	</td>
	<td class="attribute-class">
	    <%= className %>
	</td>
	<td class="attribute-value">
	    <%= (checked ? htmlescape(String.valueOf(this.getValue(value))) : "") %>
	</td>
    </tr>
<%
    } // foreach(application attribute)
%>
    </table>
<%
    } // if(application attributes)
%>
</fieldset>

<div class="buttons">
    <input type="submit" name="submit" value="Submit" />
</div>
</form>

<hr />

<p class="license">
    <!-- Creative Commons License -->
    <a rel="license" href="http://creativecommons.org/licenses/by-sa/2.0/">
    <img alt="Creative Commons License" style="border:none;"
        src="http://creativecommons.org/images/public/somerights20.gif" />
    </a>
    <!-- /Creative Commons License -->

    <a href="http://validator.w3.org/check?uri=referer"><img
          src="http://www.w3.org/Icons/valid-xhtml10"
          alt="Valid XHTML 1.0!" style="border:none;height:31px;width:88px;" />
    </a>

    <a href="http://jigsaw.w3.org/css-validator/">
    <img style="border:0;width:88px;height:31px"
       src="http://jigsaw.w3.org/css-validator/images/vcss" 
       alt="Valid CSS!" />
    </a>
</p>
<p class="license">
    <!-- Creative Commons License -->
    This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-sa/2.0/">Creative Commons License</a>.
    <!-- /Creative Commons License -->
</p>
</body>
</html>
