incubator-sling-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From fmesc...@apache.org
Subject svn commit: r1239517 - in /sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl: ./ log/ request/
Date Thu, 02 Feb 2012 10:28:50 GMT
Author: fmeschbe
Date: Thu Feb  2 10:28:49 2012
New Revision: 1239517

URL: http://svn.apache.org/viewvc?rev=1239517&view=rev
Log:
SLING-2389 Install request logging as a Servlet API filter to catch all requests
  - Add a new log parameter 'y' to emit the HttpServletRequest.getAuthType()
  - Refactor RequestLogger to register RequestLoggerService instances according to the
     request and access log configuration
  - RequestLoggerFilter is only active if at least one RequestLoggerService is registered
  - RequestLoggerFilter takes no configuration

Added:
    sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/log/RequestLoggerFilter.java
    sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/log/RequestLoggerRequest.java
    sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/log/RequestLoggerResponse.java
Modified:
    sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/SlingMainServlet.java
    sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/SlingRequestProcessorImpl.java
    sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/log/CustomLogFormat.java
    sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/log/RequestLogger.java
    sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/log/RequestLoggerService.java
    sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/request/RequestData.java

Modified: sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/SlingMainServlet.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/SlingMainServlet.java?rev=1239517&r1=1239516&r2=1239517&view=diff
==============================================================================
--- sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/SlingMainServlet.java (original)
+++ sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/SlingMainServlet.java Thu Feb  2 10:28:49 2012
@@ -56,7 +56,6 @@ import org.apache.sling.engine.SlingRequ
 import org.apache.sling.engine.impl.filter.ServletFilterManager;
 import org.apache.sling.engine.impl.helper.RequestListenerManager;
 import org.apache.sling.engine.impl.helper.SlingServletContext;
-import org.apache.sling.engine.impl.log.RequestLogger;
 import org.apache.sling.engine.impl.parameters.ParameterSupport;
 import org.apache.sling.engine.impl.request.RequestData;
 import org.apache.sling.engine.impl.request.RequestHistoryConsolePlugin;
@@ -82,7 +81,6 @@ import org.slf4j.LoggerFactory;
 })
 @References( {
     @Reference(name = "ErrorHandler", referenceInterface = ErrorHandler.class, cardinality = ReferenceCardinality.OPTIONAL_UNARY, policy = ReferencePolicy.DYNAMIC, bind = "setErrorHandler", unbind = "unsetErrorHandler"),
-    @Reference(name = "RequestLogger", referenceInterface = RequestLogger.class, cardinality = ReferenceCardinality.OPTIONAL_UNARY, policy = ReferencePolicy.DYNAMIC, bind = "setRequestLogger", unbind = "unsetRequestLogger"),
     @Reference(name = "ServletResolver", referenceInterface = ServletResolver.class, cardinality = ReferenceCardinality.OPTIONAL_UNARY, policy = ReferencePolicy.DYNAMIC, bind = "setServletResolver", unbind = "unsetServletResolver"),
     @Reference(name = "MimeTypeService", referenceInterface = MimeTypeService.class, cardinality = ReferenceCardinality.OPTIONAL_UNARY, policy = ReferencePolicy.DYNAMIC, bind = "setMimeTypeService", unbind = "unsetMimeTypeService"),
     @Reference(name = "AuthenticationSupport", referenceInterface = AuthenticationSupport.class, cardinality = ReferenceCardinality.OPTIONAL_UNARY, policy = ReferencePolicy.DYNAMIC, bind = "setAuthenticationSupport", unbind = "unsetAuthenticationSupport") })
@@ -522,14 +520,6 @@ public class SlingMainServlet extends Ge
         requestProcessor.unsetServletResolver(servletResolver);
     }
 
-    public void setRequestLogger(final RequestLogger requestLogger) {
-        requestProcessor.setRequestLogger(requestLogger);
-    }
-
-    public void unsetRequestLogger(final RequestLogger requestLogger) {
-        requestProcessor.unsetRequestLogger(requestLogger);
-    }
-
     public void setMimeTypeService(final MimeTypeService mimeTypeService) {
         slingHttpContext.setMimeTypeService(mimeTypeService);
     }

Modified: sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/SlingRequestProcessorImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/SlingRequestProcessorImpl.java?rev=1239517&r1=1239516&r2=1239517&view=diff
==============================================================================
--- sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/SlingRequestProcessorImpl.java (original)
+++ sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/SlingRequestProcessorImpl.java Thu Feb  2 10:28:49 2012
@@ -53,7 +53,6 @@ import org.apache.sling.engine.impl.filt
 import org.apache.sling.engine.impl.filter.ServletFilterManager;
 import org.apache.sling.engine.impl.filter.ServletFilterManager.FilterChainType;
 import org.apache.sling.engine.impl.filter.SlingComponentFilterChain;
-import org.apache.sling.engine.impl.log.RequestLogger;
 import org.apache.sling.engine.impl.request.ContentData;
 import org.apache.sling.engine.impl.request.RequestData;
 import org.apache.sling.engine.impl.request.RequestHistoryConsolePlugin;
@@ -72,8 +71,6 @@ public class SlingRequestProcessorImpl i
 
     private ErrorHandler errorHandler = defaultErrorHandler;
 
-    private RequestLogger requestLogger;
-
     private ServletResolver servletResolver;
 
     private ServletFilterManager filterManager;
@@ -96,16 +93,6 @@ public class SlingRequestProcessorImpl i
         }
     }
 
-    void setRequestLogger(final RequestLogger requestLogger) {
-        this.requestLogger = requestLogger;
-    }
-
-    void unsetRequestLogger(final RequestLogger requestLogger) {
-        if (this.requestLogger == requestLogger) {
-            this.requestLogger = null;
-        }
-    }
-
     void setServletResolver(final ServletResolver servletResolver) {
         this.servletResolver = servletResolver;
     }
@@ -139,11 +126,6 @@ public class SlingRequestProcessorImpl i
         // record the request for the web console display
         RequestHistoryConsolePlugin.recordRequest(request);
 
-        // request entry log
-        if (requestLogger != null) {
-            requestLogger.logRequestEntry(request, response);
-        }
-
         long startTimestamp = System.currentTimeMillis();
 
         try {
@@ -245,11 +227,6 @@ public class SlingRequestProcessorImpl i
             if (mbean != null) {
                 mbean.addRequestDuration(elapsed);
             }
-
-            // request exit log
-            if (requestLogger != null) {
-                requestLogger.logRequestExit(request, response);
-            }
         }
     }
 

Modified: sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/log/CustomLogFormat.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/log/CustomLogFormat.java?rev=1239517&r1=1239516&r2=1239517&view=diff
==============================================================================
--- sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/log/CustomLogFormat.java (original)
+++ sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/log/CustomLogFormat.java Thu Feb  2 10:28:49 2012
@@ -31,9 +31,8 @@ import java.util.Locale;
 
 import javax.servlet.http.Cookie;
 
-import org.apache.sling.api.SlingHttpServletRequest;
-import org.apache.sling.api.resource.Resource;
-import org.apache.sling.engine.impl.SlingHttpServletResponseImpl;
+import org.apache.sling.engine.impl.request.RequestData;
+import org.osgi.service.http.HttpContext;
 
 /**
  * The <code>CustomLogFormat</code> class implements the support for log format
@@ -73,9 +72,9 @@ class CustomLogFormat {
      *         formatter has not been initialized with a valid log format
      *         pattern.
      */
-    String format(SlingHttpServletRequest request, SlingHttpServletResponseImpl response) {
+    String format(RequestLoggerRequest request, RequestLoggerResponse response) {
         if (this.logParameters != null) {
-            StringBuffer buf = new StringBuffer();
+            StringBuilder buf = new StringBuilder();
             for (int i=0; i < this.logParameters.length; i++) {
                 this.logParameters[i].print(buf, request, response);
             }
@@ -273,6 +272,10 @@ class CustomLogFormat {
                 param = new ServerNameParameter();
                 break;
 
+            case 'y':
+                param = new AuthTypeParameter();
+                break;
+
             case 'X': // no supported fall through to default
             case 'I': // no supported fall through to default
             case 'O': // no supported fall through to default
@@ -280,12 +283,13 @@ class CustomLogFormat {
             case 'l': // no supported fall through to default
             case 'e': // no supported fall through to default
             default:
-                param = new NonImplementedParameter((char) c, name);
+                param = new NonImplementedParameter(name);
                 break;
         }
 
         if (param instanceof BaseParameter) {
             BaseParameter baseParam = (BaseParameter) param;
+            baseParam.setParName((char) c);
             baseParam.setRequired(required);
             baseParam.setStatusLimits(statCodes);
         }
@@ -346,7 +350,7 @@ class CustomLogFormat {
     //---------- Parameter support --------------------------------------------
 
     static interface Parameter {
-        void print(StringBuffer dest, SlingHttpServletRequest request, SlingHttpServletResponseImpl response);
+        void print(StringBuilder dest, RequestLoggerRequest request, RequestLoggerResponse response);
     }
 
     static class PlainTextParameter implements Parameter {
@@ -354,8 +358,8 @@ class CustomLogFormat {
         PlainTextParameter(String value) {
             this.value = value;
         }
-        public void print(StringBuffer dest, SlingHttpServletRequest request,
-                SlingHttpServletResponseImpl response) {
+        public void print(StringBuilder dest, RequestLoggerRequest request,
+                RequestLoggerResponse response) {
             dest.append(this.value);
         }
         public String toString() {
@@ -366,23 +370,17 @@ class CustomLogFormat {
     abstract static class BaseParameter implements Parameter {
         private int[] statusLimits;
         private boolean required;
-        private final char parName;
+        private char parName;
         private final String parParam;
-
         private final boolean isRequest;
 
-        protected BaseParameter(int[] statusLimits, boolean required, char parName, String parParam, boolean isRequest) {
-            this.statusLimits = statusLimits;
-            this.required = required;
-            this.parName = parName;
+        protected BaseParameter(String parParam, boolean isRequest) {
             this.parParam = parParam;
             this.isRequest = isRequest;
         }
 
-        protected BaseParameter(char parName, String parParam, boolean isRequest) {
+        public void setParName(char parName) {
             this.parName = parName;
-            this.parParam = parParam;
-            this.isRequest = isRequest;
         }
 
         public void setStatusLimits(int[] statusLimits) {
@@ -393,10 +391,10 @@ class CustomLogFormat {
             this.required = required;
         }
 
-        protected abstract String getValue(SlingHttpServletRequest request);
-        protected abstract String getValue(SlingHttpServletResponseImpl response);
+        protected abstract String getValue(RequestLoggerRequest request);
+        protected abstract String getValue(RequestLoggerResponse response);
 
-        public final void print(StringBuffer dest, SlingHttpServletRequest request, SlingHttpServletResponseImpl response) {
+        public final void print(StringBuilder dest, RequestLoggerRequest request, RequestLoggerResponse response) {
             if (this.printOk(response.getStatus())) {
                 String value = this.isRequest ? this.getValue(request) : this.getValue(response);
                 dest.append((value == null) ? "-" : value);
@@ -516,71 +514,71 @@ class CustomLogFormat {
 
     static class NonImplementedParameter extends BaseParameter {
 
-        NonImplementedParameter(char parName, String parParam) {
-            super(parName, parParam, true);
+        NonImplementedParameter(String parParam) {
+            super(parParam, true);
         }
 
-        protected String getValue(SlingHttpServletRequest request) {
+        protected String getValue(RequestLoggerRequest request) {
             return null;
         }
 
-        protected String getValue(SlingHttpServletResponseImpl response) {
+        protected String getValue(RequestLoggerResponse response) {
             return null;
         }
     }
 
     static class ThreadParameter extends BaseParameter {
         public ThreadParameter(String parParam) {
-            super('P', parParam, true);
+            super(parParam, true);
         }
 
-        protected String getValue(SlingHttpServletRequest request) {
+        protected String getValue(RequestLoggerRequest request) {
             return Thread.currentThread().getName();
         }
 
-        protected String getValue(SlingHttpServletResponseImpl response) {
+        protected String getValue(RequestLoggerResponse response) {
             return null;
         }
     }
 
     static class ParamParameter extends BaseParameter {
         public ParamParameter(String parParam) {
-            super('M', parParam, true);
+            super(parParam, true);
         }
 
-        protected String getValue(SlingHttpServletRequest request) {
+        protected String getValue(RequestLoggerRequest request) {
             return request.getParameter(this.getParParam());
         }
 
-        protected String getValue(SlingHttpServletResponseImpl response) {
+        protected String getValue(RequestLoggerResponse response) {
             return null;
         }
     }
 
     static class IdParameter extends BaseParameter {
         public IdParameter() {
-            super('R', null, false);
+            super(null, false);
         }
 
-        protected String getValue(SlingHttpServletRequest request) {
+        protected String getValue(RequestLoggerRequest request) {
             return null;
         }
 
-        protected String getValue(SlingHttpServletResponseImpl response) {
+        protected String getValue(RequestLoggerResponse response) {
             return String.valueOf(response.getRequestId());
         }
     }
 
     static class ByteCountParameter extends BaseParameter {
         public ByteCountParameter(char c) {
-            super(c, null, false);
+            super(null, false);
         }
 
-        protected String getValue(SlingHttpServletRequest request) {
+        protected String getValue(RequestLoggerRequest request) {
             return null;
         }
 
-        protected String getValue(SlingHttpServletResponseImpl response) {
+        protected String getValue(RequestLoggerResponse response) {
             int count = response.getCount();
             if (count == 0) {
                 return (this.getParName() == 'b') ? "-" : "0";
@@ -615,16 +613,16 @@ class CustomLogFormat {
         private final boolean requestStart;
 
         public TimeParameter(String parParam) {
-            super('t', parParam, false);
+            super(parParam, false);
 
             this.requestStart = parParam== null || !parParam.equals("end");
         }
 
-        protected String getValue(SlingHttpServletRequest request) {
+        protected String getValue(RequestLoggerRequest request) {
             return null;
         }
 
-        protected String getValue(SlingHttpServletResponseImpl response) {
+        protected String getValue(RequestLoggerResponse response) {
             long time = this.requestStart ? response.getRequestStart() : response.getRequestEnd();
             return timeFormatted(time);
         }
@@ -656,15 +654,15 @@ class CustomLogFormat {
     static class DurationParameter extends BaseParameter {
         private final boolean seconds;
         public DurationParameter(boolean seconds) {
-            super((seconds ? 'T' : 'D'), null, false);
+            super(null, false);
             this.seconds = seconds;
         }
 
-        protected String getValue(SlingHttpServletRequest request) {
+        protected String getValue(RequestLoggerRequest request) {
             return null;
         }
 
-        protected String getValue(SlingHttpServletResponseImpl response) {
+        protected String getValue(RequestLoggerResponse response) {
             long time = response.getRequestDuration();
             if (this.seconds) {
                 time /= 1000;
@@ -675,95 +673,98 @@ class CustomLogFormat {
 
     static class RemoteIPParameter extends BaseParameter {
         public RemoteIPParameter() {
-            super('a', null, true);
+            super(null, true);
         }
 
-        protected String getValue(SlingHttpServletRequest request) {
+        protected String getValue(RequestLoggerRequest request) {
             return request.getRemoteAddr();
         }
 
-        protected String getValue(SlingHttpServletResponseImpl response) {
+        protected String getValue(RequestLoggerResponse response) {
             return null;
         }
     }
 
     static class RemoteHostParameter extends BaseParameter {
         public RemoteHostParameter() {
-            super('h', null, true);
+            super(null, true);
         }
 
-        protected String getValue(SlingHttpServletRequest request) {
+        protected String getValue(RequestLoggerRequest request) {
             return request.getRemoteHost();
         }
 
-        protected String getValue(SlingHttpServletResponseImpl response) {
+        protected String getValue(RequestLoggerResponse response) {
             return null;
         }
     }
 
     static class LocalIPParameter extends BaseParameter {
         public LocalIPParameter() {
-            super('A', null, true);
+            super(null, true);
         }
 
-        protected String getValue(SlingHttpServletRequest request) {
+        protected String getValue(RequestLoggerRequest request) {
             return request.getLocalAddr();
         }
 
-        protected String getValue(SlingHttpServletResponseImpl response) {
+        protected String getValue(RequestLoggerResponse response) {
             return null;
         }
     }
 
     static class LocalPortParameter extends BaseParameter {
         public LocalPortParameter() {
-            super('p', null, true);
+            super(null, true);
         }
 
-        protected String getValue(SlingHttpServletRequest request) {
+        protected String getValue(RequestLoggerRequest request) {
             return String.valueOf(request.getServerPort());
         }
 
-        protected String getValue(SlingHttpServletResponseImpl response) {
+        protected String getValue(RequestLoggerResponse response) {
             return null;
         }
     }
 
     static class ServerNameParameter extends BaseParameter {
         public ServerNameParameter() {
-            super('v', null, true);
+            super(null, true);
         }
 
-        protected String getValue(SlingHttpServletRequest request) {
+        protected String getValue(RequestLoggerRequest request) {
             return request.getServerName();
         }
 
-        protected String getValue(SlingHttpServletResponseImpl response) {
+        protected String getValue(RequestLoggerResponse response) {
             return null;
         }
     }
 
     static class ContentPathParameter extends BaseParameter {
         public ContentPathParameter() {
-            super('f', null, true);
+            super(null, true);
         }
 
-        protected String getValue(SlingHttpServletRequest request) {
-            Resource resource = request.getResource();
-            return (resource != null) ? resource.getPath() : null;
+        protected String getValue(RequestLoggerRequest request) {
+            final Object resourcePath = request.getAttribute(RequestData.REQUEST_RESOURCE_PATH_ATTR);
+            if (resourcePath instanceof String) {
+                return (String) resourcePath;
+            }
+            return null;
         }
 
-        protected String getValue(SlingHttpServletResponseImpl response) {
+        protected String getValue(RequestLoggerResponse response) {
             return null;
         }
     }
 
     static class FirstRequestLineParameter extends BaseParameter {
         public FirstRequestLineParameter() {
-            super('r', null, true);
+            super(null, true);
         }
 
-        protected String getValue(SlingHttpServletRequest request) {
+        protected String getValue(RequestLoggerRequest request) {
             String query = request.getQueryString();
             query = (query == null || query.length() == 0) ? "" : "?" + query;
 
@@ -771,92 +772,116 @@ class CustomLogFormat {
                 + " " + request.getProtocol();
         }
 
-        protected String getValue(SlingHttpServletResponseImpl response) {
+        protected String getValue(RequestLoggerResponse response) {
             return null;
         }
     }
 
     static class ProtocolParameter extends BaseParameter {
         public ProtocolParameter() {
-            super('H', null, true);
+            super(null, true);
         }
 
-        protected String getValue(SlingHttpServletRequest request) {
+        protected String getValue(RequestLoggerRequest request) {
             return request.getProtocol();
         }
 
-        protected String getValue(SlingHttpServletResponseImpl response) {
+        protected String getValue(RequestLoggerResponse response) {
             return null;
         }
     }
 
     static class MethodParameter extends BaseParameter {
         public MethodParameter() {
-            super('m', null, true);
+            super(null, true);
         }
 
-        protected String getValue(SlingHttpServletRequest request) {
+        protected String getValue(RequestLoggerRequest request) {
             return request.getMethod();
         }
 
-        protected String getValue(SlingHttpServletResponseImpl response) {
+        protected String getValue(RequestLoggerResponse response) {
             return null;
         }
     }
 
     static class RequestParameter extends BaseParameter {
         public RequestParameter() {
-            super('U', null, true);
+            super(null, true);
         }
 
-        protected String getValue(SlingHttpServletRequest request) {
+        protected String getValue(RequestLoggerRequest request) {
             return request.getRequestURI();
         }
 
-        protected String getValue(SlingHttpServletResponseImpl response) {
+        protected String getValue(RequestLoggerResponse response) {
             return null;
         }
     }
 
     static class QueryParameter extends BaseParameter {
         public QueryParameter() {
-            super('q', null, true);
+            super(null, true);
         }
 
-        protected String getValue(SlingHttpServletRequest request) {
+        protected String getValue(RequestLoggerRequest request) {
             String query = request.getQueryString();
             return (query == null || query.length() == 0) ? "" : "?" + query;
         }
 
-        protected String getValue(SlingHttpServletResponseImpl response) {
+        protected String getValue(RequestLoggerResponse response) {
             return null;
         }
     }
 
     static class UserParameter extends BaseParameter {
         public UserParameter() {
-            super('u', null, true);
+            super(null, true);
         }
 
-        protected String getValue(SlingHttpServletRequest request) {
+        protected String getValue(RequestLoggerRequest request) {
+            final Object user = request.getAttribute(HttpContext.REMOTE_USER);
+            if (user instanceof String) {
+                return (String) user;
+            }
+
             return request.getRemoteUser();
         }
 
-        protected String getValue(SlingHttpServletResponseImpl response) {
+        protected String getValue(RequestLoggerResponse response) {
+            return null;
+        }
+    }
+
+    static class AuthTypeParameter extends BaseParameter {
+        public AuthTypeParameter() {
+            super(null, true);
+        }
+
+        protected String getValue(RequestLoggerRequest request) {
+            final Object authType = request.getAttribute(HttpContext.AUTHENTICATION_TYPE);
+            if (authType instanceof String) {
+                return (String) authType;
+            }
+
+            return request.getAuthType();
+        }
+
+        protected String getValue(RequestLoggerResponse response) {
             return null;
         }
     }
 
     static class StatusParameter extends BaseParameter {
         public StatusParameter() {
-            super('s', null, false);
+            super(null, false);
         }
 
-        protected String getValue(SlingHttpServletRequest request) {
+        protected String getValue(RequestLoggerRequest request) {
             return null;
         }
 
-        protected String getValue(SlingHttpServletResponseImpl response) {
+        protected String getValue(RequestLoggerResponse response) {
             return String.valueOf(response.getStatus());
         }
     }
@@ -864,16 +889,24 @@ class CustomLogFormat {
     static class CookieParameter extends BaseParameter {
         private String cookieName;
         CookieParameter(String cookieName, boolean isRequest) {
-            super('C', cookieName, isRequest);
+            super(cookieName, isRequest);
             this.cookieName = cookieName;
         }
 
-        protected String getValue(SlingHttpServletRequest request) {
-            Cookie cookie = request.getCookie(cookieName);
-            return (cookie == null) ? null : escape(cookie.toString());
+        protected String getValue(RequestLoggerRequest request) {
+            final Cookie[] cookies = request.getCookies();
+            if (cookies != null) {
+                for (int i = 0; i < cookies.length; i++) {
+                    if (cookies[i].getName().equals(cookieName)) {
+                        return escape(cookies[i].toString());
+                    }
+                }
+            }
+
+            return null;
         }
 
-        protected String getValue(SlingHttpServletResponseImpl response) {
+        protected String getValue(RequestLoggerResponse response) {
             Cookie cookie = response.getCookie(this.cookieName);
             return (cookie == null) ? null : escape(cookie.toString());
         }
@@ -883,11 +916,11 @@ class CustomLogFormat {
     static class HeaderParameter extends BaseParameter {
         private String headerName;
         HeaderParameter(String headerName, boolean isRequest) {
-            super((isRequest ? 'i' : 'o'), headerName, isRequest);
+            super(headerName, isRequest);
             this.headerName = headerName;
         }
 
-        protected String getValue(SlingHttpServletRequest request) {
+        protected String getValue(RequestLoggerRequest request) {
             Enumeration<?> values = request.getHeaders(this.headerName);
             if (values == null || !values.hasMoreElements()) {
                 return null;
@@ -900,7 +933,7 @@ class CustomLogFormat {
             return escape(value);
         }
 
-        protected String getValue(SlingHttpServletResponseImpl response) {
+        protected String getValue(RequestLoggerResponse response) {
             return escape(response.getHeaders(this.headerName));
         }
     }

Modified: sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/log/RequestLogger.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/log/RequestLogger.java?rev=1239517&r1=1239516&r2=1239517&view=diff
==============================================================================
--- sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/log/RequestLogger.java (original)
+++ sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/log/RequestLogger.java Thu Feb  2 10:28:49 2012
@@ -18,21 +18,17 @@
  */
 package org.apache.sling.engine.impl.log;
 
-import java.util.Dictionary;
+import java.util.HashMap;
 import java.util.Hashtable;
+import java.util.Map;
+import java.util.Map.Entry;
 
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Properties;
 import org.apache.felix.scr.annotations.Property;
 import org.apache.felix.scr.annotations.PropertyOption;
-import org.apache.felix.scr.annotations.Reference;
-import org.apache.felix.scr.annotations.ReferenceCardinality;
-import org.apache.felix.scr.annotations.ReferencePolicy;
-import org.apache.felix.scr.annotations.Service;
-import org.apache.sling.api.SlingHttpServletRequest;
-import org.apache.sling.api.SlingHttpServletResponse;
-import org.apache.sling.engine.impl.SlingHttpServletResponseImpl;
 import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
 
 /**
  * The <code>RequestLogger</code> is a request level filter, which
@@ -42,16 +38,11 @@ import org.osgi.framework.BundleContext;
  * acting just before the request handling terminates.
  *
  */
-@Component(immediate=true,metatype=true,label="%request.log.name",description="%request.log.description")
+@Component(metatype=true,label="%request.log.name",description="%request.log.description")
 @Properties({
     @Property(name="service.description",value="Request Logger"),
     @Property(name="service.vendor",value="The Apache Software Foundation")
 })
-@Service(value=RequestLogger.class)
-@Reference(name="RequestLoggerService",
-       referenceInterface=RequestLoggerService.class,
-       cardinality=ReferenceCardinality.OPTIONAL_MULTIPLE,
-       policy=ReferencePolicy.DYNAMIC)
 public class RequestLogger {
 
     @Property(value="logs/request.log")
@@ -100,20 +91,6 @@ public class RequestLogger {
     private static final String ACCESS_LOG_FORMAT = "%a %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"";
 
     /**
-     * The list of {@link RequestLoggerService} called when the request enters
-     * processing. The order of the services in this list determined by the
-     * registration order.
-     */
-    private RequestLoggerService[] requestEntry;
-
-    /**
-     * The list of {@link RequestLoggerService} called when the request is about
-     * to exit processing. The order of the services in this list determined by
-     * the registration order.
-     */
-    private RequestLoggerService[] requestExit;
-
-    /**
      * A special request logger service, which writes the request log message at
      * request start time. This logger logs a message with the format
      * {@link #REQUEST_LOG_ENTRY_FORMAT}.
@@ -134,33 +111,11 @@ public class RequestLogger {
      */
     private RequestLoggerService accessLog;
 
-    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);
-                }
-            }
-        }
-    }
-
-    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
-            if (this.requestExit != null) {
-                for (int i = 0; i < this.requestExit.length; i++) {
-                    this.requestExit[i].log(request, loggerResponse);
-                }
-            }
-        }
-    }
+    /**
+     * RequestLoggerService instances created on behalf of the static
+     * configuration.
+     */
+    private Map<ServiceRegistration, RequestLoggerService> services = new HashMap<ServiceRegistration, RequestLoggerService>();
 
     // ---------- SCR Integration ----------------------------------------------
 
@@ -174,16 +129,7 @@ public class RequestLogger {
      * @param osgiContext The OSGi Component Context providing the configuration
      *            data and access into the system.
      */
-    protected void activate(
-            org.osgi.service.component.ComponentContext osgiContext) {
-
-        BundleContext bundleContext = osgiContext.getBundleContext();
-        @SuppressWarnings("unchecked")
-        Dictionary props = osgiContext.getProperties();
-
-        // initialize the FileRequestLog with sling.home as the root for
-        // relative log file paths
-        FileRequestLog.init(bundleContext.getProperty("sling.home"));
+    protected void activate(BundleContext bundleContext, Map<String, Object> props) {
 
         // prepare the request loggers if a name is configured and the
         // request loggers are enabled
@@ -191,31 +137,20 @@ public class RequestLogger {
         Object requestLogEnabled = props.get(PROP_REQUEST_LOG_ENABLED);
         if (requestLogName != null && requestLogEnabled instanceof Boolean
             && ((Boolean) requestLogEnabled).booleanValue()) {
-
             Object requestLogType = props.get(PROP_REQUEST_LOG_OUTPUT_TYPE);
-
-            this.requestLogEntry = this.createRequestLoggerService(bundleContext, true,
-                REQUEST_LOG_ENTRY_FORMAT, requestLogName, requestLogType);
-            this.requestLogExit = this.createRequestLoggerService(bundleContext, false,
-                REQUEST_LOG_EXIT_FORMAT, requestLogName, requestLogType);
-
-            this.bindRequestLoggerService(this.requestLogEntry);
-            this.bindRequestLoggerService(this.requestLogExit);
+            createRequestLoggerService(services, bundleContext, true, REQUEST_LOG_ENTRY_FORMAT, requestLogName,
+                requestLogType);
+            createRequestLoggerService(services, bundleContext, false, REQUEST_LOG_EXIT_FORMAT, requestLogName,
+                requestLogType);
         }
 
         // prepare the access logger if a name is configured and the
         // access logger is enabled
         Object accessLogName = props.get(PROP_ACCESS_LOG_OUTPUT);
         Object accessLogEnabled = props.get(PROP_ACCESS_LOG_ENABLED);
-        if (accessLogName != null && accessLogEnabled instanceof Boolean
-            && ((Boolean) accessLogEnabled).booleanValue()) {
-
+        if (accessLogName != null && accessLogEnabled instanceof Boolean && ((Boolean) accessLogEnabled).booleanValue()) {
             Object accessLogType = props.get(PROP_ACCESS_LOG_OUTPUT_TYPE);
-
-            this.accessLog = this.createRequestLoggerService(bundleContext, false,
-                ACCESS_LOG_FORMAT, accessLogName, accessLogType);
-
-            this.bindRequestLoggerService(this.accessLog);
+            createRequestLoggerService(services, bundleContext, false, ACCESS_LOG_FORMAT, accessLogName, accessLogType);
         }
     }
 
@@ -228,60 +163,12 @@ public class RequestLogger {
      * @param osgiContext The OSGi Component Context providing the configuration
      *            data and access into the system.
      */
-    protected void deactivate(
-            org.osgi.service.component.ComponentContext osgiContext) {
-
-        // remove the loggers if they have been set up
-        if (this.requestLogEntry != null) {
-            this.unbindRequestLoggerService(this.requestLogEntry);
-            this.requestLogEntry.shutdown();
-            this.requestLogEntry = null;
-        }
-        if (this.requestLogExit != null) {
-            this.unbindRequestLoggerService(this.requestLogExit);
-            this.requestLogExit.shutdown();
-            this.requestLogExit = null;
-        }
-        if (this.accessLog != null) {
-            this.unbindRequestLoggerService(this.accessLog);
-            this.accessLog.shutdown();
-            this.accessLog = null;
-        }
-
-        // hack to ensure all log files are closed
-        FileRequestLog.dispose();
-    }
-
-    /**
-     * Binds a <code>RequestLoggerService</code> to be used during request
-     * filter.
-     *
-     * @param requestLoggerService The <code>RequestLoggerService</code> to
-     *            use.
-     */
-    protected void bindRequestLoggerService(
-            RequestLoggerService requestLoggerService) {
-        if (requestLoggerService.isOnEntry()) {
-            this.requestEntry = this.addService(this.requestEntry, requestLoggerService);
-        } else {
-            this.requestExit = this.addService(this.requestExit, requestLoggerService);
-        }
-    }
-
-    /**
-     * Binds a <code>RequestLoggerService</code> to be used during request
-     * filter.
-     *
-     * @param requestLoggerService The <code>RequestLoggerService</code> to
-     *            use.
-     */
-    protected void unbindRequestLoggerService(
-            RequestLoggerService requestLoggerService) {
-        if (requestLoggerService.isOnEntry()) {
-            this.requestEntry = this.removeService(this.requestEntry, requestLoggerService);
-        } else {
-            this.requestExit = this.removeService(this.requestExit, requestLoggerService);
+    protected void deactivate() {
+        for (Entry<ServiceRegistration, RequestLoggerService> entry : services.entrySet()) {
+            entry.getKey().unregister();
+            entry.getValue().shutdown();
         }
+        services.clear();
     }
 
     /**
@@ -306,82 +193,16 @@ public class RequestLogger {
      * @return The functional and prepared <code>RequestLoggerService</code>
      *         instance.
      */
-    private RequestLoggerService createRequestLoggerService(
-            BundleContext bundleContext, boolean onEntry, Object format,
-            Object output, Object outputType) {
+    private static void createRequestLoggerService(Map<ServiceRegistration, RequestLoggerService> services,
+            BundleContext bundleContext, boolean onEntry, Object format, Object output, Object outputType) {
         final Hashtable<String, Object> config = new Hashtable<String, Object>();
-        config.put(RequestLoggerService.PARAM_ON_ENTRY, onEntry
-                ? Boolean.TRUE
-                : Boolean.FALSE);
+        config.put(RequestLoggerService.PARAM_ON_ENTRY, onEntry ? Boolean.TRUE : Boolean.FALSE);
         config.put(RequestLoggerService.PARAM_FORMAT, format);
         config.put(RequestLoggerService.PARAM_OUTPUT, output);
         config.put(RequestLoggerService.PARAM_OUTPUT_TYPE, outputType);
 
-        return new RequestLoggerService(bundleContext, config);
+        final RequestLoggerService service = new RequestLoggerService(bundleContext, config);
+        final ServiceRegistration reg = bundleContext.registerService(service.getClass().getName(), service, config);
+        services.put(reg, service);
     }
-
-    /**
-     * Creates a new list of request logger services from the existing list
-     * appending the new logger. This method does not check, whether the logger
-     * has already been added or not and so may add the the logger multiple
-     * times. It is the responsibility of the caller to make sure to not add
-     * services multiple times.
-     *
-     * @param list The list to add the new service to
-     * @param requestLoggerService The service to append to the list
-     * @param A new list with the added service at the end.
-     */
-    private RequestLoggerService[] addService(RequestLoggerService[] list,
-            RequestLoggerService requestLoggerService) {
-        if (list == null) {
-            return new RequestLoggerService[] { requestLoggerService };
-        }
-
-        // add the service to the list, must not be in the list yet due to
-        // the SCR contract
-        RequestLoggerService[] newList = new RequestLoggerService[list.length + 1];
-        System.arraycopy(list, 0, newList, 0, list.length);
-        newList[list.length] = requestLoggerService;
-
-        return newList;
-    }
-
-    /**
-     * Creates a new list of request logger services from the existing list by
-     * removing the named logger. The logger is searched for by referential
-     * equality (comparing the object references) and not calling the
-     * <code>equals</code> method. If the last element is being removed from
-     * the list, <code>null</code> is returned instead of an empty list.
-     *
-     * @param list The list from which the service is to be removed.
-     * @param requestLoggerService The service to remove.
-     * @return The list without the service. This may be the same list if the
-     *         service is not in the list or may be <code>null</code> if the
-     *         last service has just been removed from the list.
-     */
-    private RequestLoggerService[] removeService(RequestLoggerService[] list,
-            RequestLoggerService requestLoggerService) {
-
-        RequestLoggerService[] newList = null;
-        for (int i = 0; list != null && i < list.length; i++) {
-            if (list[i] == requestLoggerService) {
-                newList = new RequestLoggerService[list.length - 1];
-
-                // if not first take over the leading elements
-                if (i > 0) {
-                    System.arraycopy(list, 0, newList, 0, i);
-                }
-
-                // if not the last element, shift rest to the left
-                if (i < list.length - 1) {
-                    System.arraycopy(list, i + 1, newList, 0, newList.length
-                        - i);
-                }
-            }
-        }
-
-        // return the new list if at least one entry is contained
-        return (newList != null && newList.length > 0) ? newList : null;
-    }
-
 }

Added: sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/log/RequestLoggerFilter.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/log/RequestLoggerFilter.java?rev=1239517&view=auto
==============================================================================
--- sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/log/RequestLoggerFilter.java (added)
+++ sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/log/RequestLoggerFilter.java Thu Feb  2 10:28:49 2012
@@ -0,0 +1,238 @@
+/*
+ * 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.sling.engine.impl.log;
+
+import java.io.IOException;
+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.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.ConfigurationPolicy;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Properties;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.ReferencePolicy;
+import org.apache.felix.scr.annotations.Service;
+import org.osgi.framework.BundleContext;
+
+/**
+ * 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
+ * acting just before the request handling terminates.
+ *
+ */
+@Component(immediate = true, policy = ConfigurationPolicy.IGNORE)
+@Properties({
+    @Property(name = "service.description", value = "Request Logger Filter"),
+    @Property(name = "service.vendor", value = "The Apache Software Foundation")
+})
+@Service(value = Filter.class)
+@Reference(
+        name = "RequestLoggerService",
+        referenceInterface = RequestLoggerService.class,
+        cardinality = ReferenceCardinality.MANDATORY_MULTIPLE,
+        policy = ReferencePolicy.DYNAMIC)
+@Property(name = "pattern", value = "/.*")
+public final class RequestLoggerFilter implements Filter {
+
+    private static final RequestLoggerService[] NONE = new RequestLoggerService[0];
+
+    /**
+     * The list of {@link RequestLoggerService} called when the request enters
+     * processing. The order of the services in this list determined by the
+     * registration order.
+     */
+    private RequestLoggerService[] requestEntry = NONE;
+
+    /**
+     * The list of {@link RequestLoggerService} called when the request is about
+     * to exit processing. The order of the services in this list determined by
+     * the registration order.
+     */
+    private RequestLoggerService[] requestExit = NONE;
+
+    public void init(FilterConfig filterConfig) {
+    }
+
+    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
+            ServletException {
+
+        final RequestLoggerRequest rlreq = new RequestLoggerRequest((HttpServletRequest) request);
+        final RequestLoggerResponse rlres = new RequestLoggerResponse((HttpServletResponse) response);
+
+        log(this.requestEntry, rlreq, rlres);
+        try {
+            chain.doFilter(rlreq, rlres);
+        } finally {
+            rlres.requestEnd();
+            log(this.requestExit, rlreq, rlres);
+        }
+    }
+
+    public void destroy() {
+    }
+
+    // ---------- SCR Integration ----------------------------------------------
+
+    /**
+     * Activates this component by setting up the special request entry and exit
+     * request loggers and the access logger as configured in the context
+     * properties. In addition the <code>FileRequestLog</code> class is
+     * initialized with the value of the <code>sling.home</code> context
+     * property to resolve relative log file names.
+     */
+    @Activate
+    @SuppressWarnings("unused")
+    private void activate(BundleContext bundleContext) {
+
+        // initialize the FileRequestLog with sling.home as the root for
+        // relative log file paths
+        FileRequestLog.init(bundleContext.getProperty("sling.home"));
+
+    }
+
+    /**
+     * Deactivates this component by unbinding and shutting down all loggers
+     * setup during activation and finally dispose off the
+     * <code>FileRequestLog</code> class to make sure all shared writers are
+     * closed.
+     */
+    @Deactivate
+    @SuppressWarnings("unused")
+    private void deactivate() {
+        // hack to ensure all log files are closed
+        FileRequestLog.dispose();
+    }
+
+    /**
+     * Binds a <code>RequestLoggerService</code> to be used during request
+     * filter.
+     *
+     * @param requestLoggerService The <code>RequestLoggerService</code> to
+     *            use.
+     */
+    @SuppressWarnings("unused")
+    private void bindRequestLoggerService(
+            RequestLoggerService requestLoggerService) {
+        if (requestLoggerService.isOnEntry()) {
+            this.requestEntry = this.addService(this.requestEntry, requestLoggerService);
+        } else {
+            this.requestExit = this.addService(this.requestExit, requestLoggerService);
+        }
+    }
+
+    /**
+     * Binds a <code>RequestLoggerService</code> to be used during request
+     * filter.
+     *
+     * @param requestLoggerService The <code>RequestLoggerService</code> to
+     *            use.
+     */
+    @SuppressWarnings("unused")
+    private void unbindRequestLoggerService(
+            RequestLoggerService requestLoggerService) {
+        if (requestLoggerService.isOnEntry()) {
+            this.requestEntry = this.removeService(this.requestEntry, requestLoggerService);
+        } else {
+            this.requestExit = this.removeService(this.requestExit, requestLoggerService);
+        }
+    }
+
+    /**
+     * Creates a new list of request logger services from the existing list
+     * appending the new logger. This method does not check, whether the logger
+     * has already been added or not and so may add the the logger multiple
+     * times. It is the responsibility of the caller to make sure to not add
+     * services multiple times.
+     *
+     * @param list The list to add the new service to
+     * @param requestLoggerService The service to append to the list
+     * @param A new list with the added service at the end.
+     */
+    private RequestLoggerService[] addService(RequestLoggerService[] list,
+            RequestLoggerService requestLoggerService) {
+        if (list == NONE) {
+            return new RequestLoggerService[] { requestLoggerService };
+        }
+
+        // add the service to the list, must not be in the list yet due to
+        // the SCR contract
+        RequestLoggerService[] newList = new RequestLoggerService[list.length + 1];
+        System.arraycopy(list, 0, newList, 0, list.length);
+        newList[list.length] = requestLoggerService;
+
+        return newList;
+    }
+
+    /**
+     * Creates a new list of request logger services from the existing list by
+     * removing the named logger. The logger is searched for by referential
+     * equality (comparing the object references) and not calling the
+     * <code>equals</code> method. If the last element is being removed from
+     * the list, <code>NONE</code> is returned instead of an empty list.
+     *
+     * @param list The list from which the service is to be removed.
+     * @param requestLoggerService The service to remove.
+     * @return The list without the service. This may be the same list if the
+     *         service is not in the list or may be <code>NONE</code> if the
+     *         last service has just been removed from the list.
+     */
+    private RequestLoggerService[] removeService(RequestLoggerService[] list,
+            RequestLoggerService requestLoggerService) {
+
+        RequestLoggerService[] newList = NONE;
+        for (int i = 0; i < list.length; i++) {
+            if (list[i] == requestLoggerService) {
+                newList = new RequestLoggerService[list.length - 1];
+
+                // if not first take over the leading elements
+                if (i > 0) {
+                    System.arraycopy(list, 0, newList, 0, i);
+                }
+
+                // if not the last element, shift rest to the left
+                if (i < list.length - 1) {
+                    System.arraycopy(list, i + 1, newList, 0, newList.length
+                        - i);
+                }
+            }
+        }
+
+        // return the new list if at least one entry is contained
+        return (newList.length > 0) ? newList : NONE;
+    }
+
+    private void log(RequestLoggerService[] services, final RequestLoggerRequest request,
+            final RequestLoggerResponse response) {
+        for (int i = 0; i < services.length; i++) {
+            services[i].log(request, response);
+        }
+    }
+}

Added: sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/log/RequestLoggerRequest.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/log/RequestLoggerRequest.java?rev=1239517&view=auto
==============================================================================
--- sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/log/RequestLoggerRequest.java (added)
+++ sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/log/RequestLoggerRequest.java Thu Feb  2 10:28:49 2012
@@ -0,0 +1,30 @@
+/*
+ * 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.sling.engine.impl.log;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+
+class RequestLoggerRequest extends HttpServletRequestWrapper {
+
+    RequestLoggerRequest(HttpServletRequest request) {
+        super(request);
+    }
+
+}

Added: sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/log/RequestLoggerResponse.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/log/RequestLoggerResponse.java?rev=1239517&view=auto
==============================================================================
--- sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/log/RequestLoggerResponse.java (added)
+++ sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/log/RequestLoggerResponse.java Thu Feb  2 10:28:49 2012
@@ -0,0 +1,428 @@
+/*
+ * 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.sling.engine.impl.log;
+
+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 java.util.concurrent.atomic.AtomicLong;
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpServletResponseWrapper;
+
+public class RequestLoggerResponse extends HttpServletResponseWrapper {
+
+    // 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 AtomicLong requestCounter = new AtomicLong();
+
+    // TODO: more content related headers, namely Content-Language should
+    // probably be supported
+
+    // the request counter
+    private long 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;
+
+    public RequestLoggerResponse(HttpServletResponse response) {
+        super(response);
+
+        this.requestId = requestCounter.getAndIncrement();
+        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() {
+//        return requestData;
+//    }
+
+    //---------- SlingHttpServletResponse interface
+
+    @Override
+    public ServletOutputStream getOutputStream() throws IOException {
+        if (this.out == null) {
+            ServletOutputStream sos = getResponse().getOutputStream();
+            this.out = new LoggerResponseOutputStream(sos);
+        }
+        return this.out;
+    }
+
+    @Override
+    public PrintWriter getWriter() throws IOException {
+        if (this.writer == null) {
+            PrintWriter pw = getResponse().getWriter();
+            this.writer = new LoggerResponseWriter(pw);
+        }
+        return this.writer;
+    }
+
+    // ---------- 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 status) throws IOException {
+        super.sendError(status);
+        this.status = status;
+    }
+
+    @Override
+    public void sendError(int status, String message) throws IOException {
+        super.sendError(status, message);
+        this.status = status;
+    }
+
+    @Override
+    public void setStatus(int status, String message) {
+        super.setStatus(status, message);
+        this.status = status;
+    }
+
+    @Override
+    public void setStatus(int status) {
+        super.setStatus(status);
+        this.status = 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) {
+        // SLING-726 No handling required since this seems to be correct
+        this.registerHeader(HEADER_CONTENT_TYPE, type, false);
+        super.setContentType(type);
+    }
+
+    @Override
+    public void setCharacterEncoding(String charset) {
+        // SLING-726 Ignore call if getWriter() has been called
+        if (writer == null) {
+            super.setCharacterEncoding(charset);
+        }
+    }
+
+    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 long 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 ---------------------------------------------
+
+    /**
+     * 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.
+     */
+    @SuppressWarnings("unchecked")
+    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: sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/log/RequestLoggerService.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/log/RequestLoggerService.java?rev=1239517&r1=1239516&r2=1239517&view=diff
==============================================================================
--- sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/log/RequestLoggerService.java (original)
+++ sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/log/RequestLoggerService.java Thu Feb  2 10:28:49 2012
@@ -19,19 +19,18 @@
 package org.apache.sling.engine.impl.log;
 
 import java.io.IOException;
-import java.util.Dictionary;
+import java.util.Map;
 
+import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.ConfigurationPolicy;
+import org.apache.felix.scr.annotations.Deactivate;
 import org.apache.felix.scr.annotations.Properties;
 import org.apache.felix.scr.annotations.Property;
 import org.apache.felix.scr.annotations.PropertyOption;
 import org.apache.felix.scr.annotations.Service;
-import org.apache.sling.api.SlingHttpServletRequest;
 import org.apache.sling.engine.RequestLog;
-import org.apache.sling.engine.impl.SlingHttpServletResponseImpl;
 import org.osgi.framework.BundleContext;
-import org.osgi.service.component.ComponentContext;
 
 /**
  * The <code>RequestLoggerService</code> is a factory component which gets
@@ -83,11 +82,12 @@ public class RequestLoggerService {
     public RequestLoggerService() {
     }
 
-    RequestLoggerService(BundleContext bundleContext, Dictionary<String, Object> configuration) {
+    RequestLoggerService(BundleContext bundleContext, Map<String, Object> configuration) {
         this.setup(bundleContext, configuration);
     }
 
-    void setup(BundleContext bundleContext, Dictionary<String, Object> configuration) {
+    @Activate
+    void setup(BundleContext bundleContext, Map<String, Object> configuration) {
         // whether to log on request entry or request exit
         Object onEntryObject = configuration.get(PARAM_ON_ENTRY);
         this.onEntry = (onEntryObject instanceof Boolean)
@@ -111,6 +111,7 @@ public class RequestLoggerService {
         }
     }
 
+    @Deactivate
     void shutdown() {
         if (this.log != null) {
             this.log.close();
@@ -120,7 +121,7 @@ public class RequestLoggerService {
         this.logFormat = null;
     }
 
-    void log(SlingHttpServletRequest request, SlingHttpServletResponseImpl response) {
+    void log(RequestLoggerRequest request, RequestLoggerResponse response) {
         if (this.log != null && this.logFormat != null) {
             this.log.write(this.logFormat.format(request, response));
         }
@@ -130,17 +131,6 @@ public class RequestLoggerService {
         return this.onEntry;
     }
 
-    // ---------- SCR integration ----------------------------------------------
-
-    @SuppressWarnings("unchecked")
-    protected void activate(ComponentContext context) {
-        this.setup(context.getBundleContext(), context.getProperties());
-    }
-
-    protected void deactivate(ComponentContext context) {
-        this.shutdown();
-    }
-
     private RequestLog getLog(BundleContext bundleContext, String output,
             int outputType) {
         switch (outputType) {

Modified: sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/request/RequestData.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/request/RequestData.java?rev=1239517&r1=1239516&r2=1239517&view=diff
==============================================================================
--- sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/request/RequestData.java (original)
+++ sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/request/RequestData.java Thu Feb  2 10:28:49 2012
@@ -83,6 +83,12 @@ public class RequestData {
     public static final int DEFAULT_MAX_CALL_COUNTER = 1000;
 
     /**
+     * The name of the request attribute providing the resource addressed by the
+     * request URL.
+     */
+    public static final String REQUEST_RESOURCE_PATH_ATTR = "$$sling.request.resource$$";
+
+    /**
      * The maximum inclusion depth (default
      * {@link #DEFAULT_MAX_INCLUSION_COUNTER}). This value is compared to the
      * number of entries in the {@link #contentDataStack} when the
@@ -192,6 +198,9 @@ public class RequestData {
         requestProgressTracker.startTimer("ResourceResolution");
         final SlingHttpServletRequest request = getSlingRequest();
         Resource resource = resourceResolver.resolve(request, request.getPathInfo());
+        if (request.getAttribute(REQUEST_RESOURCE_PATH_ATTR) == null) {
+            request.setAttribute(REQUEST_RESOURCE_PATH_ATTR, resource.getPath());
+        }
         requestProgressTracker.logTimer("ResourceResolution",
             "URI={0} resolves to Resource={1}",
             getServletRequest().getRequestURI(), resource);



Mime
View raw message