Author: markt
Date: Mon Sep 14 18:30:22 2015
New Revision: 1703024

URL: http://svn.apache.org/r1703024
Log:
Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=58373
Fix rare data race with the application event listeners for StandardContext

Modified:
    tomcat/trunk/java/org/apache/catalina/core/StandardContext.java

Modified: tomcat/trunk/java/org/apache/catalina/core/StandardContext.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/StandardContext.java?rev=1703024&r1=1703023&r2=1703024&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/core/StandardContext.java (original)
+++ tomcat/trunk/java/org/apache/catalina/core/StandardContext.java Mon Sep 14 
18:30:22 2015
@@ -42,6 +42,7 @@ import java.util.Set;
 import java.util.Stack;
 import java.util.TreeMap;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReadWriteLock;
@@ -217,12 +218,11 @@ public class StandardContext extends Con
     private final Set<Object> noPluggabilityListeners = new HashSet<>();
 
     /**
-     * The set of instantiated application event listener objects. Note that
+     * The list of instantiated application event listener objects. Note that
      * SCIs and other code may use the pluggability APIs to add listener
      * instances directly to this list before the application starts.
      */
-    private Object applicationEventListenersObjects[] =
-        new Object[0];
+    private List<Object> applicationEventListenersList = new 
CopyOnWriteArrayList<>();
 
 
     /**
@@ -1150,26 +1150,34 @@ public class StandardContext extends Con
 
     @Override
     public Object[] getApplicationEventListeners() {
-        return (applicationEventListenersObjects);
+        return applicationEventListenersList.toArray();
     }
 
 
+    /**
+     * {@inheritDoc}
+     *
+     * Note that this implementation is not thread safe. If two threads call
+     * this method concurrently, the result may be either set of listeners or a
+     * the union of both.
+     */
     @Override
     public void setApplicationEventListeners(Object listeners[]) {
-        applicationEventListenersObjects = listeners;
+        applicationEventListenersList.clear();
+        if (listeners != null && listeners.length > 0) {
+            applicationEventListenersList.addAll(Arrays.asList(listeners));
+        }
     }
 
 
     /**
      * Add a listener to the end of the list of initialized application event
      * listeners.
+     *
+     * @param listener The listener to add
      */
     public void addApplicationEventListener(Object listener) {
-        int len = applicationEventListenersObjects.length;
-        Object[] newListeners = Arrays.copyOf(applicationEventListenersObjects,
-                len + 1);
-        newListeners[len] = listener;
-        applicationEventListenersObjects = newListeners;
+        applicationEventListenersList.add(listener);
     }
 
 
@@ -5578,7 +5586,7 @@ public class StandardContext extends Con
         distributable = false;
 
         applicationListeners = new String[0];
-        applicationEventListenersObjects = new Object[0];
+        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