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

cstamas pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven-resolver.git


The following commit(s) were added to refs/heads/master by this push:
     new 0c4f7a4fa GH-1768 Drastically simplify auth caching (#1791)
0c4f7a4fa is described below

commit 0c4f7a4fa3c476924e5f113eaa86ddb888fe58a0
Author: Tamas Cservenak <[email protected]>
AuthorDate: Thu Feb 12 12:18:07 2026 +0100

    GH-1768 Drastically simplify auth caching (#1791)
    
    As there is a reproducible issue for proxy auth cache. Seems auth cache 
fall apart in the moment non-single thread flow happens. Instead to chase and 
wrap around our head, I just went to drastically simplify the whole stuff, 
without dropping any existing feature, and making sure that reproducer does not 
reproduce anymore.
    
    Fixes #1768
---
 .../aether/transport/apache/ApacheTransporter.java | 14 +++-
 .../aether/transport/apache/AuthSchemePool.java    | 60 --------------
 .../aether/transport/apache/GlobalState.java       |  8 --
 .../aether/transport/apache/LocalState.java        | 28 -------
 .../aether/transport/apache/SharingAuthCache.java  | 95 ----------------------
 .../transport/apache/SharingHttpContext.java       | 13 +--
 6 files changed, 14 insertions(+), 204 deletions(-)

diff --git 
a/maven-resolver-transport-apache/src/main/java/org/eclipse/aether/transport/apache/ApacheTransporter.java
 
b/maven-resolver-transport-apache/src/main/java/org/eclipse/aether/transport/apache/ApacheTransporter.java
index 505e6314b..0374470c4 100644
--- 
a/maven-resolver-transport-apache/src/main/java/org/eclipse/aether/transport/apache/ApacheTransporter.java
+++ 
b/maven-resolver-transport-apache/src/main/java/org/eclipse/aether/transport/apache/ApacheTransporter.java
@@ -45,6 +45,7 @@ import org.apache.http.HttpResponse;
 import org.apache.http.HttpStatus;
 import org.apache.http.auth.AuthSchemeProvider;
 import org.apache.http.auth.AuthScope;
+import org.apache.http.client.AuthCache;
 import org.apache.http.client.CredentialsProvider;
 import org.apache.http.client.HttpRequestRetryHandler;
 import org.apache.http.client.HttpResponseException;
@@ -72,6 +73,7 @@ import org.apache.http.impl.auth.DigestSchemeFactory;
 import org.apache.http.impl.auth.KerberosSchemeFactory;
 import org.apache.http.impl.auth.NTLMSchemeFactory;
 import org.apache.http.impl.auth.SPNegoSchemeFactory;
+import org.apache.http.impl.client.BasicAuthCache;
 import org.apache.http.impl.client.CloseableHttpClient;
 import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
 import org.apache.http.impl.client.HttpClientBuilder;
@@ -95,6 +97,7 @@ import org.eclipse.aether.spi.io.PathProcessor;
 import org.eclipse.aether.transfer.NoTransporterException;
 import org.eclipse.aether.transfer.TransferCancelledException;
 import org.eclipse.aether.util.ConfigUtils;
+import org.eclipse.aether.util.StringDigestUtil;
 import org.eclipse.aether.util.connector.transport.http.HttpTransporterUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -145,6 +148,8 @@ final class ApacheTransporter extends AbstractTransporter 
implements HttpTranspo
 
     private final boolean supportWebDav;
 
+    private final AuthCache authCache;
+
     @SuppressWarnings("checkstyle:methodlength")
     ApacheTransporter(
             RemoteRepository repository,
@@ -281,6 +286,13 @@ final class ApacheTransporter extends AbstractTransporter 
implements HttpTranspo
             
builder.setConnectionReuseStrategy(NoConnectionReuseStrategy.INSTANCE);
         }
 
+        if (session.getCache() != null) {
+            String authCacheKey = getClass().getSimpleName() + "-" + 
repository.getId() + "-"
+                    + StringDigestUtil.sha1(repository.toString());
+            this.authCache = (AuthCache) 
session.getCache().computeIfAbsent(session, authCacheKey, BasicAuthCache::new);
+        } else {
+            this.authCache = new BasicAuthCache();
+        }
         this.client = builder.build();
     }
 
@@ -382,10 +394,10 @@ final class ApacheTransporter extends AbstractTransporter 
implements HttpTranspo
     private void execute(HttpUriRequest request, EntityGetter getter) throws 
Exception {
         try {
             SharingHttpContext context = new SharingHttpContext(state);
+            context.setAuthCache(authCache);
             prepare(request, context);
             try (CloseableHttpResponse response = client.execute(server, 
request, context)) {
                 try {
-                    context.close();
                     handleStatus(response);
                     if (getter != null) {
                         getter.handle(response);
diff --git 
a/maven-resolver-transport-apache/src/main/java/org/eclipse/aether/transport/apache/AuthSchemePool.java
 
b/maven-resolver-transport-apache/src/main/java/org/eclipse/aether/transport/apache/AuthSchemePool.java
deleted file mode 100644
index 592ab4ba6..000000000
--- 
a/maven-resolver-transport-apache/src/main/java/org/eclipse/aether/transport/apache/AuthSchemePool.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.eclipse.aether.transport.apache;
-
-import java.util.LinkedList;
-
-import org.apache.http.auth.AuthScheme;
-import org.apache.http.client.config.AuthSchemes;
-import org.apache.http.impl.auth.BasicScheme;
-
-/**
- * Pool of (equivalent) auth schemes for a single host.
- */
-final class AuthSchemePool {
-
-    private final LinkedList<AuthScheme> authSchemes;
-
-    private String schemeName;
-
-    AuthSchemePool() {
-        authSchemes = new LinkedList<>();
-    }
-
-    public synchronized AuthScheme get() {
-        AuthScheme authScheme = null;
-        if (!authSchemes.isEmpty()) {
-            authScheme = authSchemes.removeLast();
-        } else if (AuthSchemes.BASIC.equalsIgnoreCase(schemeName)) {
-            authScheme = new BasicScheme();
-        }
-        return authScheme;
-    }
-
-    public synchronized void put(AuthScheme authScheme) {
-        if (authScheme == null) {
-            return;
-        }
-        if (!authScheme.getSchemeName().equals(schemeName)) {
-            schemeName = authScheme.getSchemeName();
-            authSchemes.clear();
-        }
-        authSchemes.add(authScheme);
-    }
-}
diff --git 
a/maven-resolver-transport-apache/src/main/java/org/eclipse/aether/transport/apache/GlobalState.java
 
b/maven-resolver-transport-apache/src/main/java/org/eclipse/aether/transport/apache/GlobalState.java
index b64c14971..9b2d453b7 100644
--- 
a/maven-resolver-transport-apache/src/main/java/org/eclipse/aether/transport/apache/GlobalState.java
+++ 
b/maven-resolver-transport-apache/src/main/java/org/eclipse/aether/transport/apache/GlobalState.java
@@ -29,7 +29,6 @@ import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.TimeUnit;
 
-import org.apache.http.HttpHost;
 import org.apache.http.config.RegistryBuilder;
 import org.apache.http.conn.HttpClientConnectionManager;
 import org.apache.http.conn.socket.ConnectionSocketFactory;
@@ -96,8 +95,6 @@ final class GlobalState implements Closeable {
 
     private final ConcurrentMap<CompoundKey, Object> userTokens;
 
-    private final ConcurrentMap<HttpHost, AuthSchemePool> authSchemePools;
-
     private final ConcurrentMap<CompoundKey, Boolean> expectContinues;
 
     public static GlobalState get(RepositorySystemSession session) {
@@ -127,7 +124,6 @@ final class GlobalState implements Closeable {
     private GlobalState() {
         connectionManagers = new ConcurrentHashMap<>();
         userTokens = new ConcurrentHashMap<>();
-        authSchemePools = new ConcurrentHashMap<>();
         expectContinues = new ConcurrentHashMap<>();
     }
 
@@ -217,10 +213,6 @@ final class GlobalState implements Closeable {
         }
     }
 
-    public ConcurrentMap<HttpHost, AuthSchemePool> getAuthSchemePools() {
-        return authSchemePools;
-    }
-
     public Boolean getExpectContinue(CompoundKey key) {
         return expectContinues.get(key);
     }
diff --git 
a/maven-resolver-transport-apache/src/main/java/org/eclipse/aether/transport/apache/LocalState.java
 
b/maven-resolver-transport-apache/src/main/java/org/eclipse/aether/transport/apache/LocalState.java
index 5b31e2ee8..1f079994e 100644
--- 
a/maven-resolver-transport-apache/src/main/java/org/eclipse/aether/transport/apache/LocalState.java
+++ 
b/maven-resolver-transport-apache/src/main/java/org/eclipse/aether/transport/apache/LocalState.java
@@ -19,11 +19,7 @@
 package org.eclipse.aether.transport.apache;
 
 import java.io.Closeable;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
 
-import org.apache.http.HttpHost;
-import org.apache.http.auth.AuthScheme;
 import org.apache.http.conn.HttpClientConnectionManager;
 import org.eclipse.aether.RepositorySystemSession;
 import org.eclipse.aether.repository.RemoteRepository;
@@ -47,8 +43,6 @@ final class LocalState implements Closeable {
 
     private volatile Boolean webDav;
 
-    private final ConcurrentMap<HttpHost, AuthSchemePool> authSchemePools;
-
     LocalState(RepositorySystemSession session, RemoteRepository repo, 
ConnMgrConfig connMgrConfig) {
         global = GlobalState.get(session);
         userToken = this;
@@ -56,13 +50,11 @@ final class LocalState implements Closeable {
             connMgr = GlobalState.newConnectionManager(connMgrConfig);
             userTokenKey = null;
             expectContinueKey = null;
-            authSchemePools = new ConcurrentHashMap<>();
         } else {
             connMgr = global.getConnectionManager(connMgrConfig);
             userTokenKey =
                     new GlobalState.CompoundKey(repo.getId(), repo.getUrl(), 
repo.getAuthentication(), repo.getProxy());
             expectContinueKey = new GlobalState.CompoundKey(repo.getUrl(), 
repo.getProxy());
-            authSchemePools = global.getAuthSchemePools();
         }
     }
 
@@ -107,26 +99,6 @@ final class LocalState implements Closeable {
         this.webDav = webDav;
     }
 
-    public AuthScheme getAuthScheme(HttpHost host) {
-        AuthSchemePool pool = authSchemePools.get(host);
-        if (pool != null) {
-            return pool.get();
-        }
-        return null;
-    }
-
-    public void setAuthScheme(HttpHost host, AuthScheme authScheme) {
-        AuthSchemePool pool = authSchemePools.get(host);
-        if (pool == null) {
-            AuthSchemePool p = new AuthSchemePool();
-            pool = authSchemePools.putIfAbsent(host, p);
-            if (pool == null) {
-                pool = p;
-            }
-        }
-        pool.put(authScheme);
-    }
-
     @Override
     public void close() {
         if (global == null) {
diff --git 
a/maven-resolver-transport-apache/src/main/java/org/eclipse/aether/transport/apache/SharingAuthCache.java
 
b/maven-resolver-transport-apache/src/main/java/org/eclipse/aether/transport/apache/SharingAuthCache.java
deleted file mode 100644
index d868eacaf..000000000
--- 
a/maven-resolver-transport-apache/src/main/java/org/eclipse/aether/transport/apache/SharingAuthCache.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.eclipse.aether.transport.apache;
-
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-import org.apache.http.HttpHost;
-import org.apache.http.auth.AuthScheme;
-import org.apache.http.client.AuthCache;
-
-/**
- * Auth scheme cache that upon clearing releases all cached schemes into a 
pool for future reuse by other requests,
- * thereby reducing challenge-response roundtrips.
- */
-final class SharingAuthCache implements AuthCache {
-
-    private final LocalState state;
-
-    private final ConcurrentHashMap<HttpHost, AuthScheme> authSchemes;
-
-    SharingAuthCache(LocalState state) {
-        this.state = state;
-        authSchemes = new ConcurrentHashMap<>();
-    }
-
-    private static HttpHost toKey(HttpHost host) {
-        if (host.getPort() <= 0) {
-            int port = host.getSchemeName().equalsIgnoreCase("https") ? 443 : 
80;
-            return new HttpHost(host.getHostName(), port, 
host.getSchemeName());
-        }
-        return host;
-    }
-
-    @Override
-    public AuthScheme get(HttpHost host) {
-        host = toKey(host);
-        AuthScheme authScheme = authSchemes.get(host);
-        if (authScheme == null) {
-            authScheme = state.getAuthScheme(host);
-            if (authScheme != null) {
-                authSchemes.put(host, authScheme);
-            }
-        }
-        return authScheme;
-    }
-
-    @Override
-    public void put(HttpHost host, AuthScheme authScheme) {
-        host = toKey(host);
-        if (authScheme != null) {
-            authSchemes.put(host, authScheme);
-        } else {
-            authSchemes.remove(host);
-        }
-    }
-
-    @Override
-    public void remove(HttpHost host) {
-        authSchemes.remove(toKey(host));
-    }
-
-    @Override
-    public void clear() {
-        share();
-        authSchemes.clear();
-    }
-
-    private void share() {
-        for (Map.Entry<HttpHost, AuthScheme> entry : authSchemes.entrySet()) {
-            state.setAuthScheme(entry.getKey(), entry.getValue());
-        }
-    }
-
-    @Override
-    public String toString() {
-        return authSchemes.toString();
-    }
-}
diff --git 
a/maven-resolver-transport-apache/src/main/java/org/eclipse/aether/transport/apache/SharingHttpContext.java
 
b/maven-resolver-transport-apache/src/main/java/org/eclipse/aether/transport/apache/SharingHttpContext.java
index a37aeaa50..659667e82 100644
--- 
a/maven-resolver-transport-apache/src/main/java/org/eclipse/aether/transport/apache/SharingHttpContext.java
+++ 
b/maven-resolver-transport-apache/src/main/java/org/eclipse/aether/transport/apache/SharingHttpContext.java
@@ -18,8 +18,6 @@
  */
 package org.eclipse.aether.transport.apache;
 
-import java.io.Closeable;
-
 import org.apache.http.client.protocol.HttpClientContext;
 
 /**
@@ -28,16 +26,12 @@ import org.apache.http.client.protocol.HttpClientContext;
  * @see <a 
href="http://hc.apache.org/httpcomponents-client-ga/tutorial/html/advanced.html#stateful_conn";>Stateful
 HTTP
  *      connections</a>
  */
-final class SharingHttpContext extends HttpClientContext implements Closeable {
+final class SharingHttpContext extends HttpClientContext {
 
     private final LocalState state;
 
-    private final SharingAuthCache authCache;
-
     SharingHttpContext(LocalState state) {
         this.state = state;
-        authCache = new SharingAuthCache(state);
-        super.setAttribute(HttpClientContext.AUTH_CACHE, authCache);
     }
 
     @Override
@@ -65,9 +59,4 @@ final class SharingHttpContext extends HttpClientContext 
implements Closeable {
         }
         return super.removeAttribute(id);
     }
-
-    @Override
-    public void close() {
-        authCache.clear();
-    }
 }

Reply via email to