Return-Path: Delivered-To: apmail-tomcat-dev-archive@www.apache.org Received: (qmail 91260 invoked from network); 2 Jun 2010 15:13:10 -0000 Received: from unknown (HELO mail.apache.org) (140.211.11.3) by 140.211.11.9 with SMTP; 2 Jun 2010 15:13:10 -0000 Received: (qmail 82993 invoked by uid 500); 2 Jun 2010 15:13:09 -0000 Delivered-To: apmail-tomcat-dev-archive@tomcat.apache.org Received: (qmail 82935 invoked by uid 500); 2 Jun 2010 15:13:09 -0000 Mailing-List: contact dev-help@tomcat.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: "Tomcat Developers List" Delivered-To: mailing list dev@tomcat.apache.org Received: (qmail 82924 invoked by uid 99); 2 Jun 2010 15:13:09 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 02 Jun 2010 15:13:09 +0000 X-ASF-Spam-Status: No, hits=-1454.4 required=10.0 tests=ALL_TRUSTED,AWL X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 02 Jun 2010 15:13:08 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 6EEAE238890A; Wed, 2 Jun 2010 15:12:47 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r950587 - in /tomcat/trunk: java/org/apache/catalina/AccessLog.java java/org/apache/catalina/connector/CoyoteAdapter.java java/org/apache/catalina/valves/AccessLogValve.java webapps/docs/config/valve.xml Date: Wed, 02 Jun 2010 15:12:47 -0000 To: dev@tomcat.apache.org From: markt@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20100602151247.6EEAE238890A@eris.apache.org> Author: markt Date: Wed Jun 2 15:12:36 2010 New Revision: 950587 URL: http://svn.apache.org/viewvc?rev=950587&view=rev Log: Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=49099 Hooking the CoyoteAdaptor into the existing AccessLog wasn't as invasive as I feared so go that route to log requests rejected by the Adaptor before the request/response reaches the AcessLogValve Added: tomcat/trunk/java/org/apache/catalina/AccessLog.java (with props) Modified: tomcat/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java tomcat/trunk/java/org/apache/catalina/valves/AccessLogValve.java tomcat/trunk/webapps/docs/config/valve.xml Added: tomcat/trunk/java/org/apache/catalina/AccessLog.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/AccessLog.java?rev=950587&view=auto ============================================================================== --- tomcat/trunk/java/org/apache/catalina/AccessLog.java (added) +++ tomcat/trunk/java/org/apache/catalina/AccessLog.java Wed Jun 2 15:12:36 2010 @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.catalina; + +import org.apache.catalina.connector.Request; +import org.apache.catalina.connector.Response; + + +/** + * Intended for use by a {@link Valve} to indicate that the {@link Valve} + * provides access logging. It is used by the Tomcat internals (the + * {@link org.apache.catalina.connector.CoyoteAdapter} at the time of writing) + * to identify a Valve that logs access requests so requests that are rejected + * earlier in the processing chain can still be added to the access log. + * Implementations of this interface should be robust against the provided + * {@link Request} and {@link Response} objects being null, having null + * attributes or any other 'oddness' that may result from attempting to log + * a request that was almost certainly rejected because it was mal-formed. + */ +public interface AccessLog { + + /** + * Add the request/response to the access log using the specified processing + * time. + * + * @param request Request (associated with the response) to log + * @param response Response (associated with the request) to log + * @param time Time taken to process the request/response in + * milliseconds (use 0 if not known) + */ + public void log(Request request, Response response, long time); +} Propchange: tomcat/trunk/java/org/apache/catalina/AccessLog.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: tomcat/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java?rev=950587&r1=950586&r2=950587&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java (original) +++ tomcat/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java Wed Jun 2 15:12:36 2010 @@ -24,8 +24,13 @@ import java.util.EnumSet; import javax.servlet.SessionTrackingMode; +import org.apache.catalina.AccessLog; +import org.apache.catalina.Container; import org.apache.catalina.Context; +import org.apache.catalina.Engine; import org.apache.catalina.Globals; +import org.apache.catalina.Host; +import org.apache.catalina.Valve; import org.apache.catalina.Wrapper; import org.apache.tomcat.util.res.StringManager; import org.apache.catalina.comet.CometEvent; @@ -115,6 +120,11 @@ public class CoyoteAdapter implements Ad protected static URLEncoder urlEncoder; + /** + * Access log to use for rejected requests + */ + private volatile AccessLog accessLog = null; + // ----------------------------------------------------- Static Initializer @@ -512,12 +522,14 @@ public class CoyoteAdapter implements Ad } catch (IOException ioe) { res.setStatus(400); res.setMessage("Invalid URI: " + ioe.getMessage()); + getAccessLog().log(request, response, 0); return false; } // Normalization if (!normalize(req.decodedURI())) { res.setStatus(400); res.setMessage("Invalid URI"); + getAccessLog().log(request, response, 0); return false; } // Character decoding @@ -526,6 +538,7 @@ public class CoyoteAdapter implements Ad if (!checkNormalize(req.decodedURI())) { res.setStatus(400); res.setMessage("Invalid URI character encoding"); + getAccessLog().log(request, response, 0); return false; } @@ -585,6 +598,7 @@ public class CoyoteAdapter implements Ad res.setStatus(405); res.addHeader("Allow", header); res.setMessage("TRACE method is not allowed"); + getAccessLog().log(request, response, 0); return false; } @@ -623,6 +637,7 @@ public class CoyoteAdapter implements Ad redirectPath = redirectPath + "?" + query; } response.sendRedirect(redirectPath); + getAccessLog().log(request, response, 0); return false; } @@ -1075,4 +1090,61 @@ public class CoyoteAdapter implements Ad } + /** + * Obtain a reference to the access log to use to log rejected requests. + * + * @return + */ + protected AccessLog getAccessLog() { + if (accessLog != null) { + return accessLog; + } + + // First look in Engine for associated service + Engine engine = (Engine) connector.getService().getContainer(); + accessLog = findAccessLog(engine); + if (accessLog != null) { + return accessLog; + } + + // Then look in default host + Host defaultHost = (Host) engine.findChild(engine.getDefaultHost()); + accessLog = findAccessLog(defaultHost); + if (accessLog != null) { + return accessLog; + } + + // Then look in ROOT context of default host + Context defaultContext = (Context) defaultHost.findChild("/"); + accessLog = findAccessLog(defaultContext); + if (accessLog != null) { + return accessLog; + } + + accessLog = new NoopAccessLog(); + return accessLog; + } + + private AccessLog findAccessLog(Container container) { + if (container == null) { + return new NoopAccessLog(); + } + + Valve valves[] = container.getPipeline().getValves(); + for (Valve valve : valves) { + if (valve instanceof AccessLog) { + return (AccessLog) valve; + } + } + return null; + } + + private static final class NoopAccessLog implements AccessLog { + + @Override + public void log(Request request, Response response, long time) { + // NOOP + } + + } } Modified: tomcat/trunk/java/org/apache/catalina/valves/AccessLogValve.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/valves/AccessLogValve.java?rev=950587&r1=950586&r2=950587&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/valves/AccessLogValve.java (original) +++ tomcat/trunk/java/org/apache/catalina/valves/AccessLogValve.java Wed Jun 2 15:12:36 2010 @@ -36,6 +36,7 @@ import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpSession; +import org.apache.catalina.AccessLog; import org.apache.catalina.LifecycleException; import org.apache.catalina.LifecycleState; import org.apache.catalina.connector.Request; @@ -118,7 +119,7 @@ import org.apache.juli.logging.LogFactor * @version $Id$ */ -public class AccessLogValve extends ValveBase { +public class AccessLogValve extends ValveBase implements AccessLog { private static final Log log = LogFactory.getLog(AccessLogValve.class); @@ -563,25 +564,30 @@ public class AccessLogValve extends Valv long t2 = System.currentTimeMillis(); long time = t2 - t1; - - if (logElements == null || condition != null - && null != request.getRequest().getAttribute(condition)) { - return; - } - - Date date = getDate(); - StringBuilder result = new StringBuilder(128); - - for (int i = 0; i < logElements.length; i++) { - logElements[i].addElement(result, date, request, response, time); - } - - log(result.toString()); + + log(request,response, time); } else getNext().invoke(request, response); } + public void log(Request request, Response response, long time) { + if (logElements == null || condition != null + && null != request.getRequest().getAttribute(condition)) { + return; + } + + Date date = getDate(); + StringBuilder result = new StringBuilder(128); + + for (int i = 0; i < logElements.length; i++) { + logElements[i].addElement(result, date, request, response, time); + } + + log(result.toString()); + } + + /** * Rename the existing log file to something else. Then open the * old log file name up once again. Intended to be called by a JMX Modified: tomcat/trunk/webapps/docs/config/valve.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/config/valve.xml?rev=950587&r1=950586&r2=950587&view=diff ============================================================================== --- tomcat/trunk/webapps/docs/config/valve.xml (original) +++ tomcat/trunk/webapps/docs/config/valve.xml Wed Jun 2 15:12:36 2010 @@ -66,6 +66,15 @@ Host, or Engine), and will record ALL requests processed by that container.

+

Some requests (e.g. those with mal-formed URLs) may be rejected by Tomcat + before they are passed to a container. In these cases Tomcat will look in + the Engine, then the default Host for the + Engine and finally the ROOT (or default) Context + for the default Host for an AccessLogValve or + other AccessLog implementation. Tomcat will use the first + AccessLog implementation found to log those requests that are + rejected before they are passed to a container.

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