This is an automated email from the ASF dual-hosted git repository. jsedding pushed a commit to branch resolver-2.x-backports in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-servlets-resolver.git
commit 84114986facc68744af3bcc6ab179923f036aa19 Author: Jörg Hoh <[email protected]> AuthorDate: Mon May 12 17:04:18 2025 +0200 SLING-12433 fix concurrency issue when registering servlets (#59) use locking to prevent ConcurrentModificationExceptions when servlets are registered concurrently. (cherry picked from commit 439d822bb2e2aa686aa1b3e4621de20975bb252e) --- .../resolver/internal/resource/ServletMounter.java | 34 ++++++++++++++-------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/src/main/java/org/apache/sling/servlets/resolver/internal/resource/ServletMounter.java b/src/main/java/org/apache/sling/servlets/resolver/internal/resource/ServletMounter.java index 757e036..516aa95 100644 --- a/src/main/java/org/apache/sling/servlets/resolver/internal/resource/ServletMounter.java +++ b/src/main/java/org/apache/sling/servlets/resolver/internal/resource/ServletMounter.java @@ -32,6 +32,8 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; import org.apache.sling.api.request.RequestUtil; import org.apache.sling.api.resource.ResourceResolverFactory; @@ -90,6 +92,7 @@ public class ServletMounter { private final MergingServletResourceProvider provider; private final Set<ServiceRegistration<?>> providerRegs; + private final Lock providerRegsLock = new ReentrantLock(); // to guard concurrent access to the providerRegs private final ConcurrentHashMap<ResolutionCache, ResolutionCache> resolutionCaches = new ConcurrentHashMap<>(); @@ -249,20 +252,27 @@ public class ServletMounter { if (this.provider != null) { this.provider.add(srProvider, reference); if (pathProviders) { - outer: - for (final String path : srProvider.getServletPaths()) { - String root = - path.indexOf('/', 1) != -1 ? path.substring(0, path.indexOf('/', 1) + 1) : path; - for (ServiceRegistration<?> reg : providerRegs) { - if (root.equals(reg.getReference().getProperty(ResourceProvider.PROPERTY_ROOT))) { - continue outer; + providerRegsLock.lock(); + try { + outer: + for (final String path : srProvider.getServletPaths()) { + String root = path.indexOf('/', 1) != -1 + ? path.substring(0, path.indexOf('/', 1) + 1) + : path; + for (ServiceRegistration<?> reg : providerRegs) { + if (root.equals( + reg.getReference().getProperty(ResourceProvider.PROPERTY_ROOT))) { + continue outer; + } } + final Dictionary<String, Object> params = new Hashtable<>(); + params.put(ResourceProvider.PROPERTY_ROOT, root); + params.put(Constants.SERVICE_DESCRIPTION, "ServletResourceProvider for Servlets"); + params.put(ResourceProvider.PROPERTY_MODE, ResourceProvider.MODE_PASSTHROUGH); + providerRegs.add(context.registerService(ResourceProvider.class, provider, params)); } - final Dictionary<String, Object> params = new Hashtable<>(); - params.put(ResourceProvider.PROPERTY_ROOT, root); - params.put(Constants.SERVICE_DESCRIPTION, "ServletResourceProvider for Servlets"); - params.put(ResourceProvider.PROPERTY_MODE, ResourceProvider.MODE_PASSTHROUGH); - providerRegs.add(context.registerService(ResourceProvider.class, provider, params)); + } finally { + providerRegsLock.unlock(); } } resolutionCaches.values().forEach(ResolutionCache::flushCache);
