This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git


The following commit(s) were added to refs/heads/9.0.x by this push:
     new 030e748852 Refactor to use CopyOnWriteArrayList rather than 
hand-crafted equivalent
030e748852 is described below

commit 030e748852cd7018929cf87cbe1021f97ff0abed
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Thu Aug 10 15:25:47 2023 +0100

    Refactor to use CopyOnWriteArrayList rather than hand-crafted equivalent
    
    In response to a concurrency issue raised by Coverity
---
 java/org/apache/catalina/core/StandardContext.java | 62 +++++-----------------
 1 file changed, 12 insertions(+), 50 deletions(-)

diff --git a/java/org/apache/catalina/core/StandardContext.java 
b/java/org/apache/catalina/core/StandardContext.java
index d038e18460..d621fe7d45 100644
--- a/java/org/apache/catalina/core/StandardContext.java
+++ b/java/org/apache/catalina/core/StandardContext.java
@@ -202,12 +202,10 @@ public class StandardContext extends ContainerBase 
implements Context, Notificat
 
 
     /**
-     * The set of application listener class names configured for this 
application, in the order they were encountered
-     * in the resulting merged web.xml file.
+     * The list of unique application listener class names configured for this 
application, in the order they were
+     * encountered in the resulting merged web.xml file.
      */
-    private String applicationListeners[] = new String[0];
-
-    private final Object applicationListenersLock = new Object();
+    private CopyOnWriteArrayList<String> applicationListeners = new 
CopyOnWriteArrayList<>();
 
     /**
      * The set of application listeners that are required to have limited 
access to ServletContext methods. See Servlet
@@ -2682,21 +2680,11 @@ public class StandardContext extends ContainerBase 
implements Context, Notificat
      */
     @Override
     public void addApplicationListener(String listener) {
-
-        synchronized (applicationListenersLock) {
-            String results[] = new String[applicationListeners.length + 1];
-            for (int i = 0; i < applicationListeners.length; i++) {
-                if (listener.equals(applicationListeners[i])) {
-                    log.info(sm.getString("standardContext.duplicateListener", 
listener));
-                    return;
-                }
-                results[i] = applicationListeners[i];
-            }
-            results[applicationListeners.length] = listener;
-            applicationListeners = results;
+        if (applicationListeners.addIfAbsent(listener)) {
+            fireContainerEvent("addApplicationListener", listener);
+        } else {
+            log.info(sm.getString("standardContext.duplicateListener", 
listener));
         }
-        fireContainerEvent("addApplicationListener", listener);
-
     }
 
 
@@ -3198,7 +3186,7 @@ public class StandardContext extends ContainerBase 
implements Context, Notificat
      */
     @Override
     public String[] findApplicationListeners() {
-        return applicationListeners;
+        return applicationListeners.toArray(new String[0]);
     }
 
 
@@ -3611,36 +3599,10 @@ public class StandardContext extends ContainerBase 
implements Context, Notificat
      */
     @Override
     public void removeApplicationListener(String listener) {
-
-        synchronized (applicationListenersLock) {
-
-            // Make sure this listener is currently present
-            int n = -1;
-            for (int i = 0; i < applicationListeners.length; i++) {
-                if (applicationListeners[i].equals(listener)) {
-                    n = i;
-                    break;
-                }
-            }
-            if (n < 0) {
-                return;
-            }
-
-            // Remove the specified listener
-            int j = 0;
-            String results[] = new String[applicationListeners.length - 1];
-            for (int i = 0; i < applicationListeners.length; i++) {
-                if (i != n) {
-                    results[j++] = applicationListeners[i];
-                }
-            }
-            applicationListeners = results;
-
+        if (applicationListeners.remove(listener)) {
+            // Inform interested listeners if the specified listener was 
present and has been removed
+            fireContainerEvent("removeApplicationListener", listener);
         }
-
-        // Inform interested listeners
-        fireContainerEvent("removeApplicationListener", listener);
-
     }
 
 
@@ -5359,7 +5321,7 @@ public class StandardContext extends ContainerBase 
implements Context, Notificat
         // Bugzilla 32867
         distributable = false;
 
-        applicationListeners = new String[0];
+        applicationListeners.clear();
         applicationEventListenersList.clear();
         applicationLifecycleListenersObjects = new Object[0];
         jspConfigDescriptor = null;


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

Reply via email to