You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by fm...@apache.org on 2008/03/11 12:19:02 UTC

svn commit: r635888 - in /incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl: ./ log/ request/

Author: fmeschbe
Date: Tue Mar 11 04:18:49 2008
New Revision: 635888

URL: http://svn.apache.org/viewvc?rev=635888&view=rev
Log:
SLING-214 Merge LoggerResponse methods into SlingHttpServletResponseImpl
and turn RequestLoggerFilter into a simple service, which is directly
accessed by the SlingMainServlet to call for request entry and exit.

Added:
    incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/log/RequestLogger.java
      - copied, changed from r635461, incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/log/RequestLoggerFilter.java
Removed:
    incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/log/LoggerResponse.java
    incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/log/RequestLoggerFilter.java
Modified:
    incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/SlingHttpServletResponseImpl.java
    incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/log/CustomLogFormat.java
    incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/log/FileRequestLog.java
    incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/log/RequestLoggerService.java
    incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/request/RequestData.java
    incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/request/SlingRequestProgressTracker.java

Modified: incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/SlingHttpServletResponseImpl.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/SlingHttpServletResponseImpl.java?rev=635888&r1=635887&r2=635888&view=diff
==============================================================================
--- incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/SlingHttpServletResponseImpl.java (original)
+++ incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/SlingHttpServletResponseImpl.java Tue Mar 11 04:18:49 2008
@@ -20,9 +20,17 @@
 
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 
 import javax.servlet.ServletOutputStream;
+import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpServletResponseWrapper;
 
@@ -35,12 +43,76 @@
  */
 public class SlingHttpServletResponseImpl extends HttpServletResponseWrapper implements SlingHttpServletResponse {
 
+    // the content type header name
+    private static final String HEADER_CONTENT_TYPE = "Content-Type";
+
+    // the content length header name
+    private static final String HEADER_CONTENT_LENGTH = "Content-Length";
+
+    /** format for RFC 1123 date string -- "Sun, 06 Nov 1994 08:49:37 GMT" */
+    private final static SimpleDateFormat RFC1123_FORMAT = new SimpleDateFormat(
+        "EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
+
+    /**
+     * The counter for request gone through this filter. As this is the first
+     * request level filter hit, this counter should actually count each request
+     * which at least enters the request level component filter processing.
+     * <p>
+     * This counter is reset to zero, when this component is activated. That is,
+     * each time this component is restarted (system start, bundle start,
+     * reconfiguration), the request counter restarts at zero.
+     */
+    private static int requestCounter = 0;
+
+    // TODO: more content related headers, namely Content-Language should
+    // probably be supported
+
+    // the request counter
+    private int requestId;
+
+    // the system time in ms when the request entered the system, this is
+    // the time this instance was created
+    private long requestStart;
+
+    // the system time in ms when the request exited the system, this is
+    // the time of the call to the requestEnd() method
+    private long requestEnd;
+
+    // the output stream wrapper providing the transferred byte count
+    private LoggerResponseOutputStream out;
+
+    // the print writer wrapper providing the transferred character count
+    private LoggerResponseWriter writer;
+
+    // the caches status
+    private int status = SC_OK;
+
+    // the cookies set during the request, indexed by cookie name
+    private Map<String, Cookie> cookies;
+
+    // the headers set during the request, indexed by lower-case header
+    // name, value is string for single-valued and list for multi-valued
+    // headers
+    private Map<String, Object> headers;
+
     private final RequestData requestData;
 
     public SlingHttpServletResponseImpl(RequestData requestData,
             HttpServletResponse response) {
         super(response);
         this.requestData = requestData;
+
+        this.requestId = requestCounter++;
+        this.requestStart = System.currentTimeMillis();
+    }
+
+    /**
+     * Called to indicate the request processing has ended. This method
+     * currently sets the request end time returned by {@link #getRequestEnd()}
+     * and which is used to calculate the request duration.
+     */
+    public void requestEnd() {
+        this.requestEnd = System.currentTimeMillis();
     }
 
     protected final RequestData getRequestData() {
@@ -65,12 +137,20 @@
 
     @Override
     public ServletOutputStream getOutputStream() throws IOException {
-        return getRequestData().getBufferProvider().getOutputStream();
+        if (this.out == null) {
+            ServletOutputStream sos = getRequestData().getBufferProvider().getOutputStream();
+            this.out = new LoggerResponseOutputStream(sos);
+        }
+        return this.out;
     }
 
     @Override
     public PrintWriter getWriter() throws IOException {
-        return getRequestData().getBufferProvider().getWriter();
+        if (this.writer == null) {
+            PrintWriter pw = getRequestData().getBufferProvider().getWriter();
+            this.writer = new LoggerResponseWriter(pw);
+        }
+        return this.writer;
     }
 
     @Override
@@ -135,29 +215,156 @@
 
     // ---------- Error handling through Sling Error Resolver -----------------
 
+    
+    @Override
+    public void sendRedirect(String location) throws IOException {
+        super.sendRedirect(location);
+
+        // replicate the status code of call to base class
+        this.status = SC_MOVED_TEMPORARILY;
+    }
+
     @Override
-    public void sendError(int sc) throws IOException {
-        sendError(sc, null);
+    public void sendError(int status) throws IOException {
+        sendError(status, null);
     }
 
     @Override
-    public void sendError(int sc, String msg) throws IOException {
+    public void sendError(int status, String message) throws IOException {
         checkCommitted();
 
+        this.status = status;
         ErrorHandler eh = getRequestData().getSlingMainServlet().getErrorHandler();
-        eh.handleError(sc, msg, requestData.getSlingRequest(), this);
+        eh.handleError(status, message, requestData.getSlingRequest(), this);
     }
 
     @Override
-    public void setStatus(int sc, String sm) {
+    public void setStatus(int status, String message) {
         checkCommitted();
-        super.setStatus(sc, sm);
+        this.status = status;
+        super.setStatus(status, message);
     }
 
     @Override
-    public void setStatus(int sc) {
+    public void setStatus(int status) {
         checkCommitted();
-        super.setStatus(sc);
+        this.status = status;
+        super.setStatus(status);
+    }
+
+    public void addCookie(Cookie cookie) {
+
+        // register the cookie for later use
+        if (this.cookies == null) {
+            this.cookies = new HashMap<String, Cookie>();
+        }
+        this.cookies.put(cookie.getName(), cookie);
+
+        super.addCookie(cookie);
+    }
+
+    public void addDateHeader(String name, long date) {
+        this.registerHeader(name, toDateString(date), true);
+        super.addDateHeader(name, date);
+    }
+
+    public void addHeader(String name, String value) {
+        this.registerHeader(name, value, true);
+        super.addHeader(name, value);
+    }
+
+    public void addIntHeader(String name, int value) {
+        this.registerHeader(name, String.valueOf(value), true);
+        super.addIntHeader(name, value);
+    }
+
+    public void setContentLength(int len) {
+        this.registerHeader(HEADER_CONTENT_LENGTH, String.valueOf(len), false);
+        super.setContentLength(len);
+    }
+
+    public void setContentType(String type) {
+        this.registerHeader(HEADER_CONTENT_TYPE, type, false);
+        super.setContentType(type);
+    }
+
+    public void setDateHeader(String name, long date) {
+        this.registerHeader(name, toDateString(date), false);
+        super.setDateHeader(name, date);
+    }
+
+    public void setHeader(String name, String value) {
+        this.registerHeader(name, value, false);
+        super.setHeader(name, value);
+    }
+
+    public void setIntHeader(String name, int value) {
+        this.registerHeader(name, String.valueOf(value), false);
+        this.setHeader(name, String.valueOf(value));
+    }
+
+    public void setLocale(Locale loc) {
+        // TODO: Might want to register the Content-Language header
+        super.setLocale(loc);
+    }
+
+    // ---------- Retrieving response information ------------------------------
+
+    public int getRequestId() {
+        return this.requestId;
+    }
+
+    public long getRequestStart() {
+        return this.requestStart;
+    }
+
+    public long getRequestEnd() {
+        return this.requestEnd;
+    }
+
+    public long getRequestDuration() {
+        return this.requestEnd - this.requestStart;
+    }
+
+    public int getStatus() {
+        return this.status;
+    }
+
+    public int getCount() {
+        if (this.out != null) {
+            return this.out.getCount();
+        } else if (this.writer != null) {
+            return this.writer.getCount();
+        }
+
+        // otherwise return zero
+        return 0;
+    }
+
+    public Cookie getCookie(String name) {
+        return (this.cookies != null) ? (Cookie) this.cookies.get(name) : null;
+    }
+
+    public String getHeaders(String name) {
+        // normalize header name to lower case to support case-insensitive
+        // headers
+        name = name.toLowerCase();
+
+        Object header = (this.headers != null) ? this.headers.get(name) : null;
+        if (header == null) {
+            return null;
+        } else if (header instanceof String) {
+            return (String) header;
+        } else {
+            StringBuffer headerBuf = new StringBuffer();
+            for (Iterator<?> hi = ((List<?>) header).iterator(); hi.hasNext();) {
+                if (headerBuf.length() > 0) {
+                    headerBuf.append(",");
+                }
+                headerBuf.append(hi.next());
+            }
+            return headerBuf.toString();
+        }
     }
 
     // ---------- Internal helper ---------------------------------------------
@@ -187,5 +394,139 @@
 
     private String map(String url) {
         return getRequestData().getResourceResolver().map(url);
+    }
+
+    /**
+     * Stores the name header-value pair in the header map. The name is
+     * converted to lower-case before using it as an index in the map.
+     *
+     * @param name The name of the header to register
+     * @param value The value of the header to register
+     * @param add If <code>true</code> the header value is added to the list
+     *            of potentially existing header values. Otherwise the new value
+     *            replaces any existing values.
+     */
+    private void registerHeader(String name, String value, boolean add) {
+        // ensure the headers map
+        if (this.headers == null) {
+            this.headers = new HashMap<String, Object>();
+        }
+
+        // normalize header name to lower case to support case-insensitive
+        // headers
+        name = name.toLowerCase();
+
+        // retrieve the current contents if adding, otherwise assume no current
+        Object current = add ? this.headers.get(name) : null;
+
+        if (current == null) {
+            // set the single value (forced if !add)
+            this.headers.put(name, value);
+
+        } else if (current instanceof String) {
+            // create list if a single value is already set
+            List<String> list = new ArrayList<String>();
+            list.add((String) current);
+            list.add(value);
+            this.headers.put(name, list);
+
+        } else {
+            // append to the list of more than one already set
+            ((List<Object>) current).add(value);
+        }
+    }
+
+    /**
+     * Converts the time value given as the number of milliseconds since January
+     * 1, 1970 to a date and time string compliant with RFC 1123 date
+     * specification. The resulting string is compliant with section 3.3.1, Full
+     * Date, of <a href="http://www.faqs.org/rfcs/rfc2616.html">RFC 2616</a>
+     * and may thus be used as the value of date header such as
+     * <code>Date</code>.
+     *
+     * @param date The date value to convert to a string
+     * @return The string representation of the date and time value.
+     */
+    public static String toDateString(long date) {
+        synchronized (RFC1123_FORMAT) {
+            return RFC1123_FORMAT.format(new Date(date));
+        }
+    }
+
+    //---------- byte/character counting output channels ----------------------
+    
+    // byte transfer counting ServletOutputStream
+    private static class LoggerResponseOutputStream extends ServletOutputStream {
+        private ServletOutputStream delegatee;
+
+        private int count;
+
+        LoggerResponseOutputStream(ServletOutputStream delegatee) {
+            this.delegatee = delegatee;
+        }
+
+        public int getCount() {
+            return this.count;
+        }
+
+        public void write(int b) throws IOException {
+            this.delegatee.write(b);
+            this.count++;
+        }
+
+        public void write(byte[] b) throws IOException {
+            this.delegatee.write(b);
+            this.count += b.length;
+        }
+
+        public void write(byte[] b, int off, int len) throws IOException {
+            this.delegatee.write(b, off, len);
+            this.count += len;
+        }
+
+        public void flush() throws IOException {
+            this.delegatee.flush();
+        }
+
+        public void close() throws IOException {
+            this.delegatee.close();
+        }
+    }
+
+    // character transfer counting PrintWriter
+    private static class LoggerResponseWriter extends PrintWriter {
+
+        private static final int LINE_SEPARATOR_LENGTH = System.getProperty(
+            "line.separator").length();
+
+        private int count;
+
+        LoggerResponseWriter(PrintWriter delegatee) {
+            super(delegatee);
+        }
+
+        public int getCount() {
+            return this.count;
+        }
+
+        public void write(int c) {
+            super.write(c);
+            this.count++;
+        }
+
+        public void write(char[] buf, int off, int len) {
+            super.write(buf, off, len);
+            this.count += len;
+        }
+
+        public void write(String s, int off, int len) {
+            super.write(s, off, len);
+            this.count += len;
+        }
+
+        public void println() {
+            super.println();
+            this.count += LINE_SEPARATOR_LENGTH;
+        }
     }
 }

Modified: incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/log/CustomLogFormat.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/log/CustomLogFormat.java?rev=635888&r1=635887&r2=635888&view=diff
==============================================================================
--- incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/log/CustomLogFormat.java (original)
+++ incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/log/CustomLogFormat.java Tue Mar 11 04:18:49 2008
@@ -33,6 +33,7 @@
 
 import org.apache.sling.api.SlingHttpServletRequest;
 import org.apache.sling.api.resource.Resource;
+import org.apache.sling.core.impl.SlingHttpServletResponseImpl;
 
 /**
  * The <code>CustomLogFormat</code> class implements the support for log format
@@ -65,14 +66,14 @@
      *
      * @param request The {@link org.apache.sling.component.ComponentResponse}
      *            used to extract values for the log message.
-     * @param response The {@link LoggerResponse} used to extract values for the
+     * @param response The {@link SlingHttpServletResponseImpl} used to extract values for the
      *            log message.
      *
      * @return The formatted log message or <code>null</code> if this log
      *         formatter has not been initialized with a valid log format
      *         pattern.
      */
-    String format(SlingHttpServletRequest request, LoggerResponse response) {
+    String format(SlingHttpServletRequest request, SlingHttpServletResponseImpl response) {
         if (this.logParameters != null) {
             StringBuffer buf = new StringBuffer();
             for (int i=0; i < this.logParameters.length; i++) {
@@ -341,7 +342,7 @@
     //---------- Parameter support --------------------------------------------
 
     static interface Parameter {
-        void print(StringBuffer dest, SlingHttpServletRequest request, LoggerResponse response);
+        void print(StringBuffer dest, SlingHttpServletRequest request, SlingHttpServletResponseImpl response);
     }
 
     static class PlainTextParameter implements Parameter {
@@ -350,7 +351,7 @@
             this.value = value;
         }
         public void print(StringBuffer dest, SlingHttpServletRequest request,
-                LoggerResponse response) {
+                SlingHttpServletResponseImpl response) {
             dest.append(this.value);
         }
         public String toString() {
@@ -389,9 +390,9 @@
         }
 
         protected abstract String getValue(SlingHttpServletRequest request);
-        protected abstract String getValue(LoggerResponse response);
+        protected abstract String getValue(SlingHttpServletResponseImpl response);
 
-        public final void print(StringBuffer dest, SlingHttpServletRequest request, LoggerResponse response) {
+        public final void print(StringBuffer dest, SlingHttpServletRequest request, SlingHttpServletResponseImpl response) {
             if (this.printOk(response.getStatus())) {
                 String value = this.isRequest ? this.getValue(request) : this.getValue(response);
                 dest.append((value == null) ? "-" : value);
@@ -515,7 +516,7 @@
             return null;
         }
 
-        protected String getValue(LoggerResponse response) {
+        protected String getValue(SlingHttpServletResponseImpl response) {
             return null;
         }
     }
@@ -529,7 +530,7 @@
             return Thread.currentThread().getName();
         }
 
-        protected String getValue(LoggerResponse response) {
+        protected String getValue(SlingHttpServletResponseImpl response) {
             return null;
         }
     }
@@ -543,7 +544,7 @@
             return null;
         }
 
-        protected String getValue(LoggerResponse response) {
+        protected String getValue(SlingHttpServletResponseImpl response) {
             return String.valueOf(response.getRequestId());
         }
     }
@@ -557,7 +558,7 @@
             return null;
         }
 
-        protected String getValue(LoggerResponse response) {
+        protected String getValue(SlingHttpServletResponseImpl response) {
             int count = response.getCount();
             if (count == 0) {
                 return (this.getParName() == 'b') ? "-" : "0";
@@ -601,7 +602,7 @@
             return null;
         }
 
-        protected String getValue(LoggerResponse response) {
+        protected String getValue(SlingHttpServletResponseImpl response) {
             long time = this.requestStart ? response.getRequestStart() : response.getRequestEnd();
             return timeFormatted(time);
         }
@@ -641,7 +642,7 @@
             return null;
         }
 
-        protected String getValue(LoggerResponse response) {
+        protected String getValue(SlingHttpServletResponseImpl response) {
             long time = response.getRequestDuration();
             if (this.seconds) {
                 time /= 1000;
@@ -659,7 +660,7 @@
             return request.getRemoteAddr();
         }
 
-        protected String getValue(LoggerResponse response) {
+        protected String getValue(SlingHttpServletResponseImpl response) {
             return null;
         }
     }
@@ -673,7 +674,7 @@
             return request.getRemoteHost();
         }
 
-        protected String getValue(LoggerResponse response) {
+        protected String getValue(SlingHttpServletResponseImpl response) {
             return null;
         }
     }
@@ -687,7 +688,7 @@
             return request.getLocalAddr();
         }
 
-        protected String getValue(LoggerResponse response) {
+        protected String getValue(SlingHttpServletResponseImpl response) {
             return null;
         }
     }
@@ -701,7 +702,7 @@
             return String.valueOf(request.getServerPort());
         }
 
-        protected String getValue(LoggerResponse response) {
+        protected String getValue(SlingHttpServletResponseImpl response) {
             return null;
         }
     }
@@ -715,7 +716,7 @@
             return request.getServerName();
         }
 
-        protected String getValue(LoggerResponse response) {
+        protected String getValue(SlingHttpServletResponseImpl response) {
             return null;
         }
     }
@@ -730,7 +731,7 @@
             return (resource != null) ? resource.getPath() : null;
         }
 
-        protected String getValue(LoggerResponse response) {
+        protected String getValue(SlingHttpServletResponseImpl response) {
             return null;
         }
     }
@@ -748,7 +749,7 @@
                 + " " + request.getProtocol();
         }
 
-        protected String getValue(LoggerResponse response) {
+        protected String getValue(SlingHttpServletResponseImpl response) {
             return null;
         }
     }
@@ -762,7 +763,7 @@
             return request.getProtocol();
         }
 
-        protected String getValue(LoggerResponse response) {
+        protected String getValue(SlingHttpServletResponseImpl response) {
             return null;
         }
     }
@@ -776,7 +777,7 @@
             return request.getMethod();
         }
 
-        protected String getValue(LoggerResponse response) {
+        protected String getValue(SlingHttpServletResponseImpl response) {
             return null;
         }
     }
@@ -790,7 +791,7 @@
             return request.getRequestURI();
         }
 
-        protected String getValue(LoggerResponse response) {
+        protected String getValue(SlingHttpServletResponseImpl response) {
             return null;
         }
     }
@@ -805,7 +806,7 @@
             return (query == null || query.length() == 0) ? "" : "?" + query;
         }
 
-        protected String getValue(LoggerResponse response) {
+        protected String getValue(SlingHttpServletResponseImpl response) {
             return null;
         }
     }
@@ -819,7 +820,7 @@
             return request.getRemoteUser();
         }
 
-        protected String getValue(LoggerResponse response) {
+        protected String getValue(SlingHttpServletResponseImpl response) {
             return null;
         }
     }
@@ -833,7 +834,7 @@
             return null;
         }
 
-        protected String getValue(LoggerResponse response) {
+        protected String getValue(SlingHttpServletResponseImpl response) {
             return String.valueOf(response.getStatus());
         }
     }
@@ -850,7 +851,7 @@
             return (cookie == null) ? null : escape(cookie.toString());
         }
 
-        protected String getValue(LoggerResponse response) {
+        protected String getValue(SlingHttpServletResponseImpl response) {
             Cookie cookie = response.getCookie(this.cookieName);
             return (cookie == null) ? null : escape(cookie.toString());
         }
@@ -877,7 +878,7 @@
             return escape(value);
         }
 
-        protected String getValue(LoggerResponse response) {
+        protected String getValue(SlingHttpServletResponseImpl response) {
             return escape(response.getHeaders(this.headerName));
         }
     }

Modified: incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/log/FileRequestLog.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/log/FileRequestLog.java?rev=635888&r1=635887&r2=635888&view=diff
==============================================================================
--- incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/log/FileRequestLog.java (original)
+++ incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/log/FileRequestLog.java Tue Mar 11 04:18:49 2008
@@ -42,7 +42,7 @@
  * not recommended to call the {@link #init(String)} method multiple times. When
  * the class is not used any more the {@link #dispose()} method should be called
  * to clean up, namely to close all open files. This lifecycle behaviour is
- * forced by the {@link RequestLoggerFilter} component, which calls the
+ * forced by the {@link RequestLogger} component, which calls the
  * {@link #init(String)} method on filter component activation and calls the
  * {@link #dispose()} metod on filter component deactivation.
  * <p>

Copied: incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/log/RequestLogger.java (from r635461, incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/log/RequestLoggerFilter.java)
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/log/RequestLogger.java?p2=incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/log/RequestLogger.java&p1=incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/log/RequestLoggerFilter.java&r1=635461&r2=635888&rev=635888&view=diff
==============================================================================
--- incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/log/RequestLoggerFilter.java (original)
+++ incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/log/RequestLogger.java Tue Mar 11 04:18:49 2008
@@ -18,23 +18,16 @@
  */
 package org.apache.sling.core.impl.log;
 
-import java.io.IOException;
 import java.util.Dictionary;
 import java.util.Properties;
 
-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 org.apache.sling.api.SlingHttpServletRequest;
 import org.apache.sling.api.SlingHttpServletResponse;
+import org.apache.sling.core.impl.SlingHttpServletResponseImpl;
 import org.osgi.framework.BundleContext;
 
 /**
- * The <code>RequestLoggerFilter</code> is a request level filter, which
+ * The <code>RequestLogger</code> is a request level filter, which
  * provides customizable logging or requests handled by Sling. This filter is
  * inserted as the first filter in the request level filter chain and therefore
  * is the first filter called when processing a request and the last filter
@@ -42,17 +35,14 @@
  *
  * @scr.component immediate="true" label="%request.log.name"
  *                description="%request.log.description"
- * @scr.property name="service.description" value="Request Logger Filter"
+ * @scr.property name="service.description" value="Request Logger"
  * @scr.property name="service.vendor" value="The Apache Software Foundation"
- * @scr.property name="filter.scope" value="request" private="true"
- * @scr.property name="filter.order" value="-2147483648" type="Integer"
- *               private="true"
- * @scr.service
+ * @scr.service interface="org.apache.sling.core.impl.log.RequestLogger"
  * @scr.reference name="RequestLoggerService"
  *                interface="org.apache.sling.core.impl.log.RequestLoggerService"
  *                cardinality="0..n" policy="dynamic"
  */
-public class RequestLoggerFilter implements Filter {
+public class RequestLogger {
 
     /**
      * @scr.property value="logs/request.log"
@@ -152,16 +142,6 @@
     private RequestLoggerService accessLog;
 
     /**
-     * No further initialization needed by this instance as the full
-     * configuration has already been done by the
-     * {@link #activate(org.osgi.service.component.ComponentContext)} method.
-     *
-     * @param config Not used.
-     */
-    public void init(FilterConfig config) {
-    }
-
-    /**
      * Filters the request as follows:
      * <ol>
      * <li>Creates a wrapper around the <code>response</code> object to catch
@@ -185,29 +165,24 @@
      * @throws ServletException Forwarded if thrown by any filter in the chain
      *             or by the Component called to handle the request.
      */
-    public void doFilter(ServletRequest sRequest, ServletResponse response,
-            FilterChain filterChain) throws IOException,
-            ServletException {
-
-        SlingHttpServletRequest request = (SlingHttpServletRequest) sRequest;
-        LoggerResponse loggerResponse = new LoggerResponse(
-            (SlingHttpServletResponse) response, this.requestCounter++);
-
-        // log the request start
-        if (this.requestEntry != null) {
-            for (int i = 0; i < this.requestEntry.length; i++) {
-                this.requestEntry[i].log(request, loggerResponse);
+    
+    public void logRequestEntry(SlingHttpServletRequest request, SlingHttpServletResponse response) {
+
+        if (response instanceof SlingHttpServletResponseImpl) {
+            // log the request start
+            if (this.requestEntry != null) {
+                for (int i = 0; i < this.requestEntry.length; i++) {
+                    this.requestEntry[i].log(request,
+                        (SlingHttpServletResponseImpl) response);
+                }
             }
         }
-
-        try {
-
-            // continue request processing without any more intervention
-            filterChain.doFilter(request, loggerResponse);
-
-        } finally {
-
-            // signal the end of the request
+    }
+    
+    public void logRequestExit(SlingHttpServletRequest request, SlingHttpServletResponse response) {
+        // signal the end of the request
+        if (response instanceof SlingHttpServletResponseImpl) {
+            SlingHttpServletResponseImpl loggerResponse = (SlingHttpServletResponseImpl) response;
             loggerResponse.requestEnd();
 
             // log the request end
@@ -217,14 +192,6 @@
                 }
             }
         }
-    }
-
-    /**
-     * No further shutdown needed by this instance as the full configuration
-     * will bee done by the
-     * {@link #deactivate(org.osgi.service.component.ComponentContext)} method.
-     */
-    public void destroy() {
     }
 
     // ---------- SCR Integration ----------------------------------------------

Modified: incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/log/RequestLoggerService.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/log/RequestLoggerService.java?rev=635888&r1=635887&r2=635888&view=diff
==============================================================================
--- incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/log/RequestLoggerService.java (original)
+++ incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/log/RequestLoggerService.java Tue Mar 11 04:18:49 2008
@@ -23,12 +23,13 @@
 
 import org.apache.sling.api.SlingHttpServletRequest;
 import org.apache.sling.core.RequestLog;
+import org.apache.sling.core.impl.SlingHttpServletResponseImpl;
 import org.osgi.framework.BundleContext;
 import org.osgi.service.component.ComponentContext;
 
 /**
  * The <code>RequestLoggerService</code> is a factory component which gets
- * configuration to register loggers for the {@link RequestLoggerFilter}.
+ * configuration to register loggers for the {@link RequestLogger}.
  *
  * @scr.component label="%request.log.service.name"
  *                description="%request.log.service.description"
@@ -110,7 +111,7 @@
         this.logFormat = null;
     }
 
-    void log(SlingHttpServletRequest request, LoggerResponse response) {
+    void log(SlingHttpServletRequest request, SlingHttpServletResponseImpl response) {
         if (this.log != null && this.logFormat != null) {
             this.log.write(this.logFormat.format(request, response));
         }

Modified: incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/request/RequestData.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/request/RequestData.java?rev=635888&r1=635887&r2=635888&view=diff
==============================================================================
--- incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/request/RequestData.java (original)
+++ incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/request/RequestData.java Tue Mar 11 04:18:49 2008
@@ -50,7 +50,6 @@
 import org.apache.sling.api.servlets.ServletResolver;
 import org.apache.sling.api.wrappers.SlingHttpServletRequestWrapper;
 import org.apache.sling.api.wrappers.SlingHttpServletResponseWrapper;
-import org.apache.sling.core.CoreConstants;
 import org.apache.sling.core.RequestUtil;
 import org.apache.sling.core.impl.SlingHttpServletRequestImpl;
 import org.apache.sling.core.impl.SlingHttpServletResponseImpl;
@@ -124,7 +123,7 @@
     private String activeServletName;
 
     public RequestData(SlingMainServlet slingMainServlet,
-            ResourceResolver resourceResolver, HttpServletRequest request,
+            HttpServletRequest request,
             HttpServletResponse response) {
 
         this.slingMainServlet = slingMainServlet;
@@ -138,13 +137,18 @@
             servletResponse);
 
         this.requestProgressTracker = new SlingRequestProgressTracker();
-
-        this.resourceResolver = resourceResolver;
     }
 
-    public Resource initResource() {
+    public Resource initResource(ResourceResolver resourceResolver) {
+        // keep the resource resolver for request processing
+        this.resourceResolver = resourceResolver;
+        
         // resolve the resource
+        requestProgressTracker.startTimer("ResourceResolution");
         Resource resource = resourceResolver.resolve(getServletRequest());
+        requestProgressTracker.logTimer("ResourceResolution",
+            "URI={0} resolves to Resource={1}",
+            getServletRequest().getRequestURI(), resource);
         return resource;
     }
 
@@ -157,7 +161,11 @@
         // finally resolve the servlet for the resource
         ServletResolver sr = slingMainServlet.getServletResolver();
         if (sr != null) {
+            requestProgressTracker.startTimer("ServletResolution");
             Servlet servlet = sr.resolveServlet(slingRequest);
+            requestProgressTracker.logTimer("ServletResolution",
+                "URI={0} handled by Servlet={1}",
+                getServletRequest().getRequestURI(), servlet.getServletInfo());
             contentData.setServlet(servlet);
         } else {
             log.warn("init(): No ServletResolver available");

Modified: incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/request/SlingRequestProgressTracker.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/request/SlingRequestProgressTracker.java?rev=635888&r1=635887&r2=635888&view=diff
==============================================================================
--- incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/request/SlingRequestProgressTracker.java (original)
+++ incubator/sling/trunk/sling/core/src/main/java/org/apache/sling/core/impl/request/SlingRequestProgressTracker.java Tue Mar 11 04:18:49 2008
@@ -97,6 +97,12 @@
      * @see #dumpText(PrintWriter)
      */
     private static final String DUMP_FORMAT = "%1$7d (%2$tF %2$tT) %3$s%n";
+    
+    /**
+     * The name of the timer tracking the processing time of the complete
+     * process.
+     */
+    private static final String REQUEST_PROCESSING_TIMER = "Request Processing";
 
     /**
      * The system time at creation of this instance or the last {@link #reset()}.
@@ -131,8 +137,7 @@
         namedTimerEntries.clear();
 
         // enter start message
-        processingStart = System.currentTimeMillis();
-        log(processingStart, "Starting Request Processing");
+        processingStart = startTimerInternal(REQUEST_PROCESSING_TIMER);
     }
 
     public Iterator<String> getMessages() {
@@ -163,7 +168,8 @@
      * See the class comments for the rough format of each message line.
      */
     public void dump(PrintWriter writer) {
-        log("Dumping SlingRequestProgressTracker Entries");
+        logTimer(REQUEST_PROCESSING_TIMER,
+            "Dumping SlingRequestProgressTracker Entries");
 
         Iterator<String> messages = getMessages();
         while (messages.hasNext()) {
@@ -197,16 +203,25 @@
      * reset to the current time.
      */
     public void startTimer(String name) {
+        startTimerInternal(name);
+    }
+    
+    /**
+     * Actually starts the named timer and returns the start time in
+     * milliseconds
+     */
+    private long startTimerInternal(String name) {
         long timer = System.currentTimeMillis();
         namedTimerEntries.put(name, timer);
 
         log(timer, "Starting " + name);
+
+        return timer;
     }
 
     /**
-     * Logs an entry with the message set to
-     * the name of the timer and the number of milliseconds ellapsed since the
-     * timer start.
+     * Logs an entry with the message set to the name of the timer and the
+     * number of milliseconds ellapsed since the timer start.
      */
     public void logTimer(String name) {
         if (namedTimerEntries.containsKey(name)) {