Author: markt Date: Thu Jun 3 15:00:11 2010 New Revision: 951018 URL: http://svn.apache.org/viewvc?rev=951018&view=rev Log: Refactor the hooks from the CoyoteAdapter to the access logs - cleaner interface - handles AccessLogs at multiple levels (but not multiple AccessLogs per container)
Modified: tomcat/trunk/java/org/apache/catalina/AccessLog.java tomcat/trunk/java/org/apache/catalina/Container.java tomcat/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java tomcat/trunk/java/org/apache/catalina/core/ContainerBase.java tomcat/trunk/java/org/apache/catalina/core/StandardEngine.java tomcat/trunk/webapps/docs/config/valve.xml Modified: tomcat/trunk/java/org/apache/catalina/AccessLog.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/AccessLog.java?rev=951018&r1=951017&r2=951018&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/AccessLog.java (original) +++ tomcat/trunk/java/org/apache/catalina/AccessLog.java Thu Jun 3 15:00:11 2010 @@ -23,9 +23,8 @@ import org.apache.catalina.connector.Res /** * 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 + * provides access logging. It is used by the Tomcat internals 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 Modified: tomcat/trunk/java/org/apache/catalina/Container.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/Container.java?rev=951018&r1=951017&r2=951018&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/Container.java (original) +++ tomcat/trunk/java/org/apache/catalina/Container.java Thu Jun 3 15:00:11 2010 @@ -450,4 +450,27 @@ public interface Container extends Lifec * @param data Event data */ public void fireContainerEvent(String type, Object data); + + + /** + * Log a request/response that was destined for this container but has been + * handled earlier in the processing chain so that the request/response + * still appears in the correct access logs. + * @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) + * @param useDefault Flag that indicates that the request/response should + * be logged in the engine's default access log + */ + public void logAccess(Request request, Response response, long time, + boolean useDefault); + + + /** + * Identify the AccessLog to use to log a request/response that was destined + * for this container but was handled earlier in the processing chain so + * that the request/response still appears in the correct access logs. + */ + public AccessLog getAccessLog(); } 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=951018&r1=951017&r2=951018&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java (original) +++ tomcat/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java Thu Jun 3 15:00:11 2010 @@ -24,13 +24,8 @@ 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; @@ -120,11 +115,6 @@ public class CoyoteAdapter implements Ad protected static URLEncoder urlEncoder; - /** - * Access log to use for rejected requests - */ - private volatile AccessLog accessLog = null; - // ----------------------------------------------------- Static Initializer @@ -522,14 +512,16 @@ public class CoyoteAdapter implements Ad } catch (IOException ioe) { res.setStatus(400); res.setMessage("Invalid URI: " + ioe.getMessage()); - getAccessLog().log(request, response, 0); + connector.getService().getContainer().logAccess( + request, response, 0, true); return false; } // Normalization if (!normalize(req.decodedURI())) { res.setStatus(400); res.setMessage("Invalid URI"); - getAccessLog().log(request, response, 0); + connector.getService().getContainer().logAccess( + request, response, 0, true); return false; } // Character decoding @@ -538,7 +530,8 @@ public class CoyoteAdapter implements Ad if (!checkNormalize(req.decodedURI())) { res.setStatus(400); res.setMessage("Invalid URI character encoding"); - getAccessLog().log(request, response, 0); + connector.getService().getContainer().logAccess( + request, response, 0, true); return false; } @@ -598,7 +591,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); + request.getContext().logAccess(request, response, 0, true); return false; } @@ -637,7 +630,7 @@ public class CoyoteAdapter implements Ad redirectPath = redirectPath + "?" + query; } response.sendRedirect(redirectPath); - getAccessLog().log(request, response, 0); + request.getContext().logAccess(request, response, 0, true); return false; } @@ -1088,63 +1081,4 @@ public class CoyoteAdapter implements Ad b[pos + dest] = b[pos + src]; } } - - - /** - * 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/core/ContainerBase.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/ContainerBase.java?rev=951018&r1=951017&r2=951018&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/core/ContainerBase.java (original) +++ tomcat/trunk/java/org/apache/catalina/core/ContainerBase.java Thu Jun 3 15:00:11 2010 @@ -31,6 +31,7 @@ import javax.management.ObjectName; import javax.naming.directory.DirContext; import javax.servlet.ServletException; +import org.apache.catalina.AccessLog; import org.apache.catalina.CatalinaFactory; import org.apache.catalina.Cluster; import org.apache.catalina.Container; @@ -265,6 +266,13 @@ public abstract class ContainerBase exte private volatile boolean threadDone = false; + /** + * The access log to use for requests normally handled by this container + * that have been handled earlier in the processing chain. + */ + protected volatile AccessLog accessLog = null; + private volatile boolean accessLogScanComplete = false; + // ------------------------------------------------------------- Properties @@ -1062,6 +1070,46 @@ public abstract class ContainerBase exte super.destroyInternal(); } + + /** + * Check this container for an access log and if none is found, look to the + * parent. If there is no parent and still none is found, use the NoOp + * access log. + */ + public void logAccess(Request request, Response response, long time, + boolean useDefault) { + + boolean logged = false; + + if (getAccessLog() != null) { + getAccessLog().log(request, response, time); + logged = true; + } + + if (getParent() != null) { + // No need to use default logger once request/response has been logged + // once + getParent().logAccess(request, response, time, (useDefault && !logged)); + } + } + + public AccessLog getAccessLog() { + + if (accessLogScanComplete) { + return accessLog; + } + + Valve valves[] = getPipeline().getValves(); + for (Valve valve : valves) { + if (valve instanceof AccessLog) { + accessLog = (AccessLog) valve; + break; + } + } + accessLogScanComplete = true; + return accessLog; + } + // ------------------------------------------------------- Pipeline Methods @@ -1305,4 +1353,11 @@ public abstract class ContainerBase exte } + protected static final class NoopAccessLog implements AccessLog { + + @Override + public void log(Request request, Response response, long time) { + // NOOP + } + } } Modified: tomcat/trunk/java/org/apache/catalina/core/StandardEngine.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/StandardEngine.java?rev=951018&r1=951017&r2=951018&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/core/StandardEngine.java (original) +++ tomcat/trunk/java/org/apache/catalina/core/StandardEngine.java Thu Jun 3 15:00:11 2010 @@ -18,12 +18,16 @@ package org.apache.catalina.core; import java.util.Locale; +import org.apache.catalina.AccessLog; import org.apache.catalina.Container; +import org.apache.catalina.Context; import org.apache.catalina.Engine; import org.apache.catalina.Host; import org.apache.catalina.LifecycleException; import org.apache.catalina.Realm; import org.apache.catalina.Service; +import org.apache.catalina.connector.Request; +import org.apache.catalina.connector.Response; import org.apache.catalina.realm.JAASRealm; import org.apache.catalina.util.LifecycleBase; import org.apache.catalina.util.ServerInfo; @@ -99,6 +103,11 @@ public class StandardEngine extends Cont */ private String jvmRouteId; + /** + * Default access log to use for request/response pairs where we can't ID + * the intended host and context. + */ + private volatile AccessLog defaultAccessLog; // ------------------------------------------------------------- Properties @@ -280,6 +289,51 @@ public class StandardEngine extends Cont } + /** + * Override the default implementation. If no access log is defined for the + * Engine, look for one in the Engine's default host and then the default + * host's ROOT context. If still none is found, return the default NoOp + * access log. + */ + @Override + /** + * Check this container for an access log and if none is found, look to the + * parent. If there is no parent and still none is found, use the NoOp + * access log. + */ + public void logAccess(Request request, Response response, long time, + boolean useDefault) { + + boolean logged = false; + + if (accessLog != null) { + accessLog.log(request, response, time); + logged = true; + } + + if (!logged && useDefault) { + Host host = null; + if (defaultAccessLog == null) { + // If we reached this point, this Engine can't have an AccessLog + // Look in the defaultHost + host = (Host) findChild(getDefaultHost()); + defaultAccessLog = host.getAccessLog(); + + if (defaultAccessLog == null) { + // Try the ROOT context of default host + Context context = (Context) host.findChild(""); + defaultAccessLog = context.getAccessLog(); + + if (defaultAccessLog == null) { + defaultAccessLog = new NoopAccessLog(); + } + } + } + + defaultAccessLog.log(request, response, time); + } + } + // -------------------- JMX registration -------------------- Modified: tomcat/trunk/webapps/docs/config/valve.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/config/valve.xml?rev=951018&r1=951017&r2=951018&view=diff ============================================================================== --- tomcat/trunk/webapps/docs/config/valve.xml (original) +++ tomcat/trunk/webapps/docs/config/valve.xml Thu Jun 3 15:00:11 2010 @@ -66,12 +66,17 @@ <code>Host</code>, or <code>Engine</code>), and will record ALL requests processed by that container.</p> - <p>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 <code>Engine</code>, then the default <code>Host</code> for the - <code>Engine</code> and finally the ROOT (or default) <code>Context</code> - for the default <code>Host</code> for an <code>AccessLogValve</code> or - other <code>AccessLog</code> implementation. Tomcat will use the first + <p>Some requests may be handled by Tomcat before they are passed to a + container. These include redirects from /foo to /foo/ and the rejection of + invalid requests. Where Tomcat can identify the <code>Context</code> that + would have handled the request, the request/response will be logged in the + <code>AccessLog</code>(s) associated <code>Context</code>, <code>Host</code> + and <code>Engine</code>. Where Tomcat cannot identify the + <code>Context</code> that would have handled the request, e.g. in cases + where the URL is invalid, Tomcat will look first in the <code>Engine</code>, + then the default <code>Host</code> for the <code>Engine</code> and finally + the ROOT (or default) <code>Context</code> for the default <code>Host</code> + for an <code>AccessLog</code> implementation. Tomcat will use the first <code>AccessLog</code> implementation found to log those requests that are rejected before they are passed to a container.</p> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org