Author: markt
Date: Tue Aug 18 11:49:26 2009
New Revision: 805375

URL: http://svn.apache.org/viewvc?rev=805375&view=rev
Log:
Replace the RequestDumperValve with a RequestDumperFilter. Merge the 
RequestDumperFilter from the examples with this new filter.
Adds:
- thread name to start of output line to make analysing output easier
- request timings
GSOC 2009
Based on a patch by Xie Xiaodong

Added:
    tomcat/trunk/java/org/apache/catalina/filters/RequestDumperFilter.java   
(with props)
Removed:
    tomcat/trunk/java/org/apache/catalina/valves/RequestDumperValve.java
    
tomcat/trunk/webapps/examples/WEB-INF/classes/filters/RequestDumperFilter.java
Modified:
    tomcat/trunk/conf/server.xml
    tomcat/trunk/java/org/apache/catalina/mbeans/MBeanFactory.java
    tomcat/trunk/webapps/docs/config/filter.xml
    tomcat/trunk/webapps/docs/config/valve.xml
    tomcat/trunk/webapps/examples/WEB-INF/web.xml

Modified: tomcat/trunk/conf/server.xml
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/conf/server.xml?rev=805375&r1=805374&r2=805375&view=diff
==============================================================================
--- tomcat/trunk/conf/server.xml (original)
+++ tomcat/trunk/conf/server.xml Tue Aug 18 11:49:26 2009
@@ -106,13 +106,6 @@
       <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
       -->        
 
-      <!-- The request dumper valve dumps useful debugging information about
-           the request and response data received and sent by Tomcat.
-           Documentation at: /docs/config/valve.html -->
-      <!--
-      <Valve className="org.apache.catalina.valves.RequestDumperValve"/>
-      -->
-
       <!-- This Realm uses the UserDatabase configured in the global JNDI
            resources under the key "UserDatabase".  Any edits
            that are performed against this UserDatabase are immediately

Added: tomcat/trunk/java/org/apache/catalina/filters/RequestDumperFilter.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/filters/RequestDumperFilter.java?rev=805375&view=auto
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/filters/RequestDumperFilter.java 
(added)
+++ tomcat/trunk/java/org/apache/catalina/filters/RequestDumperFilter.java Tue 
Aug 18 11:49:26 2009
@@ -0,0 +1,283 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.catalina.filters;
+
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Enumeration;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+
+
+/**
+ * <p>Implementation of a Filter that logs interesting contents from the
+ * specified Request (before processing) and the corresponding Response
+ * (after processing).  It is especially useful in debugging problems
+ * related to headers and cookies.</p>
+ * 
+ * <p>When using this Filter, it is strongly recommended that the
+ * <code>org.apache.catalina.filter.RequestDumperFilter</code> logger is
+ * directed to a dedicated file and that the
+ * <code>org.apache.juli.VerbatimFormmater</code> is used.</p>
+ *
+ * @author Craig R. McClanahan
+ */
+
+public class RequestDumperFilter implements Filter {
+
+    private static final String NON_HTTP_REQ_MSG =
+        "Not available. Non-http request.";
+    private static final String NON_HTTP_RES_MSG =
+        "Not available. Non-http response.";
+
+    private static final ThreadLocal<Timestamp> timestamp =
+            new ThreadLocal<Timestamp>() {
+        protected Timestamp initialValue() {
+            return new Timestamp();
+        }
+    };
+
+    /**
+     * The logger for this class.
+     */
+    private static Log log = LogFactory.getLog(RequestDumperFilter.class);
+
+
+    /**
+     * Log the interesting request parameters, invoke the next Filter in the
+     * sequence, and log the interesting response parameters.
+     *
+     * @param request  The servlet request to be processed
+     * @param response The servlet response to be created
+     * @param chain    The filter chain being processed
+     *
+     * @exception IOException if an input/output error occurs
+     * @exception ServletException if a servlet error occurs
+     */
+    public void doFilter(ServletRequest request, ServletResponse response,
+            FilterChain chain)
+        throws IOException, ServletException {
+
+        HttpServletRequest hRequest = null;
+        HttpServletResponse hResponse = null;
+        
+        if (request instanceof HttpServletRequest) {
+            hRequest = (HttpServletRequest) request;
+        }
+        if (response instanceof HttpServletResponse) {
+            hResponse = (HttpServletResponse) response;
+        }
+
+        // Log pre-service information
+        doLog("START TIME        ", getTimestamp());
+        
+        if (hRequest == null) {
+            doLog("        requestURI", NON_HTTP_REQ_MSG);
+            doLog("          authType", NON_HTTP_REQ_MSG);
+        } else {
+            doLog("        requestURI", hRequest.getRequestURI());
+            doLog("          authType", hRequest.getAuthType());
+        }
+        
+        doLog(" characterEncoding", request.getCharacterEncoding());
+        doLog("     contentLength",
+                Integer.valueOf(request.getContentLength()).toString());
+        doLog("       contentType", request.getContentType());
+        
+        if (hRequest == null) {
+            doLog("       contextPath", NON_HTTP_REQ_MSG);
+            doLog("            cookie", NON_HTTP_REQ_MSG);
+            doLog("            header", NON_HTTP_REQ_MSG);
+        } else {
+            doLog("       contextPath", hRequest.getContextPath());
+            Cookie cookies[] = hRequest.getCookies();
+            if (cookies != null) {
+                for (int i = 0; i < cookies.length; i++)
+                    doLog("            cookie", cookies[i].getName() +
+                            "=" + cookies[i].getValue());
+            }
+            Enumeration<String> hnames = hRequest.getHeaderNames();
+            while (hnames.hasMoreElements()) {
+                String hname = hnames.nextElement();
+                Enumeration<String> hvalues = hRequest.getHeaders(hname);
+                while (hvalues.hasMoreElements()) {
+                    String hvalue = hvalues.nextElement();
+                    doLog("            header", hname + "=" + hvalue);
+                }
+            }
+        }
+        
+        doLog("            locale", request.getLocale().toString());
+        
+        if (hRequest == null) {
+            doLog("            method", NON_HTTP_REQ_MSG);
+        } else {
+            doLog("            method", hRequest.getMethod());
+        }
+        
+        Enumeration<String> pnames = request.getParameterNames();
+        while (pnames.hasMoreElements()) {
+            String pname = pnames.nextElement();
+            String pvalues[] = request.getParameterValues(pname);
+            StringBuffer result = new StringBuffer(pname);
+            result.append('=');
+            for (int i = 0; i < pvalues.length; i++) {
+                if (i > 0)
+                    result.append(", ");
+                result.append(pvalues[i]);
+            }
+            doLog("         parameter", result.toString());
+        }
+        
+        if (hRequest == null) {
+            doLog("          pathInfo", NON_HTTP_REQ_MSG);
+        } else {
+            doLog("          pathInfo", hRequest.getPathInfo());
+        }
+        
+        doLog("          protocol", request.getProtocol());
+        
+        if (hRequest == null) {
+            doLog("       queryString", NON_HTTP_REQ_MSG);
+        } else {
+            doLog("       queryString", hRequest.getQueryString());
+        }
+        
+        doLog("        remoteAddr", request.getRemoteAddr());
+        doLog("        remoteHost", request.getRemoteHost());
+        
+        if (hRequest == null) {
+            doLog("        remoteUser", NON_HTTP_REQ_MSG);
+            doLog("requestedSessionId", NON_HTTP_REQ_MSG);
+        } else {
+            doLog("        remoteUser", hRequest.getRemoteUser());
+            doLog("requestedSessionId", hRequest.getRequestedSessionId());
+        }
+        
+        doLog("            scheme", request.getScheme());
+        doLog("        serverName", request.getServerName());
+        doLog("        serverPort",
+                Integer.valueOf(request.getServerPort()).toString());
+        
+        if (hRequest == null) {
+            doLog("       servletPath", NON_HTTP_REQ_MSG);
+        } else {
+            doLog("       servletPath", hRequest.getServletPath());
+        }
+        
+        doLog("          isSecure",
+                Boolean.valueOf(request.isSecure()).toString());
+        doLog("------------------",
+                "--------------------------------------------");
+
+        // Perform the request
+        chain.doFilter(request, response);
+
+        // Log post-service information
+        doLog("------------------",
+                "--------------------------------------------");
+        if (hRequest == null) {
+            doLog("          authType", NON_HTTP_REQ_MSG);
+        } else {
+            doLog("          authType", hRequest.getAuthType());
+        }
+        
+        doLog("       contentType", response.getContentType());
+        
+        if (hResponse == null) {
+            doLog("            header", NON_HTTP_RES_MSG);
+        } else {
+            Iterable<String> rhnames = hResponse.getHeaderNames();
+            for (String rhname : rhnames) {
+                Iterable<String> rhvalues = hResponse.getHeaders(rhname);
+                for (String rhvalue : rhvalues)
+                    doLog("            header", rhname + "=" + rhvalue);
+            }
+        }
+
+        if (hRequest == null) {
+            doLog("        remoteUser", NON_HTTP_REQ_MSG);
+        } else {
+            doLog("        remoteUser", hRequest.getRemoteUser());
+        }
+        
+        if (hResponse == null) {
+            doLog("        remoteUser", NON_HTTP_RES_MSG);
+        } else {
+            doLog("            status",
+                    Integer.valueOf(hResponse.getStatus()).toString());
+        }
+
+        doLog("END TIME          ", getTimestamp());
+        doLog("==================",
+                "============================================");
+       }
+
+    private void doLog(String attribute, String value) {
+        StringBuilder sb = new StringBuilder(80);
+        sb.append(Thread.currentThread().getName());
+        sb.append(' ');
+        sb.append(attribute);
+        sb.append('=');
+        sb.append(value);
+        log.info(sb.toString());
+    }
+
+    private String getTimestamp() {
+        Timestamp ts = timestamp.get();
+        long currentTime = System.currentTimeMillis();
+        
+        if ((ts.date.getTime() + 999) < currentTime) {
+            ts.date.setTime(currentTime - (currentTime % 1000));
+            ts.update();
+        }
+        return ts.dateString;
+    }
+
+    @Override
+    public void init(FilterConfig filterConfig) throws ServletException {
+        // NOOP
+    }
+
+    @Override
+    public void destroy() {
+        // NOOP
+    }
+
+    private static final class Timestamp {
+        private Date date = new Date(0);
+        private SimpleDateFormat format =
+            new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss");
+        private String dateString = format.format(date);
+        private void update() {
+            dateString = format.format(date);
+        }
+    }
+}

Propchange: 
tomcat/trunk/java/org/apache/catalina/filters/RequestDumperFilter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
tomcat/trunk/java/org/apache/catalina/filters/RequestDumperFilter.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision

Modified: tomcat/trunk/java/org/apache/catalina/mbeans/MBeanFactory.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/mbeans/MBeanFactory.java?rev=805375&r1=805374&r2=805375&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/mbeans/MBeanFactory.java (original)
+++ tomcat/trunk/java/org/apache/catalina/mbeans/MBeanFactory.java Tue Aug 18 
11:49:26 2009
@@ -49,7 +49,6 @@
 import org.apache.catalina.valves.AccessLogValve;
 import org.apache.catalina.valves.RemoteAddrValve;
 import org.apache.catalina.valves.RemoteHostValve;
-import org.apache.catalina.valves.RequestDumperValve;
 import org.apache.catalina.valves.ValveBase;
 import org.apache.tomcat.util.modeler.BaseModelMBean;
 
@@ -513,29 +512,6 @@
 
 
     /**
-     * Create a new Request Dumper Valve.
-     *
-     * @param parent MBean Name of the associated parent component
-     *
-     * @exception Exception if an MBean cannot be created or registered
-     */
-    public String createRequestDumperValve(String parent)
-        throws Exception {
-
-        // Create a new RequestDumperValve instance
-        RequestDumperValve valve = new RequestDumperValve();
-
-        // Add the new instance to its parent component
-        ObjectName pname = new ObjectName(parent);
-        ContainerBase containerBase = getParentContainerFromParent(pname);
-        containerBase.addValve(valve);
-        ObjectName oname = valve.getObjectName();
-        return (oname.toString());
-
-    }
-
-
-    /**
      * Create a new Single Sign On Valve.
      *
      * @param parent MBean Name of the associated parent component

Modified: tomcat/trunk/webapps/docs/config/filter.xml
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/config/filter.xml?rev=805375&r1=805374&r2=805375&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/config/filter.xml (original)
+++ tomcat/trunk/webapps/docs/config/filter.xml Tue Aug 18 11:49:26 2009
@@ -194,6 +194,75 @@
 </section>
 
 
+<section name="Request Dumper Filter">
+
+  <subsection name="Introduction">
+
+    <p>The Request Dumper Filter logs information from the request and response
+    objects and is intended to be used for debugging purposes. When using this
+    Filter, it is recommended that the
+    <code>org.apache.catalina.filter.RequestDumperFilter</code> logger is
+    directed to a dedicated file and that the
+    <code>org.apache.juli.VerbatimFormmater</code> is used.</p>
+
+    <p><strong>WARNING: Using this filter has side-effects.</strong>  The
+    output from this filter includes any parameters included with the request.
+    The parameters will be decoded using the default platform encoding. Any
+    subsequent calls to <code>request.setCharacterEncoding()</code> within
+    the web application will have no effect.</p>
+    
+  </subsection>
+
+  <subsection name="Filter Class Name">
+
+    <p>The filter class name for the Request Dumper Filter is
+    <strong><code>org.apache.catalina.filters.RequestDumperFilter</code>
+    </strong>.</p>
+
+  </subsection>
+
+  <subsection name="Initialisation parameters">
+
+    <p>The Request Dumper Filter does not support any initialization
+    parameters.</p>
+
+  </subsection>
+
+  <subsection name="Sample Configuration">
+  
+    <p>The following entries in a web application's web.xml would enable the
+    Request Dumper filter for all requests for that web application. If the
+    entries were added to <code>CATALINA_BASE/conf/web.xml</code>, the Request
+    Dumper Filter would be enabled for all web applications.</p>
+    <source>
+&lt;filter&gt;
+    &lt;filter-name&gt;requestdumper&lt;/filter-name&gt;
+    &lt;filter-class&gt;
+        org.apache.catalina.filters.RequestDumperFilter
+    &lt;/filter-class&gt;
+&lt;/filter&gt;
+&lt;filter-mapping&gt;
+    &lt;filter-name&gt;requestdumper&lt;/filter-name&gt;
+    &lt;url-pattern&gt;*&lt;/url-pattern&gt;
+&lt;/filter-mapping&gt;
+    </source>
+    
+    <p>The following entries in CATALINA_BASE/conf/logging.properties would
+    create a separate log file for the Request Dumper Filter output.</p>
+    <source>
+# To this configuration below, 1request-dumper.org.apache.juli.FileHandler
+# also needs to be added to the handlers property near the top of the file
+1request-dumper.org.apache.juli.FileHandler.level = INFO
+1request-dumper.org.apache.juli.FileHandler.directory = ${catalina.base}/logs
+1request-dumper.org.apache.juli.FileHandler.prefix = request-dumper.
+1request-dumper.org.apache.juli.FileHandler.formatter = 
org.apache.juli.VerbatimFormatter
+org.apache.catalina.filters.RequestDumperFilter.level = INFO
+org.apache.catalina.filters.RequestDumperFilter.handlers = 
1request-dumper.org.apache.juli.FileHandler
+    </source>
+  </subsection>
+</section>
+
+
 <section name="WebDAV Fix Filter">
 
   <subsection name="Introduction">

Modified: tomcat/trunk/webapps/docs/config/valve.xml
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/config/valve.xml?rev=805375&r1=805374&r2=805375&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/config/valve.xml (original)
+++ tomcat/trunk/webapps/docs/config/valve.xml Tue Aug 18 11:49:26 2009
@@ -320,47 +320,6 @@
 </section>
 
 
-<section name="Request Dumper Valve">
-
-
-  <subsection name="Introduction">
-
-    <p>The <em>Request Dumper Valve</em> is a useful tool in debugging
-    interactions with a client application (or browser) that is sending
-    HTTP requests to your Tomcat-based server.  When configured, it causes
-    details about each request processed by its associated 
<code>Engine</code>, 
-    <code>Host</code>, or <code>Context</code> to be logged according to 
-    the logging configuration for that container.</p>
-
-    <p><strong>WARNING: Using this valve has side-effects.</strong>  The
-    output from this valve includes any parameters included with the request.
-    The parameters will be decoded using the default platform encoding. Any
-    subsequent calls to <code>request.setCharacterEncoding()</code> within
-    the web application will have no effect.</p>
-
-  </subsection>
-
-
-  <subsection name="Attributes">
-
-    <p>The <strong>Request Dumper Valve</strong> supports the following
-    configuration attributes:</p>
-
-    <attributes>
-
-      <attribute name="className" required="true">
-        <p>Java class name of the implementation to use.  This MUST be set to
-        <strong>org.apache.catalina.valves.RequestDumperValve</strong>.</p>
-      </attribute>
-
-    </attributes>
-
-  </subsection>
-
-
-</section>
-
-
 <section name="Single Sign On Valve">
 
   <subsection name="Introduction">

Modified: tomcat/trunk/webapps/examples/WEB-INF/web.xml
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/webapps/examples/WEB-INF/web.xml?rev=805375&r1=805374&r2=805375&view=diff
==============================================================================
--- tomcat/trunk/webapps/examples/WEB-INF/web.xml (original)
+++ tomcat/trunk/webapps/examples/WEB-INF/web.xml Tue Aug 18 11:49:26 2009
@@ -39,7 +39,7 @@
 
     <filter>
         <filter-name>Request Dumper Filter</filter-name>
-        <filter-class>filters.RequestDumperFilter</filter-class>
+        
<filter-class>org.apache.catalina.filters.RequestDumperFilter</filter-class>
     </filter>
 
     <!-- Example filter to set character encoding on each request -->



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to