From 1dbb1833f0b4d2f534328700cbf5d8fa6dd03e1c Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Tue, 18 Nov 2025 20:39:18 +0100 Subject: [PATCH 1/4] Name mappers cleanup and new GAECV mapper Cleanup name mappers usage and introduce new, more selective mapper GAECV. Changes: * introduce GAECV next to existing GAV name mapper. * make default GAECV --- .../synccontext/named/GAECVNameMapper.java | 66 +++++++++++++++++ .../impl/synccontext/named/GAVNameMapper.java | 29 +++++--- .../impl/synccontext/named/NameMappers.java | 71 +++++++++++++++++-- .../NamedLockFactoryAdapterFactoryImpl.java | 6 +- .../FileGAECVNameMapperProvider.java | 46 ++++++++++++ .../FileHashingGAECVNameMapperProvider.java | 46 ++++++++++++ .../providers/GAECVNameMapperProvider.java | 46 ++++++++++++ .../site/markdown/synccontextfactory.md.vm | 5 +- .../impl/synccontext/FileLockAdapterTest.java | 5 +- .../NamedLockFactoryAdapterTestSupport.java | 6 +- .../named/BasedirNameMapperTest.java | 2 +- .../synccontext/named/GAVNameMapperTest.java | 2 +- .../named/HashingNameMapperTest.java | 2 +- .../NamedLockFactoryAdapterTestSupport.java | 5 +- .../supplier/RepositorySystemSupplier.java | 3 + .../supplier/RepositorySystemSupplier.java | 3 + src/site/markdown/configuration.md | 2 +- 17 files changed, 315 insertions(+), 30 deletions(-) create mode 100644 maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/named/GAECVNameMapper.java create mode 100644 maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/named/providers/FileGAECVNameMapperProvider.java create mode 100644 maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/named/providers/FileHashingGAECVNameMapperProvider.java create mode 100644 maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/named/providers/GAECVNameMapperProvider.java 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..a36b2aab3 --- /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, String prefix, String separator, String suffix) { + if (artifact.getClassifier().isEmpty()) { + return prefix + + artifact.getGroupId() + + separator + + artifact.getArtifactId() + + separator + + artifact.getExtension() + + separator + + artifact.getBaseVersion() + + suffix; + } else { + return prefix + + artifact.getGroupId() + + separator + + artifact.getArtifactId() + + separator + + artifact.getExtension() + + separator + + artifact.getClassifier() + + separator + + artifact.getBaseVersion() + + suffix; + } + } +} 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 dc21b4438..05571d917 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 @@ -34,19 +34,22 @@ * 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). + *

+ * 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, @@ -94,7 +97,7 @@ public Collection nameLocks( return keys; } - private static String getArtifactName(Artifact artifact, String prefix, String separator, String suffix) { + protected String getArtifactName(Artifact artifact, String prefix, String separator, String suffix) { return prefix + artifact.getGroupId() + separator @@ -104,9 +107,9 @@ private static String getArtifactName(Artifact artifact, String prefix, String s + suffix; } - private static final String MAVEN_METADATA = "maven-metadata.xml"; + protected static final String MAVEN_METADATA = "maven-metadata.xml"; - private static String getMetadataName(Metadata metadata, String prefix, String separator, String suffix) { + protected String getMetadataName(Metadata metadata, String prefix, String separator, String suffix) { String name = prefix; if (!metadata.getGroupId().isEmpty()) { name += metadata.getGroupId(); @@ -127,10 +130,18 @@ private static String getMetadataName(Metadata metadata, String prefix, String s return name + suffix; } + /** + * @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 @@ /** * 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 static NameMapper staticNameMapper() { } 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 static NameMapper fileStaticNameMapper() { } 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..d939ca1c5 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,7 +53,7 @@ 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. @@ -65,8 +65,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/main/java/org/eclipse/aether/internal/impl/synccontext/named/providers/FileGAECVNameMapperProvider.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/named/providers/FileGAECVNameMapperProvider.java new file mode 100644 index 000000000..d24fd77af --- /dev/null +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/named/providers/FileGAECVNameMapperProvider.java @@ -0,0 +1,46 @@ +/* + * 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.providers; + +import javax.inject.Named; +import javax.inject.Provider; +import javax.inject.Singleton; + +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 { + private final NameMapper mapper; + + public FileGAECVNameMapperProvider() { + this.mapper = NameMappers.fileGaecvNameMapper(); + } + + @Override + public NameMapper get() { + return mapper; + } +} diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/named/providers/FileHashingGAECVNameMapperProvider.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/named/providers/FileHashingGAECVNameMapperProvider.java new file mode 100644 index 000000000..81f6648dc --- /dev/null +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/named/providers/FileHashingGAECVNameMapperProvider.java @@ -0,0 +1,46 @@ +/* + * 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.providers; + +import javax.inject.Named; +import javax.inject.Provider; +import javax.inject.Singleton; + +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 { + private final NameMapper mapper; + + public FileHashingGAECVNameMapperProvider() { + this.mapper = NameMappers.fileHashingGaecvNameMapper(); + } + + @Override + public NameMapper get() { + return mapper; + } +} diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/named/providers/GAECVNameMapperProvider.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/named/providers/GAECVNameMapperProvider.java new file mode 100644 index 000000000..aadec8609 --- /dev/null +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/named/providers/GAECVNameMapperProvider.java @@ -0,0 +1,46 @@ +/* + * 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.providers; + +import javax.inject.Named; +import javax.inject.Provider; +import javax.inject.Singleton; + +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 { + 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 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/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 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.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 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 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-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 @@ protected Map createNameMappers() { HashMap 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 @@ protected Map createNameMappers() { HashMap 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 e30b9316e..5361dceff 100644 --- a/src/site/markdown/configuration.md +++ b/src/site/markdown/configuration.md @@ -109,7 +109,7 @@ To modify this file, edit the template and regenerate. | `"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.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", "file-gav", "file-hgav", "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 | From aec6452f9847c5d91e3c8922892fec588d20eec2 Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Tue, 18 Nov 2025 20:45:42 +0100 Subject: [PATCH 2/4] Update doco and javadoc --- .../synccontext/named/NamedLockFactoryAdapterFactoryImpl.java | 3 ++- src/site/markdown/configuration.md | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) 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 d939ca1c5..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 @@ -56,7 +56,8 @@ public class NamedLockFactoryAdapterFactoryImpl implements NamedLockFactoryAdapt 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} diff --git a/src/site/markdown/configuration.md b/src/site/markdown/configuration.md index 5361dceff..0ff4718d0 100644 --- a/src/site/markdown/configuration.md +++ b/src/site/markdown/configuration.md @@ -107,9 +107,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-gaecv"` | 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 | From f66894310ecde55b8f6023e30141047cf4a1a59d Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Tue, 18 Nov 2025 20:50:51 +0100 Subject: [PATCH 3/4] More cleanup --- .../impl/synccontext/named/BasedirHashingNameMapperTest.java | 2 +- .../aether/named/ipc/NamedLockFactoryAdapterTestSupport.java | 5 ++--- .../named/redisson/NamedLockFactoryAdapterTestSupport.java | 5 ++--- 3 files changed, 5 insertions(+), 7 deletions(-) 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 feea3b1ea..23404b519 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 @@ 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-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 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 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 From 09671e7ac4d168277f34834fb47584534e80149f Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Thu, 20 Nov 2025 16:37:09 +0100 Subject: [PATCH 4/4] Cleanup --- .../synccontext/named/GAECVNameMapper.java | 24 ++++----- .../impl/synccontext/named/GAVNameMapper.java | 49 ++++++++++++------- 2 files changed, 43 insertions(+), 30 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 index a36b2aab3..3d5344beb 100644 --- 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 @@ -38,29 +38,29 @@ public GAECVNameMapper( } @Override - protected String getArtifactName(Artifact artifact, String prefix, String separator, String suffix) { + protected String getArtifactName(Artifact artifact) { if (artifact.getClassifier().isEmpty()) { - return prefix + return artifactPrefix + artifact.getGroupId() - + separator + + fieldSeparator + artifact.getArtifactId() - + separator + + fieldSeparator + artifact.getExtension() - + separator + + fieldSeparator + artifact.getBaseVersion() - + suffix; + + artifactSuffix; } else { - return prefix + return artifactPrefix + artifact.getGroupId() - + separator + + fieldSeparator + artifact.getArtifactId() - + separator + + fieldSeparator + artifact.getExtension() - + separator + + fieldSeparator + artifact.getClassifier() - + separator + + fieldSeparator + artifact.getBaseVersion() - + suffix; + + 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 7609818d9..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.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; @@ -81,47 +82,42 @@ public Collection nameLocks( TreeSet 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; } - protected 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; } protected static final String MAVEN_METADATA = "maven-metadata.xml"; - protected 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 { @@ -129,7 +125,24 @@ protected String getMetadataName( 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; } /**