Author: markt Date: Fri Jan 7 18:26:09 2011 New Revision: 1056442 URL: http://svn.apache.org/viewvc?rev=1056442&view=rev Log: Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=50201 Handle ROOT webapp redeployment, host start/stop etc for default access log
Modified: tomcat/tc6.0.x/trunk/STATUS.txt tomcat/tc6.0.x/trunk/java/org/apache/catalina/core/StandardEngine.java tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml Modified: tomcat/tc6.0.x/trunk/STATUS.txt URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/STATUS.txt?rev=1056442&r1=1056441&r2=1056442&view=diff ============================================================================== --- tomcat/tc6.0.x/trunk/STATUS.txt (original) +++ tomcat/tc6.0.x/trunk/STATUS.txt Fri Jan 7 18:26:09 2011 @@ -127,12 +127,6 @@ PATCHES PROPOSED TO BACKPORT: -0: markt - Patch doesn't apply cleanly to tc6.0.x/trunk -1: -* Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=50201 - Handle ROOT webapp redeployment, host start/stop etc for default access log - http://people.apache.org/~kkolinko/patches/2010-12-07_tc6_bug50201.patch - +1: kkolinko, markt, fhanik - -1: - * Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=48973 Avoid creating file SESSIONS.ser if there's no session. The patch provided by Marc Guillemot works for tc 6 & 7 Modified: tomcat/tc6.0.x/trunk/java/org/apache/catalina/core/StandardEngine.java URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/catalina/core/StandardEngine.java?rev=1056442&r1=1056441&r2=1056442&view=diff ============================================================================== --- tomcat/tc6.0.x/trunk/java/org/apache/catalina/core/StandardEngine.java (original) +++ tomcat/tc6.0.x/trunk/java/org/apache/catalina/core/StandardEngine.java Fri Jan 7 18:26:09 2011 @@ -19,8 +19,11 @@ package org.apache.catalina.core; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import java.io.File; import java.util.List; +import java.util.concurrent.atomic.AtomicReference; import javax.management.MBeanServer; import javax.management.MalformedObjectNameException; @@ -28,10 +31,15 @@ import javax.management.ObjectName; import org.apache.catalina.AccessLog; import org.apache.catalina.Container; +import org.apache.catalina.ContainerEvent; +import org.apache.catalina.ContainerListener; import org.apache.catalina.Context; import org.apache.catalina.Engine; import org.apache.catalina.Host; +import org.apache.catalina.Lifecycle; +import org.apache.catalina.LifecycleEvent; import org.apache.catalina.LifecycleException; +import org.apache.catalina.LifecycleListener; import org.apache.catalina.Realm; import org.apache.catalina.Service; import org.apache.catalina.connector.Request; @@ -132,7 +140,8 @@ public class StandardEngine * Default access log to use for request/response pairs where we can't ID * the intended host and context. */ - private volatile AccessLog defaultAccessLog; + private final AtomicReference<AccessLog> defaultAccessLog = + new AtomicReference<AccessLog>(); // ------------------------------------------------------------- Properties @@ -496,28 +505,59 @@ public class StandardEngine } if (!logged && useDefault) { - if (defaultAccessLog == null) { + AccessLog newDefaultAccessLog = defaultAccessLog.get(); + if (newDefaultAccessLog == null) { // If we reached this point, this Engine can't have an AccessLog // Look in the defaultHost Host host = (Host) findChild(getDefaultHost()); - if (host != null) { - defaultAccessLog = host.getAccessLog(); + Context context = null; + boolean checkHost = (host != null); + if (checkHost && host instanceof ContainerBase) { + checkHost = ((ContainerBase) host).started; + } + if (checkHost) { + newDefaultAccessLog = host.getAccessLog(); - if (defaultAccessLog == null) { + if (newDefaultAccessLog != null) { + if (defaultAccessLog.compareAndSet(null, + newDefaultAccessLog)) { + AccessLogListener l = new AccessLogListener(this, + host, null); + l.install(); + } + } else { // Try the ROOT context of default host - Context context = (Context) host.findChild(""); - if (context != null) { - defaultAccessLog = context.getAccessLog(); + context = (Context) host.findChild(""); + boolean checkContext = (context != null); + if (checkContext && context instanceof ContainerBase) { + checkContext = ((ContainerBase) context).started; + } + if (checkContext) { + newDefaultAccessLog = context.getAccessLog(); + if (newDefaultAccessLog != null) { + if (defaultAccessLog.compareAndSet(null, + newDefaultAccessLog)) { + AccessLogListener l = new AccessLogListener( + this, null, context); + l.install(); + } + } } } } - if (defaultAccessLog == null) { - defaultAccessLog = new NoopAccessLog(); + if (newDefaultAccessLog == null) { + newDefaultAccessLog = new NoopAccessLog(); + if (defaultAccessLog.compareAndSet(null, + newDefaultAccessLog)) { + AccessLogListener l = new AccessLogListener(this, host, + context); + l.install(); + } } } - defaultAccessLog.log(request, response, time); + newDefaultAccessLog.log(request, response, time); } } @@ -584,5 +624,88 @@ public class StandardEngine public void setDomain(String domain) { this.domain = domain; } - + + protected static final class AccessLogListener + implements PropertyChangeListener, LifecycleListener, + ContainerListener { + + private StandardEngine engine; + private Host host; + private Context context; + private volatile boolean disabled = false; + + public AccessLogListener(StandardEngine engine, Host host, + Context context) { + this.engine = engine; + this.host = host; + this.context = context; + } + + public void install() { + engine.addPropertyChangeListener(this); + if (host != null) { + host.addContainerListener(this); + if (host instanceof Lifecycle) { + ((Lifecycle) host).addLifecycleListener(this); + } + } + if (context instanceof Lifecycle) { + ((Lifecycle) context).addLifecycleListener(this); + } + } + + private void uninstall() { + disabled = true; + if (context instanceof Lifecycle) { + ((Lifecycle) context).removeLifecycleListener(this); + } + if (host != null) { + if (host instanceof Lifecycle) { + ((Lifecycle) host).removeLifecycleListener(this); + } + host.removeContainerListener(this); + } + engine.removePropertyChangeListener(this); + } + + public void lifecycleEvent(LifecycleEvent event) { + if (disabled) return; + + String type = event.getType(); + if (Lifecycle.AFTER_START_EVENT.equals(type) || + Lifecycle.BEFORE_STOP_EVENT.equals(type) || + Lifecycle.DESTROY_EVENT.equals(type)) { + // Container is being started/stopped/removed + // Force re-calculation and disable listener since it won't + // be re-used + engine.defaultAccessLog.set(null); + uninstall(); + } + } + + public void propertyChange(PropertyChangeEvent evt) { + if (disabled) return; + if ("defaultHost".equals(evt.getPropertyName())) { + // Force re-calculation and disable listener since it won't + // be re-used + engine.defaultAccessLog.set(null); + uninstall(); + } + } + + public void containerEvent(ContainerEvent event) { + // Only useful for hosts + if (disabled) return; + if (Container.ADD_CHILD_EVENT.equals(event.getType())) { + Context context = (Context) event.getData(); + if ("".equals(context.getPath())) { + // New ROOT context in default host + // Force re-calculation and disable listener since it won't + // be re-used + engine.defaultAccessLog.set(null); + uninstall(); + } + } + } + } } Modified: tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml?rev=1056442&r1=1056441&r2=1056442&view=diff ============================================================================== --- tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml (original) +++ tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml Fri Jan 7 18:26:09 2011 @@ -67,8 +67,9 @@ access. (markt) </fix> <fix> - <bug>49909</bug>: Provide a mechanism to log requests rejected before - they reach the AccessLogValve to appear in the access log. (markt) + <bug>49909</bug>, <bug>50201</bug>: Provide a mechanism to log requests + rejected before they reach the AccessLogValve to appear in the access + log. (markt/kkolinko) </fix> </changelog> </subsection> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org