This is an automated email from the ASF dual-hosted git repository. rmaucher pushed a commit to branch 9.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 96653cd8829a58a66674bb28fedac87312ba25c9 Author: opencode <[email protected]> AuthorDate: Wed Sep 30 22:51:14 2026 +0200 Fire ServletContextAttributeListener events for attributes stored in the local map of a ReplicatedContext by extracting the event firing logic of ApplicationContext into overridable hooks --- .../apache/catalina/core/ApplicationContext.java | 31 +++++++++++++++++----- .../catalina/ha/context/ReplicatedContext.java | 13 +++++++-- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/java/org/apache/catalina/core/ApplicationContext.java b/java/org/apache/catalina/core/ApplicationContext.java index 0dc4abb49f..368aeaee1e 100644 --- a/java/org/apache/catalina/core/ApplicationContext.java +++ b/java/org/apache/catalina/core/ApplicationContext.java @@ -617,6 +617,17 @@ public class ApplicationContext implements ServletContext { return; } + fireContextAttributeRemoved(name, value); + } + + + /** + * Notify the application's <code>ServletContextAttributeListener</code>s of an attribute removal. + * + * @param name The name of the attribute + * @param value The value the attribute had before it was removed + */ + protected void fireContextAttributeRemoved(String name, Object value) { // Notify interested application event listeners Object[] listeners = context.getApplicationEventListeners(); if (listeners == null || listeners.length == 0) { @@ -663,17 +674,25 @@ public class ApplicationContext implements ServletContext { Object oldValue = attributes.put(name, value); boolean replaced = oldValue != null; + fireContextAttributeAddedOrReplaced(replaced, name, replaced ? oldValue : value); + } + + + /** + * Notify the application's <code>ServletContextAttributeListener</code>s of an attribute addition or replacement. + * + * @param replaced Whether the attribute was replaced rather than added + * @param name The name of the attribute + * @param value The value for the event: the previous value when the attribute was replaced, otherwise the new + * value + */ + protected void fireContextAttributeAddedOrReplaced(boolean replaced, String name, Object value) { // Notify interested application event listeners Object[] listeners = context.getApplicationEventListeners(); if (listeners == null || listeners.length == 0) { return; } - ServletContextAttributeEvent event; - if (replaced) { - event = new ServletContextAttributeEvent(context.getServletContext(), name, oldValue); - } else { - event = new ServletContextAttributeEvent(context.getServletContext(), name, value); - } + ServletContextAttributeEvent event = new ServletContextAttributeEvent(context.getServletContext(), name, value); for (Object obj : listeners) { if (!(obj instanceof ServletContextAttributeListener)) { diff --git a/java/org/apache/catalina/ha/context/ReplicatedContext.java b/java/org/apache/catalina/ha/context/ReplicatedContext.java index 2dd2e06bc0..15e9caf5f8 100644 --- a/java/org/apache/catalina/ha/context/ReplicatedContext.java +++ b/java/org/apache/catalina/ha/context/ReplicatedContext.java @@ -235,8 +235,14 @@ public class ReplicatedContext extends StandardContext implements MapOwner { @Override public void removeAttribute(String name) { - tomcatAttributes.remove(name); + Object localValue = tomcatAttributes.remove(name); + boolean inAttributeMap = attributes.containsKey(name); super.removeAttribute(name); + if (localValue != null && !inAttributeMap) { + // The attribute was only stored locally, so the removal event + // was not fired by the attribute map + fireContextAttributeRemoved(name, localValue); + } } @Override @@ -249,7 +255,10 @@ public class ReplicatedContext extends StandardContext implements MapOwner { return; } if ((!getParent().getState().isAvailable()) || JSP_APP_CONTEXT_NAME.equals(name)) { - tomcatAttributes.put(name, value); + Object oldValue = tomcatAttributes.put(name, value); + // The attribute is stored locally, so the event has to be fired + // here rather than by the attribute map + fireContextAttributeAddedOrReplaced(oldValue != null, name, oldValue != null ? oldValue : value); } else { super.setAttribute(name, value); } --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
