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 e767edc86 Name mappers cleanup and new GAECV mapper (#1677)
e767edc86 is described below

commit e767edc8679c197d3579ad3911c9bd1f288c9254
Author: Tamas Cservenak <[email protected]>
AuthorDate: Thu Nov 20 16:41:47 2025 +0100

    Name mappers cleanup and new GAECV mapper (#1677)
    
    Cleanup name mappers usage and introduce new, more selective mapper GAECV.
    
    Changes:
    * introduce GAECV next to existing GAV name mapper.
    * make default GAECV
---
 .../impl/synccontext/named/GAECVNameMapper.java    | 66 +++++++++++++++++++
 .../impl/synccontext/named/GAVNameMapper.java      | 74 ++++++++++++++--------
 .../impl/synccontext/named/NameMappers.java        | 71 +++++++++++++++++++--
 .../named/NamedLockFactoryAdapterFactoryImpl.java  |  9 +--
 .../providers/FileGAECVNameMapperProvider.java}    | 35 ++++++----
 .../FileHashingGAECVNameMapperProvider.java}       | 35 ++++++----
 .../named/providers/GAECVNameMapperProvider.java}  | 35 ++++++----
 .../src/site/markdown/synccontextfactory.md.vm     |  5 +-
 .../impl/synccontext/FileLockAdapterTest.java      |  5 +-
 .../NamedLockFactoryAdapterTestSupport.java        |  6 +-
 .../named/BasedirHashingNameMapperTest.java        |  2 +-
 .../synccontext/named/BasedirNameMapperTest.java   |  2 +-
 .../impl/synccontext/named/GAVNameMapperTest.java  |  2 +-
 .../synccontext/named/HashingNameMapperTest.java   |  2 +-
 .../NamedLockFactoryAdapterTestSupport.java        |  5 +-
 .../ipc/NamedLockFactoryAdapterTestSupport.java    |  5 +-
 .../NamedLockFactoryAdapterTestSupport.java        |  5 +-
 .../aether/supplier/RepositorySystemSupplier.java  |  3 +
 .../aether/supplier/RepositorySystemSupplier.java  |  3 +
 src/site/markdown/configuration.md                 |  4 +-
 20 files changed, 286 insertions(+), 88 deletions(-)

diff --git 
a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/named/GAECVNameMapper.java
 
b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/named/GAECVNameMapper.java
new file mode 100644
index 000000000..3d5344beb
--- /dev/null
+++ 
b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/named/GAECVNameMapper.java
@@ -0,0 +1,66 @@
+/*
+ * 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 org.eclipse.aether.artifact.Artifact;
+
+/**
+ * Artifact GAECV {@link NameMapper} extends {@link GAVNameMapper} and 
improves artifact name mapping selectivity by
+ * using all coordinates.
+ *
+ * @since 1.9.25
+ */
+public class GAECVNameMapper extends GAVNameMapper {
+    public GAECVNameMapper(
+            boolean fileSystemFriendly,
+            String artifactPrefix,
+            String artifactSuffix,
+            String metadataPrefix,
+            String metadataSuffix,
+            String fieldSeparator) {
+        super(fileSystemFriendly, artifactPrefix, artifactSuffix, 
metadataPrefix, metadataSuffix, fieldSeparator);
+    }
+
+    @Override
+    protected String getArtifactName(Artifact artifact) {
+        if (artifact.getClassifier().isEmpty()) {
+            return artifactPrefix
+                    + artifact.getGroupId()
+                    + fieldSeparator
+                    + artifact.getArtifactId()
+                    + fieldSeparator
+                    + artifact.getExtension()
+                    + fieldSeparator
+                    + artifact.getBaseVersion()
+                    + artifactSuffix;
+        } else {
+            return artifactPrefix
+                    + artifact.getGroupId()
+                    + fieldSeparator
+                    + artifact.getArtifactId()
+                    + fieldSeparator
+                    + artifact.getExtension()
+                    + fieldSeparator
+                    + artifact.getClassifier()
+                    + fieldSeparator
+                    + artifact.getBaseVersion()
+                    + artifactSuffix;
+        }
+    }
+}
diff --git 
a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/named/GAVNameMapper.java
 
b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/named/GAVNameMapper.java
index 4f26137e4..d51d34531 100644
--- 
a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/named/GAVNameMapper.java
+++ 
b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/named/GAVNameMapper.java
@@ -27,6 +27,7 @@ import org.eclipse.aether.artifact.Artifact;
 import org.eclipse.aether.metadata.Metadata;
 import org.eclipse.aether.named.NamedLockKey;
 import org.eclipse.aether.util.PathUtils;
+import org.eclipse.aether.util.artifact.ArtifactIdUtils;
 
 import static java.util.Objects.requireNonNull;
 
@@ -34,19 +35,22 @@ import static java.util.Objects.requireNonNull;
  * Artifact GAV {@link NameMapper}, uses artifact and metadata coordinates to 
name their corresponding locks. Is not
  * considering local repository, only the artifact coordinates. May use custom 
prefixes and suffixes and separators,
  * hence this instance may or may not be filesystem friendly (depends on 
strings used).
+ * <p>
+ * Note: in earlier Resolver 1.9.x versions this mapper was the default, but 
it changed to {@link GAECVNameMapper}
+ * in 1.9.25.
  */
 public class GAVNameMapper implements NameMapper {
-    private final boolean fileSystemFriendly;
+    protected final boolean fileSystemFriendly;
 
-    private final String artifactPrefix;
+    protected final String artifactPrefix;
 
-    private final String artifactSuffix;
+    protected final String artifactSuffix;
 
-    private final String metadataPrefix;
+    protected final String metadataPrefix;
 
-    private final String metadataSuffix;
+    protected final String metadataSuffix;
 
-    private final String fieldSeparator;
+    protected final String fieldSeparator;
 
     public GAVNameMapper(
             boolean fileSystemFriendly,
@@ -78,47 +82,42 @@ public class GAVNameMapper implements NameMapper {
         TreeSet<NamedLockKey> keys = new 
TreeSet<>(Comparator.comparing(NamedLockKey::name));
         if (artifacts != null) {
             for (Artifact artifact : artifacts) {
-                keys.add(NamedLockKey.of(
-                        getArtifactName(artifact, artifactPrefix, 
fieldSeparator, artifactSuffix),
-                        getArtifactName(artifact, "", ":", "")));
+                keys.add(NamedLockKey.of(getArtifactName(artifact), 
ArtifactIdUtils.toBaseId(artifact)));
             }
         }
 
         if (metadatas != null) {
             for (Metadata metadata : metadatas) {
-                keys.add(NamedLockKey.of(
-                        getMetadataName(metadata, fileSystemFriendly, 
metadataPrefix, fieldSeparator, metadataSuffix),
-                        getMetadataName(metadata, false, "", ":", "")));
+                keys.add(NamedLockKey.of(getMetadataName(metadata), 
toMetadataId(metadata)));
             }
         }
         return keys;
     }
 
-    private static String getArtifactName(Artifact artifact, String prefix, 
String separator, String suffix) {
-        return prefix
+    protected String getArtifactName(Artifact artifact) {
+        return artifactPrefix
                 + artifact.getGroupId()
-                + separator
+                + fieldSeparator
                 + artifact.getArtifactId()
-                + separator
+                + fieldSeparator
                 + artifact.getBaseVersion()
-                + suffix;
+                + artifactSuffix;
     }
 
-    private static final String MAVEN_METADATA = "maven-metadata.xml";
+    protected static final String MAVEN_METADATA = "maven-metadata.xml";
 
-    private static String getMetadataName(
-            Metadata metadata, boolean fileSystemFriendly, String prefix, 
String separator, String suffix) {
-        String name = prefix;
+    protected String getMetadataName(Metadata metadata) {
+        String name = metadataPrefix;
         if (!metadata.getGroupId().isEmpty()) {
             name += metadata.getGroupId();
             if (!metadata.getArtifactId().isEmpty()) {
-                name += separator + metadata.getArtifactId();
+                name += fieldSeparator + metadata.getArtifactId();
                 if (!metadata.getVersion().isEmpty()) {
-                    name += separator + metadata.getVersion();
+                    name += fieldSeparator + metadata.getVersion();
                 }
             }
             if (!MAVEN_METADATA.equals(metadata.getType())) {
-                name += separator
+                name += fieldSeparator
                         + (fileSystemFriendly ? 
PathUtils.stringToPathSegment(metadata.getType()) : metadata.getType());
             }
         } else {
@@ -126,13 +125,38 @@ public class GAVNameMapper implements NameMapper {
                 name += (fileSystemFriendly ? 
PathUtils.stringToPathSegment(metadata.getType()) : metadata.getType());
             }
         }
-        return name + suffix;
+        return name + metadataSuffix;
     }
 
+    protected String toMetadataId(Metadata metadata) {
+        String name = "";
+        if (!metadata.getGroupId().isEmpty()) {
+            name += metadata.getGroupId();
+            if (!metadata.getArtifactId().isEmpty()) {
+                name += ":" + metadata.getArtifactId();
+                if (!metadata.getVersion().isEmpty()) {
+                    name += ":" + metadata.getVersion();
+                }
+            }
+        }
+        if (!metadata.getType().isEmpty()) {
+            name += (name.isEmpty() ? "" : ":") + metadata.getType();
+        }
+        return name;
+    }
+
+    /**
+     * @deprecated Use {@link NameMappers} to create name mappers instead.
+     */
+    @Deprecated
     public static NameMapper gav() {
         return new GAVNameMapper(false, "artifact:", "", "metadata:", "", ":");
     }
 
+    /**
+     * @deprecated Use {@link NameMappers} to create name mappers instead.
+     */
+    @Deprecated
     public static NameMapper fileGav() {
         return new GAVNameMapper(true, "artifact~", ".lock", "metadata~", 
".lock", "~");
     }
diff --git 
a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/named/NameMappers.java
 
b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/named/NameMappers.java
index 6297c21b2..b4cfb85d7 100644
--- 
a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/named/NameMappers.java
+++ 
b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/named/NameMappers.java
@@ -21,11 +21,14 @@ package org.eclipse.aether.internal.impl.synccontext.named;
 /**
  * As end-user "mappers" are actually configurations/compositions and are 
constructed from several NameMapper
  * implementations, this helper class constructing them. This class also holds 
"names" used by service locator and
- * Guice/Sisu as well.
+ * Guice/Sisu as well. Ideally, name mapper you want should exist here, 
constructing name mappers should not be
+ * needed (unless some very specific case or testing).
  *
  * @since 1.9.4
  */
 public final class NameMappers {
+    private NameMappers() {}
+
     public static final String STATIC_NAME = "static";
 
     public static final String GAV_NAME = "gav";
@@ -34,6 +37,21 @@ public final class NameMappers {
 
     public static final String FILE_HGAV_NAME = "file-hgav";
 
+    /**
+     * @since 1.9.25
+     */
+    public static final String GAECV_NAME = "gaecv";
+
+    /**
+     * @since 1.9.25
+     */
+    public static final String FILE_GAECV_NAME = "file-gaecv";
+
+    /**
+     * @since 1.9.25
+     */
+    public static final String FILE_HGAECV_NAME = "file-hgaecv";
+
     /**
      * @since 1.9.6
      */
@@ -46,11 +64,47 @@ public final class NameMappers {
     }
 
     public static NameMapper gavNameMapper() {
-        return GAVNameMapper.gav();
+        return gavNameMapper(false);
+    }
+
+    /**
+     * @since 1.9.25
+     */
+    public static NameMapper gavNameMapper(boolean fileSystemFriendly) {
+        if (fileSystemFriendly) {
+            return new GAVNameMapper(true, "artifact~", ".lock", "metadata~", 
".lock", "~");
+        } else {
+            return new GAVNameMapper(false, "artifact:", "", "metadata:", "", 
":");
+        }
+    }
+
+    /**
+     * @since 1.9.25
+     */
+    public static NameMapper gaecvNameMapper() {
+        return gaecvNameMapper(false);
+    }
+
+    /**
+     * @since 1.9.25
+     */
+    public static NameMapper gaecvNameMapper(boolean fileSystemFriendly) {
+        if (fileSystemFriendly) {
+            return new GAECVNameMapper(true, "artifact~", ".lock", 
"metadata~", ".lock", "~");
+        } else {
+            return new GAECVNameMapper(false, "artifact:", "", "metadata:", 
"", ":");
+        }
     }
 
     public static NameMapper fileGavNameMapper() {
-        return new BasedirNameMapper(GAVNameMapper.fileGav());
+        return new BasedirNameMapper(gavNameMapper(true));
+    }
+
+    /**
+     * @since 1.9.25
+     */
+    public static NameMapper fileGaecvNameMapper() {
+        return new BasedirNameMapper(gaecvNameMapper(true));
     }
 
     /**
@@ -61,10 +115,17 @@ public final class NameMappers {
     }
 
     public static NameMapper fileHashingGavNameMapper() {
-        return new BasedirNameMapper(new 
HashingNameMapper(GAVNameMapper.gav()));
+        return new BasedirNameMapper(new 
HashingNameMapper(gavNameMapper(false)));
+    }
+
+    /**
+     * @since 1.9.25
+     */
+    public static NameMapper fileHashingGaecvNameMapper() {
+        return new BasedirNameMapper(new 
HashingNameMapper(gaecvNameMapper(false)));
     }
 
     public static NameMapper discriminatingNameMapper() {
-        return new DiscriminatingNameMapper(GAVNameMapper.gav());
+        return new DiscriminatingNameMapper(gavNameMapper(false));
     }
 }
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 dabe250b0..868b0da6a 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
@@ -53,10 +53,11 @@ import static java.util.Objects.requireNonNull;
 public class NamedLockFactoryAdapterFactoryImpl implements 
NamedLockFactoryAdapterFactory {
     public static final String DEFAULT_FACTORY_NAME = 
FileLockNamedLockFactory.NAME;
 
-    public static final String DEFAULT_NAME_MAPPER_NAME = 
NameMappers.FILE_GAV_NAME;
+    public static final String DEFAULT_NAME_MAPPER_NAME = 
NameMappers.FILE_GAECV_NAME;
 
     /**
-     * Name of the lock factory to use in session.
+     * Name of the lock factory to use in session. Out of the box supported 
ones are "file-lock", "rwlock-local",
+     * "semaphore-local", "noop". By adding extensions one can extend 
available lock factories (for example IPC locking).
      *
      * @configurationSource {@link 
RepositorySystemSession#getConfigProperties()}
      * @configurationType {@link java.lang.String}
@@ -65,8 +66,8 @@ public class NamedLockFactoryAdapterFactoryImpl implements 
NamedLockFactoryAdapt
     public static final String CONFIG_PROP_FACTORY_KEY = 
NamedLockFactoryAdapter.CONFIG_PROPS_PREFIX + "factory";
 
     /**
-     * Name of the name mapper to use in session. Out of the box supported 
ones are "static", "gav", "file-gav",
-     * "file-hgav", "file-static" and "discriminating".
+     * Name of the name mapper to use in session. Out of the box supported 
ones are "static", "gav", "gaecv", "file-gav",
+     * "file-gaecv", "file-hgav", "file-hgaecv", "file-static" and 
"discriminating".
      *
      * @configurationSource {@link 
RepositorySystemSession#getConfigProperties()}
      * @configurationType {@link java.lang.String}
diff --git 
a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/synccontext/FileLockAdapterTest.java
 
b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/named/providers/FileGAECVNameMapperProvider.java
similarity index 53%
copy from 
maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/synccontext/FileLockAdapterTest.java
copy to 
maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/named/providers/FileGAECVNameMapperProvider.java
index e259b282a..d24fd77af 100644
--- 
a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/synccontext/FileLockAdapterTest.java
+++ 
b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/named/providers/FileGAECVNameMapperProvider.java
@@ -16,18 +16,31 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.eclipse.aether.internal.impl.synccontext;
+package org.eclipse.aether.internal.impl.synccontext.named.providers;
 
-import org.eclipse.aether.internal.impl.synccontext.named.BasedirNameMapper;
-import org.eclipse.aether.internal.impl.synccontext.named.GAVNameMapper;
-import org.eclipse.aether.named.providers.FileLockNamedLockFactory;
-import org.junit.jupiter.api.BeforeAll;
+import javax.inject.Named;
+import javax.inject.Provider;
+import javax.inject.Singleton;
 
-public class FileLockAdapterTest extends NamedLockFactoryAdapterTestSupport {
-    @BeforeAll
-    static void createNamedLockFactory() {
-        nameMapper = new BasedirNameMapper(GAVNameMapper.fileGav());
-        namedLockFactory = new FileLockNamedLockFactory();
-        createAdapter();
+import org.eclipse.aether.internal.impl.synccontext.named.NameMapper;
+import org.eclipse.aether.internal.impl.synccontext.named.NameMappers;
+
+/**
+ * The "file-gaecv" name mapper provider.
+ *
+ * @since 1.9.25
+ */
+@Singleton
+@Named(NameMappers.FILE_GAECV_NAME)
+public class FileGAECVNameMapperProvider implements Provider<NameMapper> {
+    private final NameMapper mapper;
+
+    public FileGAECVNameMapperProvider() {
+        this.mapper = NameMappers.fileGaecvNameMapper();
+    }
+
+    @Override
+    public NameMapper get() {
+        return mapper;
     }
 }
diff --git 
a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/synccontext/FileLockAdapterTest.java
 
b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/named/providers/FileHashingGAECVNameMapperProvider.java
similarity index 52%
copy from 
maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/synccontext/FileLockAdapterTest.java
copy to 
maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/named/providers/FileHashingGAECVNameMapperProvider.java
index e259b282a..81f6648dc 100644
--- 
a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/synccontext/FileLockAdapterTest.java
+++ 
b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/named/providers/FileHashingGAECVNameMapperProvider.java
@@ -16,18 +16,31 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.eclipse.aether.internal.impl.synccontext;
+package org.eclipse.aether.internal.impl.synccontext.named.providers;
 
-import org.eclipse.aether.internal.impl.synccontext.named.BasedirNameMapper;
-import org.eclipse.aether.internal.impl.synccontext.named.GAVNameMapper;
-import org.eclipse.aether.named.providers.FileLockNamedLockFactory;
-import org.junit.jupiter.api.BeforeAll;
+import javax.inject.Named;
+import javax.inject.Provider;
+import javax.inject.Singleton;
 
-public class FileLockAdapterTest extends NamedLockFactoryAdapterTestSupport {
-    @BeforeAll
-    static void createNamedLockFactory() {
-        nameMapper = new BasedirNameMapper(GAVNameMapper.fileGav());
-        namedLockFactory = new FileLockNamedLockFactory();
-        createAdapter();
+import org.eclipse.aether.internal.impl.synccontext.named.NameMapper;
+import org.eclipse.aether.internal.impl.synccontext.named.NameMappers;
+
+/**
+ * The "file-hgaecv" name mapper provider.
+ *
+ * @since 1.9.25
+ */
+@Singleton
+@Named(NameMappers.FILE_HGAECV_NAME)
+public class FileHashingGAECVNameMapperProvider implements 
Provider<NameMapper> {
+    private final NameMapper mapper;
+
+    public FileHashingGAECVNameMapperProvider() {
+        this.mapper = NameMappers.fileHashingGaecvNameMapper();
+    }
+
+    @Override
+    public NameMapper get() {
+        return mapper;
     }
 }
diff --git 
a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/synccontext/FileLockAdapterTest.java
 
b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/named/providers/GAECVNameMapperProvider.java
similarity index 54%
copy from 
maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/synccontext/FileLockAdapterTest.java
copy to 
maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/named/providers/GAECVNameMapperProvider.java
index e259b282a..aadec8609 100644
--- 
a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/synccontext/FileLockAdapterTest.java
+++ 
b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/named/providers/GAECVNameMapperProvider.java
@@ -16,18 +16,31 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.eclipse.aether.internal.impl.synccontext;
+package org.eclipse.aether.internal.impl.synccontext.named.providers;
 
-import org.eclipse.aether.internal.impl.synccontext.named.BasedirNameMapper;
-import org.eclipse.aether.internal.impl.synccontext.named.GAVNameMapper;
-import org.eclipse.aether.named.providers.FileLockNamedLockFactory;
-import org.junit.jupiter.api.BeforeAll;
+import javax.inject.Named;
+import javax.inject.Provider;
+import javax.inject.Singleton;
 
-public class FileLockAdapterTest extends NamedLockFactoryAdapterTestSupport {
-    @BeforeAll
-    static void createNamedLockFactory() {
-        nameMapper = new BasedirNameMapper(GAVNameMapper.fileGav());
-        namedLockFactory = new FileLockNamedLockFactory();
-        createAdapter();
+import org.eclipse.aether.internal.impl.synccontext.named.NameMapper;
+import org.eclipse.aether.internal.impl.synccontext.named.NameMappers;
+
+/**
+ * The "gaecv" name mapper provider.
+ *
+ * @since 1.9.25
+ */
+@Singleton
+@Named(NameMappers.GAECV_NAME)
+public class GAECVNameMapperProvider implements Provider<NameMapper> {
+    private final NameMapper mapper;
+
+    public GAECVNameMapperProvider() {
+        this.mapper = NameMappers.gaecvNameMapper();
+    }
+
+    @Override
+    public NameMapper get() {
+        return mapper;
     }
 }
diff --git a/maven-resolver-impl/src/site/markdown/synccontextfactory.md.vm 
b/maven-resolver-impl/src/site/markdown/synccontextfactory.md.vm
index c970fa15e..67755b417 100644
--- a/maven-resolver-impl/src/site/markdown/synccontextfactory.md.vm
+++ b/maven-resolver-impl/src/site/markdown/synccontextfactory.md.vm
@@ -61,10 +61,13 @@ For the `aether.syncContext.named.factory` property 
following values are allowed
 
 For the `aether.syncContext.named.nameMapper` property following values are 
allowed:
 
-- `discriminating` (default), uses hostname + local repo + GAV to create 
unique lock names for artifacts.
+- `discriminating`, uses hostname + local repo + GAV to create unique lock 
names for artifacts.
 - `gav` uses GAV to create unique lock names for artifacts and metadata. Is 
not unique if multiple local repositories are involved.
 - `file-gav` uses GAV and session to create absolute file paths (to be used 
with `file-lock` factory)
 - `file-hgav` uses more compact layout than `file-gav` by SHA-1 digest, 
similar to git (to be used with `file-lock` factory)
+- `gaecv` (default) uses GAECV to create unique lock names for artifacts and 
metadata. Is not unique if multiple local repositories are involved.
+- `file-gaecv` uses GAECV and session to create absolute file paths (to be 
used with `file-lock` factory)
+- `file-hgaecv` uses more compact layout than `file-gaecv` by SHA-1 digest, 
similar to git (to be used with `file-lock` factory)
 - `static` uses static (same) string as lock name for any input. Effectively 
providing functionality same as old
   "global" locking SyncContextFactory. Mostly for testing/experimental 
purposes.
 - `file-static` same as `static` but to be used with `file-lock` factory. 
Mostly for testing/experimental purposes.
diff --git 
a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/synccontext/FileLockAdapterTest.java
 
b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/synccontext/FileLockAdapterTest.java
index e259b282a..9a7820071 100644
--- 
a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/synccontext/FileLockAdapterTest.java
+++ 
b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/synccontext/FileLockAdapterTest.java
@@ -18,15 +18,14 @@
  */
 package org.eclipse.aether.internal.impl.synccontext;
 
-import org.eclipse.aether.internal.impl.synccontext.named.BasedirNameMapper;
-import org.eclipse.aether.internal.impl.synccontext.named.GAVNameMapper;
+import org.eclipse.aether.internal.impl.synccontext.named.NameMappers;
 import org.eclipse.aether.named.providers.FileLockNamedLockFactory;
 import org.junit.jupiter.api.BeforeAll;
 
 public class FileLockAdapterTest extends NamedLockFactoryAdapterTestSupport {
     @BeforeAll
     static void createNamedLockFactory() {
-        nameMapper = new BasedirNameMapper(GAVNameMapper.fileGav());
+        nameMapper = NameMappers.fileGavNameMapper();
         namedLockFactory = new FileLockNamedLockFactory();
         createAdapter();
     }
diff --git 
a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/synccontext/NamedLockFactoryAdapterTestSupport.java
 
b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/synccontext/NamedLockFactoryAdapterTestSupport.java
index 99cb84658..b1c0e05d1 100644
--- 
a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/synccontext/NamedLockFactoryAdapterTestSupport.java
+++ 
b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/synccontext/NamedLockFactoryAdapterTestSupport.java
@@ -29,7 +29,9 @@ import java.util.concurrent.TimeUnit;
 import org.eclipse.aether.RepositorySystemSession;
 import org.eclipse.aether.SyncContext;
 import org.eclipse.aether.artifact.DefaultArtifact;
-import org.eclipse.aether.internal.impl.synccontext.named.*;
+import org.eclipse.aether.internal.impl.synccontext.named.NameMapper;
+import org.eclipse.aether.internal.impl.synccontext.named.NameMappers;
+import 
org.eclipse.aether.internal.impl.synccontext.named.NamedLockFactoryAdapter;
 import org.eclipse.aether.named.NamedLockFactory;
 import org.eclipse.aether.named.support.LockUpgradeNotSupportedException;
 import org.eclipse.aether.repository.LocalRepository;
@@ -55,7 +57,7 @@ public abstract class NamedLockFactoryAdapterTestSupport {
     /**
      * Subclass MAY populate this field but subclass must take care of proper 
cleanup as well, if needed!
      */
-    protected static NameMapper nameMapper = new 
DiscriminatingNameMapper(GAVNameMapper.gav());
+    protected static NameMapper nameMapper = 
NameMappers.discriminatingNameMapper();
 
     /**
      * Subclass MUST populate this field but subclass must take care of proper 
cleanup as well, if needed! Once set,
diff --git 
a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/synccontext/named/BasedirHashingNameMapperTest.java
 
b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/synccontext/named/BasedirHashingNameMapperTest.java
index 226cc0f36..ffd445957 100644
--- 
a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/synccontext/named/BasedirHashingNameMapperTest.java
+++ 
b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/synccontext/named/BasedirHashingNameMapperTest.java
@@ -37,7 +37,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 public class BasedirHashingNameMapperTest extends NameMapperTestSupport {
     private final String PS = "/"; // we work with URIs now, not OS file paths
 
-    BasedirNameMapper mapper = new BasedirNameMapper(new 
HashingNameMapper(GAVNameMapper.gav()));
+    NameMapper mapper = NameMappers.fileHashingGavNameMapper();
 
     @Test
     void nullsAndEmptyInputs() {
diff --git 
a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/synccontext/named/BasedirNameMapperTest.java
 
b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/synccontext/named/BasedirNameMapperTest.java
index e322ccf14..e725b1df5 100644
--- 
a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/synccontext/named/BasedirNameMapperTest.java
+++ 
b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/synccontext/named/BasedirNameMapperTest.java
@@ -36,7 +36,7 @@ import static java.util.Collections.singletonList;
 import static org.junit.jupiter.api.Assertions.*;
 
 public class BasedirNameMapperTest extends NameMapperTestSupport {
-    private final BasedirNameMapper mapper = new 
BasedirNameMapper(GAVNameMapper.fileGav());
+    private final NameMapper mapper = NameMappers.fileGavNameMapper();
 
     private String getPrefix() throws IOException {
         Path basedir = DirectoryUtils.resolveDirectory(
diff --git 
a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/synccontext/named/GAVNameMapperTest.java
 
b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/synccontext/named/GAVNameMapperTest.java
index 308828766..6e6841666 100644
--- 
a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/synccontext/named/GAVNameMapperTest.java
+++ 
b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/synccontext/named/GAVNameMapperTest.java
@@ -33,7 +33,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
 public class GAVNameMapperTest extends NameMapperTestSupport {
-    NameMapper mapper = GAVNameMapper.fileGav();
+    NameMapper mapper = NameMappers.gavNameMapper(true);
 
     @Test
     void nullsAndEmptyInputs() {
diff --git 
a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/synccontext/named/HashingNameMapperTest.java
 
b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/synccontext/named/HashingNameMapperTest.java
index 6035ed843..c42ee397f 100644
--- 
a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/synccontext/named/HashingNameMapperTest.java
+++ 
b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/synccontext/named/HashingNameMapperTest.java
@@ -32,7 +32,7 @@ import static java.util.Collections.singletonList;
 import static org.junit.jupiter.api.Assertions.*;
 
 public class HashingNameMapperTest extends NameMapperTestSupport {
-    HashingNameMapper mapper = new HashingNameMapper(GAVNameMapper.gav());
+    HashingNameMapper mapper = new 
HashingNameMapper(NameMappers.gavNameMapper(false));
 
     @Test
     void nullsAndEmptyInputs() {
diff --git 
a/maven-resolver-named-locks-hazelcast/src/test/java/org/eclipse/aether/named/hazelcast/NamedLockFactoryAdapterTestSupport.java
 
b/maven-resolver-named-locks-hazelcast/src/test/java/org/eclipse/aether/named/hazelcast/NamedLockFactoryAdapterTestSupport.java
index 37a68f6fa..79eea69c5 100644
--- 
a/maven-resolver-named-locks-hazelcast/src/test/java/org/eclipse/aether/named/hazelcast/NamedLockFactoryAdapterTestSupport.java
+++ 
b/maven-resolver-named-locks-hazelcast/src/test/java/org/eclipse/aether/named/hazelcast/NamedLockFactoryAdapterTestSupport.java
@@ -29,8 +29,7 @@ import java.util.concurrent.TimeUnit;
 import org.eclipse.aether.RepositorySystemSession;
 import org.eclipse.aether.SyncContext;
 import org.eclipse.aether.artifact.DefaultArtifact;
-import 
org.eclipse.aether.internal.impl.synccontext.named.DiscriminatingNameMapper;
-import org.eclipse.aether.internal.impl.synccontext.named.GAVNameMapper;
+import org.eclipse.aether.internal.impl.synccontext.named.NameMappers;
 import 
org.eclipse.aether.internal.impl.synccontext.named.NamedLockFactoryAdapter;
 import org.eclipse.aether.named.NamedLockFactory;
 import org.eclipse.aether.named.support.LockUpgradeNotSupportedException;
@@ -64,7 +63,7 @@ public abstract class NamedLockFactoryAdapterTestSupport {
     private RepositorySystemSession session;
 
     protected static void setNamedLockFactory(final NamedLockFactory 
namedLockFactory) {
-        adapter = new NamedLockFactoryAdapter(new 
DiscriminatingNameMapper(GAVNameMapper.gav()), namedLockFactory);
+        adapter = new 
NamedLockFactoryAdapter(NameMappers.discriminatingNameMapper(), 
namedLockFactory);
     }
 
     @AfterAll
diff --git 
a/maven-resolver-named-locks-ipc/src/test/java/org/eclipse/aether/named/ipc/NamedLockFactoryAdapterTestSupport.java
 
b/maven-resolver-named-locks-ipc/src/test/java/org/eclipse/aether/named/ipc/NamedLockFactoryAdapterTestSupport.java
index d5212f612..f012ee4da 100644
--- 
a/maven-resolver-named-locks-ipc/src/test/java/org/eclipse/aether/named/ipc/NamedLockFactoryAdapterTestSupport.java
+++ 
b/maven-resolver-named-locks-ipc/src/test/java/org/eclipse/aether/named/ipc/NamedLockFactoryAdapterTestSupport.java
@@ -29,8 +29,7 @@ import java.util.concurrent.TimeUnit;
 import org.eclipse.aether.RepositorySystemSession;
 import org.eclipse.aether.SyncContext;
 import org.eclipse.aether.artifact.DefaultArtifact;
-import 
org.eclipse.aether.internal.impl.synccontext.named.DiscriminatingNameMapper;
-import org.eclipse.aether.internal.impl.synccontext.named.GAVNameMapper;
+import org.eclipse.aether.internal.impl.synccontext.named.NameMappers;
 import 
org.eclipse.aether.internal.impl.synccontext.named.NamedLockFactoryAdapter;
 import org.eclipse.aether.named.NamedLockFactory;
 import org.eclipse.aether.named.support.LockUpgradeNotSupportedException;
@@ -59,7 +58,7 @@ public abstract class NamedLockFactoryAdapterTestSupport {
     private RepositorySystemSession session;
 
     protected static void setNamedLockFactory(final NamedLockFactory 
namedLockFactory) {
-        adapter = new NamedLockFactoryAdapter(new 
DiscriminatingNameMapper(GAVNameMapper.gav()), namedLockFactory);
+        adapter = new 
NamedLockFactoryAdapter(NameMappers.discriminatingNameMapper(), 
namedLockFactory);
     }
 
     @AfterAll
diff --git 
a/maven-resolver-named-locks-redisson/src/test/java/org/eclipse/aether/named/redisson/NamedLockFactoryAdapterTestSupport.java
 
b/maven-resolver-named-locks-redisson/src/test/java/org/eclipse/aether/named/redisson/NamedLockFactoryAdapterTestSupport.java
index d87fb231e..fc8cd35df 100644
--- 
a/maven-resolver-named-locks-redisson/src/test/java/org/eclipse/aether/named/redisson/NamedLockFactoryAdapterTestSupport.java
+++ 
b/maven-resolver-named-locks-redisson/src/test/java/org/eclipse/aether/named/redisson/NamedLockFactoryAdapterTestSupport.java
@@ -30,8 +30,7 @@ import com.redis.testcontainers.RedisContainer;
 import org.eclipse.aether.RepositorySystemSession;
 import org.eclipse.aether.SyncContext;
 import org.eclipse.aether.artifact.DefaultArtifact;
-import 
org.eclipse.aether.internal.impl.synccontext.named.DiscriminatingNameMapper;
-import org.eclipse.aether.internal.impl.synccontext.named.GAVNameMapper;
+import org.eclipse.aether.internal.impl.synccontext.named.NameMappers;
 import 
org.eclipse.aether.internal.impl.synccontext.named.NamedLockFactoryAdapter;
 import org.eclipse.aether.named.NamedLockFactory;
 import org.eclipse.aether.named.support.LockUpgradeNotSupportedException;
@@ -68,7 +67,7 @@ public abstract class NamedLockFactoryAdapterTestSupport {
     private RepositorySystemSession session;
 
     protected static void setNamedLockFactory(final NamedLockFactory 
namedLockFactory) {
-        adapter = new NamedLockFactoryAdapter(new 
DiscriminatingNameMapper(GAVNameMapper.gav()), namedLockFactory);
+        adapter = new 
NamedLockFactoryAdapter(NameMappers.discriminatingNameMapper(), 
namedLockFactory);
     }
 
     @AfterAll
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 13219cefe..c104ebc45 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
@@ -354,9 +354,12 @@ public class RepositorySystemSupplier implements 
Supplier<RepositorySystem> {
         HashMap<String, NameMapper> result = new HashMap<>();
         result.put(NameMappers.STATIC_NAME, NameMappers.staticNameMapper());
         result.put(NameMappers.GAV_NAME, NameMappers.gavNameMapper());
+        result.put(NameMappers.GAECV_NAME, NameMappers.gaecvNameMapper());
         result.put(NameMappers.DISCRIMINATING_NAME, 
NameMappers.discriminatingNameMapper());
         result.put(NameMappers.FILE_GAV_NAME, NameMappers.fileGavNameMapper());
+        result.put(NameMappers.FILE_GAECV_NAME, 
NameMappers.fileGaecvNameMapper());
         result.put(NameMappers.FILE_HGAV_NAME, 
NameMappers.fileHashingGavNameMapper());
+        result.put(NameMappers.FILE_HGAECV_NAME, 
NameMappers.fileHashingGaecvNameMapper());
         return result;
     }
 
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 e10661488..0fc19c0e9 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
@@ -358,9 +358,12 @@ public class RepositorySystemSupplier implements 
Supplier<RepositorySystem> {
         HashMap<String, NameMapper> result = new HashMap<>();
         result.put(NameMappers.STATIC_NAME, NameMappers.staticNameMapper());
         result.put(NameMappers.GAV_NAME, NameMappers.gavNameMapper());
+        result.put(NameMappers.GAECV_NAME, NameMappers.gaecvNameMapper());
         result.put(NameMappers.DISCRIMINATING_NAME, 
NameMappers.discriminatingNameMapper());
         result.put(NameMappers.FILE_GAV_NAME, NameMappers.fileGavNameMapper());
+        result.put(NameMappers.FILE_GAECV_NAME, 
NameMappers.fileGaecvNameMapper());
         result.put(NameMappers.FILE_HGAV_NAME, 
NameMappers.fileHashingGavNameMapper());
+        result.put(NameMappers.FILE_HGAECV_NAME, 
NameMappers.fileHashingGaecvNameMapper());
         return result;
     }
 
diff --git a/src/site/markdown/configuration.md 
b/src/site/markdown/configuration.md
index b9ad76bb2..4735a16ed 100644
--- a/src/site/markdown/configuration.md
+++ b/src/site/markdown/configuration.md
@@ -111,9 +111,9 @@ To modify this file, edit the template and regenerate.
 | `"aether.syncContext.named.basedir.locksDir"` | `String` | The location of 
the directory toi use for locks. If relative path, it is resolved from the 
local repository root. |  `".locks"`  | 1.9.0 |  No  | Session Configuration |
 | `"aether.syncContext.named.discriminating.discriminator"` | `String` | 
Configuration property to pass in discriminator, if needed. If not present, it 
is auto-calculated. |  -  | 1.7.0 |  No  | Session Configuration |
 | `"aether.syncContext.named.discriminating.hostname"` | `String` | 
Configuration property to pass in hostname, if needed. If not present, hostname 
as reported by system will be used. |  -  | 1.7.0 |  No  | Session 
Configuration |
-| `"aether.syncContext.named.factory"` | `String` | Name of the lock factory 
to use in session. |  `"file-lock"`  | 1.9.1 |  No  | Session Configuration |
+| `"aether.syncContext.named.factory"` | `String` | Name of the lock factory 
to use in session. Out of the box supported ones are "file-lock", 
"rwlock-local", "semaphore-local", "noop". By adding extensions one can extend 
available lock factories (for example IPC locking). |  `"file-lock"`  | 1.9.1 | 
 No  | Session Configuration |
 | `"aether.syncContext.named.hashing.depth"` | `Integer` | The depth how many 
levels should adapter create. Acceptable values are 0-4 (inclusive). |  `2`  | 
1.9.0 |  No  | Session Configuration |
-| `"aether.syncContext.named.nameMapper"` | `String` | Name of the name mapper 
to use in session. Out of the box supported ones are "static", "gav", 
"file-gav", "file-hgav", "file-static" and "discriminating". |  `"file-gav"`  | 
1.9.1 |  No  | Session Configuration |
+| `"aether.syncContext.named.nameMapper"` | `String` | Name of the name mapper 
to use in session. Out of the box supported ones are "static", "gav", "gaecv", 
"file-gav", "file-gaecv", "file-hgav", "file-hgaecv", "file-static" and 
"discriminating". |  `"file-gaecv"`  | 1.9.1 |  No  | Session Configuration |
 | `"aether.syncContext.named.redisson.address"` | `String` | Address of the 
Redis instance. Optional. |  `"redis://localhost:6379"`  | 2.0.0 |  No  | Java 
System Properties |
 | `"aether.syncContext.named.redisson.configFile"` | `String` | Path to a 
Redisson configuration file in YAML format. Read official documentation for 
details. |  -  | 1.7.0 |  No  | Java System Properties |
 | `"aether.syncContext.named.retry"` | `Integer` | The amount of retries on 
time-out. |  `1`  | 1.7.0 |  No  | Session Configuration |


Reply via email to