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 a4058a8c9 Locking inhibitor SPI (#1696)
a4058a8c9 is described below

commit a4058a8c94b93e7fcc25bc7705d95469683460be
Author: Tamas Cservenak <[email protected]>
AuthorDate: Mon Dec 1 17:33:51 2025 +0100

    Locking inhibitor SPI (#1696)
    
    A new SPI that offers ability to augment Resolver locking and inhibit 
locking on certain resources.
    
    Out of the box RRF prefix file inhibition is provided.
    
    Fixes #1663
    Fixes #1641
---
 .../filter/PrefixesLockingInhibitorFactory.java    | 61 ++++++++++++++++
 .../PrefixesRemoteRepositoryFilterSource.java      |  2 +-
 .../synccontext/named/InhibitingNameMapper.java    | 69 ++++++++++++++++++
 .../named/NamedLockFactoryAdapterFactoryImpl.java  | 30 ++++++--
 .../named/InhibitingNameMapperTest.java            | 83 ++++++++++++++++++++++
 .../aether/spi/locking/LockingInhibitor.java       | 45 ++++++++++++
 .../spi/locking/LockingInhibitorFactory.java       | 43 +++++++++++
 .../eclipse/aether/spi/locking/package-info.java   | 25 +++++++
 .../aether/supplier/RepositorySystemSupplier.java  | 23 +++++-
 .../aether/supplier/RepositorySystemSupplier.java  | 23 +++++-
 10 files changed, 397 insertions(+), 7 deletions(-)

diff --git 
a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/filter/PrefixesLockingInhibitorFactory.java
 
b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/filter/PrefixesLockingInhibitorFactory.java
new file mode 100644
index 000000000..0034cb89f
--- /dev/null
+++ 
b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/filter/PrefixesLockingInhibitorFactory.java
@@ -0,0 +1,61 @@
+/*
+ * 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.internal.impl.filter;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import java.util.Optional;
+import java.util.function.Predicate;
+
+import org.eclipse.aether.RepositorySystemSession;
+import org.eclipse.aether.metadata.Metadata;
+import org.eclipse.aether.spi.locking.LockingInhibitor;
+import org.eclipse.aether.spi.locking.LockingInhibitorFactory;
+
+/**
+ * Locking inhibitor for RRF prefix files. They are perfect candidates, as 
they are created on remote, and locally are
+ * only cached and read, and they do not clash on local file system (local 
repo) either, as they are stored in a file
+ * that has origin repository factored in (as any metadata is).
+ *
+ * @since 2.0.14
+ */
+@Singleton
+@Named(PrefixesLockingInhibitorFactory.NAME)
+public class PrefixesLockingInhibitorFactory implements 
LockingInhibitorFactory, LockingInhibitor {
+    public static final String NAME = 
PrefixesRemoteRepositoryFilterSource.NAME;
+
+    /**
+     * Metadata predicate tailored to RRF prefixes.
+     */
+    private static final Predicate<Metadata> PREFIX_PREDICATE = m -> 
"".equals(m.getGroupId())
+            && "".equals(m.getArtifactId())
+            && "".equals(m.getVersion())
+            && 
PrefixesRemoteRepositoryFilterSource.PREFIX_FILE_TYPE.equals(m.getType());
+
+    @Override
+    public Optional<LockingInhibitor> newInstance(RepositorySystemSession 
session) {
+        return Optional.of(this);
+    }
+
+    @Override
+    public boolean preventMetadataLocking(Metadata metadata) {
+        return PREFIX_PREDICATE.test(metadata);
+    }
+}
diff --git 
a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/filter/PrefixesRemoteRepositoryFilterSource.java
 
b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/filter/PrefixesRemoteRepositoryFilterSource.java
index 8e77aab21..c34c3f7fd 100644
--- 
a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/filter/PrefixesRemoteRepositoryFilterSource.java
+++ 
b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/filter/PrefixesRemoteRepositoryFilterSource.java
@@ -86,7 +86,7 @@ public final class PrefixesRemoteRepositoryFilterSource 
extends RemoteRepository
     private static final String CONFIG_PROPS_PREFIX =
             RemoteRepositoryFilterSourceSupport.CONFIG_PROPS_PREFIX + NAME + 
".";
 
-    private static final String PREFIX_FILE_TYPE = ".meta/prefixes.txt";
+    static final String PREFIX_FILE_TYPE = ".meta/prefixes.txt";
 
     /**
      * Configuration to enable the Prefixes filter (enabled by default). Can 
be fine-tuned per repository using
diff --git 
a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/named/InhibitingNameMapper.java
 
b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/named/InhibitingNameMapper.java
new file mode 100644
index 000000000..202232d51
--- /dev/null
+++ 
b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/named/InhibitingNameMapper.java
@@ -0,0 +1,69 @@
+/*
+ * 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.internal.impl.synccontext.named;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.eclipse.aether.RepositorySystemSession;
+import org.eclipse.aether.artifact.Artifact;
+import org.eclipse.aether.metadata.Metadata;
+import org.eclipse.aether.named.NamedLockKey;
+import org.eclipse.aether.spi.locking.LockingInhibitor;
+
+import static java.util.Objects.requireNonNull;
+
+/**
+ * Wrapping {@link NameMapper} class that applies discovered {@link 
org.eclipse.aether.spi.locking.LockingInhibitor}.
+ *
+ * @since 2.0.14
+ */
+public class InhibitingNameMapper implements NameMapper {
+    private final NameMapper delegate;
+    private final List<LockingInhibitor> lockingInhibitors;
+
+    public InhibitingNameMapper(NameMapper delegate, List<LockingInhibitor> 
lockingInhibitors) {
+        this.delegate = requireNonNull(delegate);
+        this.lockingInhibitors = requireNonNull(lockingInhibitors);
+    }
+
+    @Override
+    public boolean isFileSystemFriendly() {
+        return delegate.isFileSystemFriendly();
+    }
+
+    @Override
+    public Collection<NamedLockKey> nameLocks(
+            RepositorySystemSession session,
+            Collection<? extends Artifact> artifacts,
+            Collection<? extends Metadata> metadatas) {
+        if (artifacts != null) {
+            artifacts = artifacts.stream()
+                    .filter(a -> lockingInhibitors.stream().noneMatch(i -> 
i.preventArtifactLocking(a)))
+                    .collect(Collectors.toList());
+        }
+        if (metadatas != null) {
+            metadatas = metadatas.stream()
+                    .filter(m -> lockingInhibitors.stream().noneMatch(i -> 
i.preventMetadataLocking(m)))
+                    .collect(Collectors.toList());
+        }
+        return delegate.nameLocks(session, artifacts, metadatas);
+    }
+}
diff --git 
a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/named/NamedLockFactoryAdapterFactoryImpl.java
 
b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/named/NamedLockFactoryAdapterFactoryImpl.java
index 868b0da6a..ac56e8a6e 100644
--- 
a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/named/NamedLockFactoryAdapterFactoryImpl.java
+++ 
b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/named/NamedLockFactoryAdapterFactoryImpl.java
@@ -30,6 +30,8 @@ import org.eclipse.aether.RepositorySystemSession;
 import org.eclipse.aether.impl.RepositorySystemLifecycle;
 import org.eclipse.aether.named.NamedLockFactory;
 import org.eclipse.aether.named.providers.FileLockNamedLockFactory;
+import org.eclipse.aether.spi.locking.LockingInhibitor;
+import org.eclipse.aether.spi.locking.LockingInhibitorFactory;
 import org.eclipse.aether.util.ConfigUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -85,12 +87,21 @@ public class NamedLockFactoryAdapterFactoryImpl implements 
NamedLockFactoryAdapt
 
     protected final String defaultNameMapperName;
 
+    protected final Map<String, LockingInhibitorFactory> 
lockingInhibitorFactories;
+
     @Inject
     public NamedLockFactoryAdapterFactoryImpl(
             final Map<String, NamedLockFactory> factories,
             final Map<String, NameMapper> nameMappers,
+            final Map<String, LockingInhibitorFactory> 
lockingInhibitorFactories,
             final RepositorySystemLifecycle lifecycle) {
-        this(factories, DEFAULT_FACTORY_NAME, nameMappers, 
DEFAULT_NAME_MAPPER_NAME, lifecycle);
+        this(
+                factories,
+                DEFAULT_FACTORY_NAME,
+                nameMappers,
+                DEFAULT_NAME_MAPPER_NAME,
+                lockingInhibitorFactories,
+                lifecycle);
     }
 
     public NamedLockFactoryAdapterFactoryImpl(
@@ -98,11 +109,13 @@ public class NamedLockFactoryAdapterFactoryImpl implements 
NamedLockFactoryAdapt
             final String defaultFactoryName,
             final Map<String, NameMapper> nameMappers,
             final String defaultNameMapperName,
+            final Map<String, LockingInhibitorFactory> 
lockingInhibitorFactories,
             final RepositorySystemLifecycle lifecycle) {
         this.factories = requireNonNull(factories);
         this.defaultFactoryName = requireNonNull(defaultFactoryName);
         this.nameMappers = requireNonNull(nameMappers);
         this.defaultNameMapperName = requireNonNull(defaultNameMapperName);
+        this.lockingInhibitorFactories = 
requireNonNull(lockingInhibitorFactories);
         lifecycle.addOnSystemEndedHandler(this::shutdown);
 
         logger.debug(
@@ -125,7 +138,7 @@ public class NamedLockFactoryAdapterFactoryImpl implements 
NamedLockFactoryAdapt
     protected NamedLockFactoryAdapter createAdapter(RepositorySystemSession 
session) {
         final String nameMapperName = 
requireNonNull(getNameMapperName(session));
         final String factoryName = requireNonNull(getFactoryName(session));
-        final NameMapper nameMapper = selectNameMapper(nameMapperName);
+        final NameMapper nameMapper = selectNameMapper(session, 
nameMapperName);
         final NamedLockFactory factory = selectFactory(factoryName);
         logger.debug("Creating adapter using nameMapper '{}' and factory 
'{}'", nameMapperName, factoryName);
         return new NamedLockFactoryAdapter(nameMapper, factory);
@@ -172,14 +185,23 @@ public class NamedLockFactoryAdapterFactoryImpl 
implements NamedLockFactoryAdapt
     }
 
     /**
-     * Selects a name mapper, never returns {@code null}.
+     * Selects a name mapper, never returns {@code null}. Applies inhibitors.
      */
-    protected NameMapper selectNameMapper(final String nameMapperName) {
+    protected NameMapper selectNameMapper(final RepositorySystemSession 
session, final String nameMapperName) {
         NameMapper nameMapper = nameMappers.get(nameMapperName);
         if (nameMapper == null) {
             throw new IllegalArgumentException(
                     "Unknown NameMapper name: '" + nameMapperName + "', known 
ones: " + nameMappers.keySet());
         }
+        if (!lockingInhibitorFactories.isEmpty()) {
+            ArrayList<LockingInhibitor> inhibitors = new ArrayList<>();
+            for (LockingInhibitorFactory factory : 
lockingInhibitorFactories.values()) {
+                factory.newInstance(session).ifPresent(inhibitors::add);
+            }
+            if (!inhibitors.isEmpty()) {
+                return new InhibitingNameMapper(nameMapper, inhibitors);
+            }
+        }
         return nameMapper;
     }
 
diff --git 
a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/synccontext/named/InhibitingNameMapperTest.java
 
b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/synccontext/named/InhibitingNameMapperTest.java
new file mode 100644
index 000000000..c4718a67c
--- /dev/null
+++ 
b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/synccontext/named/InhibitingNameMapperTest.java
@@ -0,0 +1,83 @@
+/*
+ * 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.internal.impl.synccontext.named;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.eclipse.aether.artifact.Artifact;
+import org.eclipse.aether.artifact.DefaultArtifact;
+import org.eclipse.aether.metadata.DefaultMetadata;
+import org.eclipse.aether.metadata.Metadata;
+import org.eclipse.aether.named.NamedLockKey;
+import org.eclipse.aether.spi.locking.LockingInhibitor;
+import org.junit.jupiter.api.Test;
+
+import static java.util.Collections.singletonList;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class InhibitingNameMapperTest extends NameMapperTestSupport {
+    NameMapper mapper = new InhibitingNameMapper(
+            NameMappers.gavNameMapper(true),
+            Arrays.asList(
+                    new LockingInhibitor() {
+                        @Override
+                        public boolean preventArtifactLocking(Artifact 
artifact) {
+                            return "no.lock".equals(artifact.getGroupId());
+                        }
+                    },
+                    new LockingInhibitor() {
+                        @Override
+                        public boolean preventMetadataLocking(Metadata 
metadata) {
+                            return "no.lock".equals(metadata.getGroupId());
+                        }
+                    }));
+
+    @Test
+    void singleArtifactWithLocking() {
+        DefaultArtifact artifact = new DefaultArtifact("group:artifact:1.0");
+        Collection<NamedLockKey> names = mapper.nameLocks(session, 
singletonList(artifact), null);
+        assertEquals(1, names.size());
+        assertEquals("artifact~group~artifact~1.0.lock", 
names.iterator().next().name());
+    }
+
+    @Test
+    void singleArtifactWithoutLocking() {
+        DefaultArtifact artifact = new DefaultArtifact("no.lock:artifact:1.0");
+        Collection<NamedLockKey> names = mapper.nameLocks(session, 
singletonList(artifact), null);
+        assertEquals(0, names.size());
+    }
+
+    @Test
+    void combined() {
+        Collection<NamedLockKey> names = mapper.nameLocks(
+                session,
+                Arrays.asList(new DefaultArtifact("group:artifact:1.0"), new 
DefaultArtifact("no.lock:artifact:1.0")),
+                Arrays.asList(
+                        new DefaultMetadata(
+                                "group", "artifact", "maven-metadata.xml", 
Metadata.Nature.RELEASE_OR_SNAPSHOT),
+                        new DefaultMetadata(
+                                "no.lock", "artifact", "maven-metadata.xml", 
Metadata.Nature.RELEASE_OR_SNAPSHOT)));
+        assertEquals(2, names.size());
+        ArrayList<NamedLockKey> keys = new ArrayList<>(names);
+        assertEquals("artifact~group~artifact~1.0.lock", keys.get(0).name());
+        assertEquals("metadata~group~artifact.lock", keys.get(1).name());
+    }
+}
diff --git 
a/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/locking/LockingInhibitor.java
 
b/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/locking/LockingInhibitor.java
new file mode 100644
index 000000000..fea682225
--- /dev/null
+++ 
b/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/locking/LockingInhibitor.java
@@ -0,0 +1,45 @@
+/*
+ * 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.spi.locking;
+
+import org.eclipse.aether.artifact.Artifact;
+import org.eclipse.aether.metadata.Metadata;
+
+/**
+ * Locking inhibitor may prevent Resolver locking to happen on certain 
resources.
+ *
+ * @since 2.0.14
+ */
+public interface LockingInhibitor {
+    /**
+     * Should return {@code true for artifacts that needs lock inhibition.
+     * <p>
+     * <em>Warning: you do not want to override this method, or if you do, 
think twice.</em>
+     */
+    default boolean preventArtifactLocking(Artifact artifact) {
+        return false;
+    }
+
+    /**
+     * Should return {@code true} for metadata that needs lock inhibition.
+     */
+    default boolean preventMetadataLocking(Metadata metadata) {
+        return false;
+    }
+}
diff --git 
a/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/locking/LockingInhibitorFactory.java
 
b/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/locking/LockingInhibitorFactory.java
new file mode 100644
index 000000000..e27de99e6
--- /dev/null
+++ 
b/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/locking/LockingInhibitorFactory.java
@@ -0,0 +1,43 @@
+/*
+ * 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.spi.locking;
+
+import java.util.Optional;
+
+import org.eclipse.aether.RepositorySystemSession;
+
+/**
+ * A factory to create {@link LockingInhibitor} instances, that are capable to 
augment Resolver locking subsystem and
+ * prevent locking to happen on certain resources.
+ * <p>
+ * <em>Warning: locking inhibition should be applied ONLY to resources that do 
not conflict on disk (i.e. local
+ * repository) and are NOT produced/written or altered in any way by Resolver, 
merely cached and read. Hence, despite
+ * artifact locking inhibition is given as option, it should never happen in 
fact, as aforementioned conditions
+ * never stand for them. On the other hand, good examples of resources may be 
needing locking inhibition are
+ * archetype catalogs and RRF prefix files, as both are metadata, hence their 
remotely fetched cache entries do not
+ * conflict locally, furthermore both are produced by remote entities only, 
and are just cached and read by Maven.
+ *
+ * @since 2.0.14
+ */
+public interface LockingInhibitorFactory {
+    /**
+     * May return a {@link LockingInhibitor} or just empty {@link Optional}, 
if for example disabled.
+     */
+    Optional<LockingInhibitor> newInstance(RepositorySystemSession session);
+}
diff --git 
a/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/locking/package-info.java
 
b/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/locking/package-info.java
new file mode 100644
index 000000000..9d9eb0f24
--- /dev/null
+++ 
b/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/locking/package-info.java
@@ -0,0 +1,25 @@
+// CHECKSTYLE_OFF: RegexpHeader
+/*
+ * 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.
+ */
+/**
+ * The contracts for locking subsystem customizations.
+ *
+ * @since 2.0.14
+ */
+package org.eclipse.aether.spi.locking;
diff --git 
a/maven-resolver-supplier-mvn3/src/main/java/org/eclipse/aether/supplier/RepositorySystemSupplier.java
 
b/maven-resolver-supplier-mvn3/src/main/java/org/eclipse/aether/supplier/RepositorySystemSupplier.java
index 26abebd3e..3766aa689 100644
--- 
a/maven-resolver-supplier-mvn3/src/main/java/org/eclipse/aether/supplier/RepositorySystemSupplier.java
+++ 
b/maven-resolver-supplier-mvn3/src/main/java/org/eclipse/aether/supplier/RepositorySystemSupplier.java
@@ -102,6 +102,7 @@ import 
org.eclipse.aether.internal.impl.collect.df.DfDependencyCollector;
 import 
org.eclipse.aether.internal.impl.filter.DefaultRemoteRepositoryFilterManager;
 import 
org.eclipse.aether.internal.impl.filter.FilteringPipelineRepositoryConnectorFactory;
 import 
org.eclipse.aether.internal.impl.filter.GroupIdRemoteRepositoryFilterSource;
+import org.eclipse.aether.internal.impl.filter.PrefixesLockingInhibitorFactory;
 import 
org.eclipse.aether.internal.impl.filter.PrefixesRemoteRepositoryFilterSource;
 import 
org.eclipse.aether.internal.impl.offline.OfflinePipelineRepositoryConnectorFactory;
 import 
org.eclipse.aether.internal.impl.resolution.TrustedChecksumsArtifactResolverPostProcessor;
@@ -139,6 +140,7 @@ import 
org.eclipse.aether.spi.connector.transport.http.ChecksumExtractorStrategy
 import org.eclipse.aether.spi.io.ChecksumProcessor;
 import org.eclipse.aether.spi.io.PathProcessor;
 import org.eclipse.aether.spi.localrepo.LocalRepositoryManagerFactory;
+import org.eclipse.aether.spi.locking.LockingInhibitorFactory;
 import org.eclipse.aether.spi.remoterepo.RepositoryKeyFunctionFactory;
 import org.eclipse.aether.spi.resolution.ArtifactResolverPostProcessor;
 import org.eclipse.aether.spi.synccontext.SyncContextFactory;
@@ -379,6 +381,22 @@ public class RepositorySystemSupplier implements 
Supplier<RepositorySystem> {
         return result;
     }
 
+    private Map<String, LockingInhibitorFactory> lockingInhibitorFactories;
+
+    public final Map<String, LockingInhibitorFactory> 
getLockingInhibitorFactories() {
+        checkClosed();
+        if (lockingInhibitorFactories == null) {
+            lockingInhibitorFactories = createLockingInhibitorFactories();
+        }
+        return lockingInhibitorFactories;
+    }
+
+    protected Map<String, LockingInhibitorFactory> 
createLockingInhibitorFactories() {
+        HashMap<String, LockingInhibitorFactory> result = new HashMap<>();
+        result.put(PrefixesLockingInhibitorFactory.NAME, new 
PrefixesLockingInhibitorFactory());
+        return result;
+    }
+
     private NamedLockFactoryAdapterFactory namedLockFactoryAdapterFactory;
 
     public final NamedLockFactoryAdapterFactory 
getNamedLockFactoryAdapterFactory() {
@@ -391,7 +409,10 @@ public class RepositorySystemSupplier implements 
Supplier<RepositorySystem> {
 
     protected NamedLockFactoryAdapterFactory 
createNamedLockFactoryAdapterFactory() {
         return new NamedLockFactoryAdapterFactoryImpl(
-                getNamedLockFactories(), getNameMappers(), 
getRepositorySystemLifecycle());
+                getNamedLockFactories(),
+                getNameMappers(),
+                getLockingInhibitorFactories(),
+                getRepositorySystemLifecycle());
     }
 
     private SyncContextFactory syncContextFactory;
diff --git 
a/maven-resolver-supplier-mvn4/src/main/java/org/eclipse/aether/supplier/RepositorySystemSupplier.java
 
b/maven-resolver-supplier-mvn4/src/main/java/org/eclipse/aether/supplier/RepositorySystemSupplier.java
index 870b6b1c8..3bd5ff3d7 100644
--- 
a/maven-resolver-supplier-mvn4/src/main/java/org/eclipse/aether/supplier/RepositorySystemSupplier.java
+++ 
b/maven-resolver-supplier-mvn4/src/main/java/org/eclipse/aether/supplier/RepositorySystemSupplier.java
@@ -106,6 +106,7 @@ import 
org.eclipse.aether.internal.impl.collect.df.DfDependencyCollector;
 import 
org.eclipse.aether.internal.impl.filter.DefaultRemoteRepositoryFilterManager;
 import 
org.eclipse.aether.internal.impl.filter.FilteringPipelineRepositoryConnectorFactory;
 import 
org.eclipse.aether.internal.impl.filter.GroupIdRemoteRepositoryFilterSource;
+import org.eclipse.aether.internal.impl.filter.PrefixesLockingInhibitorFactory;
 import 
org.eclipse.aether.internal.impl.filter.PrefixesRemoteRepositoryFilterSource;
 import 
org.eclipse.aether.internal.impl.offline.OfflinePipelineRepositoryConnectorFactory;
 import 
org.eclipse.aether.internal.impl.resolution.TrustedChecksumsArtifactResolverPostProcessor;
@@ -143,6 +144,7 @@ import 
org.eclipse.aether.spi.connector.transport.http.ChecksumExtractorStrategy
 import org.eclipse.aether.spi.io.ChecksumProcessor;
 import org.eclipse.aether.spi.io.PathProcessor;
 import org.eclipse.aether.spi.localrepo.LocalRepositoryManagerFactory;
+import org.eclipse.aether.spi.locking.LockingInhibitorFactory;
 import org.eclipse.aether.spi.remoterepo.RepositoryKeyFunctionFactory;
 import org.eclipse.aether.spi.resolution.ArtifactResolverPostProcessor;
 import org.eclipse.aether.spi.synccontext.SyncContextFactory;
@@ -383,6 +385,22 @@ public class RepositorySystemSupplier implements 
Supplier<RepositorySystem> {
         return result;
     }
 
+    private Map<String, LockingInhibitorFactory> lockingInhibitorFactories;
+
+    public final Map<String, LockingInhibitorFactory> 
getLockingInhibitorFactories() {
+        checkClosed();
+        if (lockingInhibitorFactories == null) {
+            lockingInhibitorFactories = createLockingInhibitorFactories();
+        }
+        return lockingInhibitorFactories;
+    }
+
+    protected Map<String, LockingInhibitorFactory> 
createLockingInhibitorFactories() {
+        HashMap<String, LockingInhibitorFactory> result = new HashMap<>();
+        result.put(PrefixesLockingInhibitorFactory.NAME, new 
PrefixesLockingInhibitorFactory());
+        return result;
+    }
+
     private NamedLockFactoryAdapterFactory namedLockFactoryAdapterFactory;
 
     public final NamedLockFactoryAdapterFactory 
getNamedLockFactoryAdapterFactory() {
@@ -395,7 +413,10 @@ public class RepositorySystemSupplier implements 
Supplier<RepositorySystem> {
 
     protected NamedLockFactoryAdapterFactory 
createNamedLockFactoryAdapterFactory() {
         return new NamedLockFactoryAdapterFactoryImpl(
-                getNamedLockFactories(), getNameMappers(), 
getRepositorySystemLifecycle());
+                getNamedLockFactories(),
+                getNameMappers(),
+                getLockingInhibitorFactories(),
+                getRepositorySystemLifecycle());
     }
 
     private SyncContextFactory syncContextFactory;

Reply via email to