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

remm pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git


The following commit(s) were added to refs/heads/main by this push:
     new 01215beacc Improve locks handling
01215beacc is described below

commit 01215beaccfbd8139a62074ad7e58abe5e34e85b
Author: remm <r...@apache.org>
AuthorDate: Thu Apr 25 12:11:52 2024 +0200

    Improve locks handling
    
    Fix WebDAV lock null (locks for non existing resources) thread safety
    and removal.
    Add periodic checking for WebDAV locks expiration.
---
 .../apache/catalina/servlets/WebdavServlet.java    | 53 ++++++++++++++++++----
 webapps/docs/changelog.xml                         |  7 +++
 2 files changed, 51 insertions(+), 9 deletions(-)

diff --git a/java/org/apache/catalina/servlets/WebdavServlet.java 
b/java/org/apache/catalina/servlets/WebdavServlet.java
index 1f1aae190b..7afe45a378 100644
--- a/java/org/apache/catalina/servlets/WebdavServlet.java
+++ b/java/org/apache/catalina/servlets/WebdavServlet.java
@@ -37,6 +37,7 @@ import java.util.Locale;
 import java.util.Map;
 import java.util.TimeZone;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
 
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
@@ -53,6 +54,7 @@ import org.apache.catalina.WebResource;
 import org.apache.catalina.connector.RequestFacade;
 import org.apache.catalina.util.DOMWriter;
 import org.apache.catalina.util.XMLWriter;
+import org.apache.tomcat.PeriodicEventListener;
 import org.apache.tomcat.util.buf.HexUtils;
 import org.apache.tomcat.util.http.ConcurrentDateFormat;
 import org.apache.tomcat.util.http.FastHttpDateFormat;
@@ -129,11 +131,9 @@ import org.xml.sax.SAXException;
  * access will be able to edit content available via 
http://host:port/context/content using
  * http://host:port/context/webdavedit/content
  *
- * @author Remy Maucherat
- *
  * @see <a href="https://tools.ietf.org/html/rfc4918";>RFC 4918</a>
  */
-public class WebdavServlet extends DefaultServlet {
+public class WebdavServlet extends DefaultServlet implements 
PeriodicEventListener {
 
     private static final long serialVersionUID = 1L;
 
@@ -273,6 +273,26 @@ public class WebdavServlet extends DefaultServlet {
     }
 
 
+    @Override
+    public void periodicEvent() {
+        // Check expiration of all locks
+        for (LockInfo currentLock : resourceLocks.values()) {
+            if (currentLock.hasExpired()) {
+                resourceLocks.remove(currentLock.path);
+                removeLockNull(currentLock.path);
+            }
+        }
+        Iterator<LockInfo> collectionLocksIterator = 
collectionLocks.iterator();
+        while (collectionLocksIterator.hasNext()) {
+            LockInfo currentLock = collectionLocksIterator.next();
+            if (currentLock.hasExpired()) {
+                collectionLocksIterator.remove();
+                removeLockNull(currentLock.path);
+            }
+        }
+    }
+
+
     // ------------------------------------------------------ Protected Methods
 
     /**
@@ -727,7 +747,7 @@ public class WebdavServlet extends DefaultServlet {
         if (resources.mkdir(path)) {
             resp.setStatus(WebdavStatus.SC_CREATED);
             // Removing any lock-null resource which would be present
-            lockNullResources.remove(path);
+            removeLockNull(path);
         } else {
             resp.sendError(WebdavStatus.SC_CONFLICT);
         }
@@ -787,7 +807,7 @@ public class WebdavServlet extends DefaultServlet {
         super.doPut(req, resp);
 
         // Removing any lock-null resource which would be present
-        lockNullResources.remove(path);
+        removeLockNull(path);
     }
 
 
@@ -1177,7 +1197,7 @@ public class WebdavServlet extends DefaultServlet {
                         int slash = lock.path.lastIndexOf('/');
                         String parentPath = lock.path.substring(0, slash);
 
-                        lockNullResources.computeIfAbsent(parentPath, k -> new 
ArrayList<>()).add(lock.path);
+                        lockNullResources.computeIfAbsent(parentPath, k -> new 
CopyOnWriteArrayList<>()).add(lock.path);
                     }
 
                     // Add the Lock-Token header as by RFC 2518 8.10.1
@@ -1287,7 +1307,7 @@ public class WebdavServlet extends DefaultServlet {
             if (lock.tokens.isEmpty()) {
                 resourceLocks.remove(path);
                 // Removing any lock-null resource which would be present
-                lockNullResources.remove(path);
+                removeLockNull(path);
             }
 
         }
@@ -1308,7 +1328,7 @@ public class WebdavServlet extends DefaultServlet {
                 if (lock.tokens.isEmpty()) {
                     collectionLocksList.remove();
                     // Removing any lock-null resource which would be present
-                    lockNullResources.remove(path);
+                    removeLockNull(path);
                 }
             }
         }
@@ -1552,7 +1572,7 @@ public class WebdavServlet extends DefaultServlet {
 
         // Removing any lock-null resource which would be present at
         // the destination path
-        lockNullResources.remove(destinationPath);
+        removeLockNull(destinationPath);
 
         return true;
     }
@@ -2196,6 +2216,21 @@ public class WebdavServlet extends DefaultServlet {
     }
 
 
+    private void removeLockNull(String path) {
+        int slash = path.lastIndexOf('/');
+        if (slash >= 0) {
+            String parentPath = path.substring(0, slash);
+            List<String> paths = lockNullResources.get(parentPath);
+            if (paths != null) {
+                paths.remove(path);
+            }
+            if (paths.isEmpty()) {
+                lockNullResources.remove(parentPath);
+            }
+        }
+    }
+
+
     // -------------------------------------------------- LockInfo Inner Class
 
     /**
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 8ec96c2a59..46f409d856 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -137,6 +137,13 @@
         Re-factor ElapsedTimeElement in AbstractAccessLogValve to use a 
customizable
         style. (schultz)
       </add>
+      <fix>
+        Fix WebDAV lock null (locks for non existing resources) thread safety
+        and removal. (remm)
+      </fix>
+      <fix>
+        Add periodic checking for WebDAV locks expiration. (remm)
+      </fix>
     </changelog>
   </subsection>
   <subsection name="Coyote">


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

Reply via email to