You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2010/06/03 17:00:11 UTC
svn commit: r951018 - in /tomcat/trunk: java/org/apache/catalina/
java/org/apache/catalina/connector/ java/org/apache/catalina/core/
webapps/docs/config/
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-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org