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 70696c0b5 Better checksum control (#1784)
70696c0b5 is described below
commit 70696c0b5f2b4e74a1a910459dd94e1a6715303b
Author: Tamas Cservenak <[email protected]>
AuthorDate: Wed Feb 4 13:03:44 2026 +0100
Better checksum control (#1784)
Ability to explicitly configure checksums for download (used to validate
during donwloads) and for uploads (generated during uploads).
Fixes #1782
---
.../connector/basic/BasicRepositoryConnector.java | 2 +-
.../impl/Maven2RepositoryLayoutFactory.java | 113 +++++++++++++++++----
.../impl/Maven2RepositoryLayoutFactoryTest.java | 48 ++++++++-
.../checksum/ChecksumAlgorithmFactorySelector.java | 2 +-
.../spi/connector/layout/RepositoryLayout.java | 22 +++-
5 files changed, 161 insertions(+), 26 deletions(-)
diff --git
a/maven-resolver-connector-basic/src/main/java/org/eclipse/aether/connector/basic/BasicRepositoryConnector.java
b/maven-resolver-connector-basic/src/main/java/org/eclipse/aether/connector/basic/BasicRepositoryConnector.java
index fd2d51e93..3d4d748fa 100644
---
a/maven-resolver-connector-basic/src/main/java/org/eclipse/aether/connector/basic/BasicRepositoryConnector.java
+++
b/maven-resolver-connector-basic/src/main/java/org/eclipse/aether/connector/basic/BasicRepositoryConnector.java
@@ -215,7 +215,7 @@ final class BasicRepositoryConnector implements
RepositoryConnector {
SmartExecutor executor = getExecutor(true,
safeArtifactDownloads.size() + safeMetadataDownloads.size());
RunnableErrorForwarder errorForwarder = new RunnableErrorForwarder();
- List<ChecksumAlgorithmFactory> checksumAlgorithmFactories =
layout.getChecksumAlgorithmFactories();
+ List<ChecksumAlgorithmFactory> checksumAlgorithmFactories =
layout.getChecksumAlgorithmFactories(false);
boolean first = true;
diff --git
a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/Maven2RepositoryLayoutFactory.java
b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/Maven2RepositoryLayoutFactory.java
index c89ca5ffe..fdfc0c5ba 100644
---
a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/Maven2RepositoryLayoutFactory.java
+++
b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/Maven2RepositoryLayoutFactory.java
@@ -26,6 +26,7 @@ import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.LinkedHashMap;
import java.util.List;
import org.eclipse.aether.ConfigurationProperties;
@@ -57,7 +58,9 @@ public final class Maven2RepositoryLayoutFactory implements
RepositoryLayoutFact
/**
* Comma-separated list of checksum algorithms with which checksums are
validated (downloaded) and generated
* (uploaded) with this layout. Resolver by default supports following
algorithms: MD5, SHA-1, SHA-256 and
- * SHA-512. New algorithms can be added by implementing
ChecksumAlgorithmFactory component.
+ * SHA-512. New algorithms can be added by implementing
ChecksumAlgorithmFactory component. To configure separately
+ * checksums for download or upload, use {@link
#CONFIG_PROP_DOWNLOAD_CHECKSUMS_ALGORITHMS} and
+ * {@link #CONFIG_PROP_UPLOAD_CHECKSUMS_ALGORITHMS} respectively.
*
* @since 1.8.0
* @configurationSource {@link
RepositorySystemSession#getConfigProperties()}
@@ -69,6 +72,38 @@ public final class Maven2RepositoryLayoutFactory implements
RepositoryLayoutFact
public static final String DEFAULT_CHECKSUMS_ALGORITHMS = "SHA-1,MD5";
+ /**
+ * Comma-separated list of checksum algorithms with which checksums are
generated and uploaded
+ * with this layout. Resolver by default supports following algorithms:
MD5, SHA-1, SHA-256 and
+ * SHA-512. New algorithms can be added by implementing
ChecksumAlgorithmFactory component.
+ * If this property is set, it <em>overrides</em> the value set in {@link
#CONFIG_PROP_CHECKSUMS_ALGORITHMS} for
+ * uploads.
+ *
+ * @since 2.0.15
+ * @configurationSource {@link
RepositorySystemSession#getConfigProperties()}
+ * @configurationType {@link java.lang.String}
+ * @configurationDefaultValue {@link #DEFAULT_CHECKSUMS_ALGORITHMS}
+ * @configurationRepoIdSuffix Yes
+ */
+ public static final String CONFIG_PROP_UPLOAD_CHECKSUMS_ALGORITHMS =
+ CONFIG_PROPS_PREFIX + "uploadChecksumAlgorithms";
+
+ /**
+ * Comma-separated list of checksum algorithms with which checksums are
validated (downloaded) with this layout.
+ * Resolver by default supports following algorithms: MD5, SHA-1, SHA-256
and SHA-512.
+ * New algorithms can be added by implementing ChecksumAlgorithmFactory
component.
+ * If this property is set, it <em>overrides</em> the value set in {@link
#CONFIG_PROP_CHECKSUMS_ALGORITHMS} for
+ * downloads.
+ *
+ * @since 2.0.15
+ * @configurationSource {@link
RepositorySystemSession#getConfigProperties()}
+ * @configurationType {@link java.lang.String}
+ * @configurationDefaultValue {@link #DEFAULT_CHECKSUMS_ALGORITHMS}
+ * @configurationRepoIdSuffix Yes
+ */
+ public static final String CONFIG_PROP_DOWNLOAD_CHECKSUMS_ALGORITHMS =
+ CONFIG_PROPS_PREFIX + "downloadChecksumAlgorithms";
+
private float priority;
private final ChecksumAlgorithmFactorySelector
checksumAlgorithmFactorySelector;
@@ -106,26 +141,48 @@ public final class Maven2RepositoryLayoutFactory
implements RepositoryLayoutFact
throw new NoRepositoryLayoutException(repository);
}
- List<ChecksumAlgorithmFactory> checksumsAlgorithms =
checksumAlgorithmFactorySelector.selectList(
-
ConfigUtils.parseCommaSeparatedUniqueNames(ConfigUtils.getString(
- session,
- DEFAULT_CHECKSUMS_ALGORITHMS,
- CONFIG_PROP_CHECKSUMS_ALGORITHMS + "." +
repository.getId(),
- CONFIG_PROP_CHECKSUMS_ALGORITHMS,
- // MRESOLVER-701: support legacy properties for
simpler transitioning
- "aether.checksums.algorithms",
- "aether.checksums.algorithms." + repository.getId())));
-
- return new Maven2RepositoryLayout(checksumsAlgorithms,
artifactPredicateFactory.newInstance(session));
+ // explicit property for download (will be empty if not configured)
+ List<String> downloadChecksumsAlgorithmNames =
ConfigUtils.parseCommaSeparatedUniqueNames(ConfigUtils.getString(
+ session,
+ DEFAULT_CHECKSUMS_ALGORITHMS,
+ CONFIG_PROP_DOWNLOAD_CHECKSUMS_ALGORITHMS + "." +
repository.getId(),
+ CONFIG_PROP_DOWNLOAD_CHECKSUMS_ALGORITHMS,
+ CONFIG_PROP_CHECKSUMS_ALGORITHMS + "." + repository.getId(),
+ CONFIG_PROP_CHECKSUMS_ALGORITHMS,
+ // MRESOLVER-701: support legacy properties for simpler
transitioning
+ "aether.checksums.algorithms." + repository.getId(),
+ "aether.checksums.algorithms"));
+
+ // explicit property for upload (will be empty if not configured)
+ List<String> uploadChecksumsAlgorithmNames =
ConfigUtils.parseCommaSeparatedUniqueNames(ConfigUtils.getString(
+ session,
+ DEFAULT_CHECKSUMS_ALGORITHMS,
+ CONFIG_PROP_UPLOAD_CHECKSUMS_ALGORITHMS + "." +
repository.getId(),
+ CONFIG_PROP_UPLOAD_CHECKSUMS_ALGORITHMS,
+ CONFIG_PROP_CHECKSUMS_ALGORITHMS + "." + repository.getId(),
+ CONFIG_PROP_CHECKSUMS_ALGORITHMS,
+ // MRESOLVER-701: support legacy properties for simpler
transitioning
+ "aether.checksums.algorithms." + repository.getId(),
+ "aether.checksums.algorithms"));
+
+ return new Maven2RepositoryLayout(
+
checksumAlgorithmFactorySelector.selectList(downloadChecksumsAlgorithmNames),
+
checksumAlgorithmFactorySelector.selectList(uploadChecksumsAlgorithmNames),
+ artifactPredicateFactory.newInstance(session));
}
private static class Maven2RepositoryLayout implements RepositoryLayout {
- private final List<ChecksumAlgorithmFactory>
configuredChecksumAlgorithms;
+ private final List<ChecksumAlgorithmFactory>
configuredDownloadChecksumAlgorithms;
+ private final List<ChecksumAlgorithmFactory>
configuredUploadChecksumAlgorithms;
private final ArtifactPredicate artifactPredicate;
private Maven2RepositoryLayout(
- List<ChecksumAlgorithmFactory> configuredChecksumAlgorithms,
ArtifactPredicate artifactPredicate) {
- this.configuredChecksumAlgorithms =
Collections.unmodifiableList(configuredChecksumAlgorithms);
+ List<ChecksumAlgorithmFactory>
configuredDownloadChecksumAlgorithms,
+ List<ChecksumAlgorithmFactory>
configuredUploadChecksumAlgorithms,
+ ArtifactPredicate artifactPredicate) {
+ this.configuredDownloadChecksumAlgorithms =
+
Collections.unmodifiableList(configuredDownloadChecksumAlgorithms);
+ this.configuredUploadChecksumAlgorithms =
Collections.unmodifiableList(configuredUploadChecksumAlgorithms);
this.artifactPredicate = requireNonNull(artifactPredicate);
}
@@ -139,7 +196,19 @@ public final class Maven2RepositoryLayoutFactory
implements RepositoryLayoutFact
@Override
public List<ChecksumAlgorithmFactory> getChecksumAlgorithmFactories() {
- return configuredChecksumAlgorithms;
+ LinkedHashMap<String, ChecksumAlgorithmFactory> factories = new
LinkedHashMap<>();
+ configuredDownloadChecksumAlgorithms.forEach(f ->
factories.putIfAbsent(f.getName(), f));
+ configuredUploadChecksumAlgorithms.forEach(f ->
factories.putIfAbsent(f.getName(), f));
+ return Collections.unmodifiableList(new
ArrayList<>(factories.values()));
+ }
+
+ @Override
+ public List<ChecksumAlgorithmFactory>
getChecksumAlgorithmFactories(boolean upload) {
+ if (upload) {
+ return configuredUploadChecksumAlgorithms;
+ } else {
+ return configuredDownloadChecksumAlgorithms;
+ }
}
@Override
@@ -196,17 +265,19 @@ public final class Maven2RepositoryLayoutFactory
implements RepositoryLayoutFact
if (artifactPredicate.isWithoutChecksum(artifact) ||
artifactPredicate.isChecksum(artifact)) {
return Collections.emptyList();
}
- return getChecksumLocations(location);
+ return getChecksumLocations(location, upload);
}
@Override
public List<ChecksumLocation> getChecksumLocations(Metadata metadata,
boolean upload, URI location) {
- return getChecksumLocations(location);
+ return getChecksumLocations(location, upload);
}
- private List<ChecksumLocation> getChecksumLocations(URI location) {
- List<ChecksumLocation> checksumLocations = new
ArrayList<>(configuredChecksumAlgorithms.size());
- for (ChecksumAlgorithmFactory checksumAlgorithmFactory :
configuredChecksumAlgorithms) {
+ private List<ChecksumLocation> getChecksumLocations(URI location,
boolean upload) {
+ List<ChecksumAlgorithmFactory> checksumAlgorithmFactories =
+ upload ? configuredUploadChecksumAlgorithms :
configuredDownloadChecksumAlgorithms;
+ List<ChecksumLocation> checksumLocations = new
ArrayList<>(checksumAlgorithmFactories.size());
+ for (ChecksumAlgorithmFactory checksumAlgorithmFactory :
checksumAlgorithmFactories) {
checksumLocations.add(ChecksumLocation.forLocation(location,
checksumAlgorithmFactory));
}
return checksumLocations;
diff --git
a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/Maven2RepositoryLayoutFactoryTest.java
b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/Maven2RepositoryLayoutFactoryTest.java
index d6bfed7e8..74f20426c 100644
---
a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/Maven2RepositoryLayoutFactoryTest.java
+++
b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/Maven2RepositoryLayoutFactoryTest.java
@@ -319,7 +319,7 @@ public class Maven2RepositoryLayoutFactoryTest {
}
@Test
- void testCustomChecksumsIgnored_IllegalInout() throws Exception {
+ void testCustomChecksumsIgnored_IllegalInput() throws Exception {
session.setConfigProperty(
DefaultArtifactPredicateFactory.CONFIG_PROP_OMIT_CHECKSUMS_FOR_EXTENSIONS,
".asc,foo");
try {
@@ -332,4 +332,50 @@ public class Maven2RepositoryLayoutFactoryTest {
message);
}
}
+
+ @Test
+ void testUploadDownloadChecksumsConfigured() throws Exception {
+ session.setConfigProperty(
+
Maven2RepositoryLayoutFactory.CONFIG_PROP_DOWNLOAD_CHECKSUMS_ALGORITHMS,
"SHA-256,SHA-1");
+
session.setConfigProperty(Maven2RepositoryLayoutFactory.CONFIG_PROP_UPLOAD_CHECKSUMS_ALGORITHMS,
"SHA-512,MD5");
+ layout = factory.newInstance(session, newRepo("default"));
+ // as configured
+ assertEquals(Arrays.asList("SHA-256", "SHA-1"),
toNames(layout.getChecksumAlgorithmFactories(false)));
+ // as configured
+ assertEquals(Arrays.asList("SHA-512", "MD5"),
toNames(layout.getChecksumAlgorithmFactories(true)));
+ // in order with download ones added first
+ assertEquals(
+ Arrays.asList("SHA-256", "SHA-1", "SHA-512", "MD5"),
toNames(layout.getChecksumAlgorithmFactories()));
+ }
+
+ @Test
+ void testDownloadChecksumsConfigured() throws Exception {
+ session.setConfigProperty(
+
Maven2RepositoryLayoutFactory.CONFIG_PROP_DOWNLOAD_CHECKSUMS_ALGORITHMS,
"SHA-256,SHA-1");
+ layout = factory.newInstance(session, newRepo("default"));
+ // as configured
+ assertEquals(Arrays.asList("SHA-256", "SHA-1"),
toNames(layout.getChecksumAlgorithmFactories(false)));
+ // defaults
+ assertEquals(Arrays.asList("SHA-1", "MD5"),
toNames(layout.getChecksumAlgorithmFactories(true)));
+ // in order with download ones added first
+ assertEquals(Arrays.asList("SHA-256", "SHA-1", "MD5"),
toNames(layout.getChecksumAlgorithmFactories()));
+ }
+
+ @Test
+ void testUploadChecksumsConfigured() throws Exception {
+ session.setConfigProperty(
+
Maven2RepositoryLayoutFactory.CONFIG_PROP_UPLOAD_CHECKSUMS_ALGORITHMS,
"SHA-512,SHA-256,SHA-1");
+ layout = factory.newInstance(session, newRepo("default"));
+ // defaults
+ assertEquals(Arrays.asList("SHA-1", "MD5"),
toNames(layout.getChecksumAlgorithmFactories(false)));
+ // as configured
+ assertEquals(Arrays.asList("SHA-512", "SHA-256", "SHA-1"),
toNames(layout.getChecksumAlgorithmFactories(true)));
+ // in order with download ones added first
+ assertEquals(
+ Arrays.asList("SHA-1", "MD5", "SHA-512", "SHA-256"),
toNames(layout.getChecksumAlgorithmFactories()));
+ }
+
+ private static List<String> toNames(List<ChecksumAlgorithmFactory>
factories) {
+ return
factories.stream().map(ChecksumAlgorithmFactory::getName).collect(Collectors.toList());
+ }
}
diff --git
a/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/connector/checksum/ChecksumAlgorithmFactorySelector.java
b/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/connector/checksum/ChecksumAlgorithmFactorySelector.java
index cc96ddabb..88f4b922a 100644
---
a/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/connector/checksum/ChecksumAlgorithmFactorySelector.java
+++
b/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/connector/checksum/ChecksumAlgorithmFactorySelector.java
@@ -52,7 +52,7 @@ public interface ChecksumAlgorithmFactorySelector {
/**
* Returns immutable collection of all supported algorithms. This set
represents ALL the algorithms supported by
* Resolver, and is NOT in any relation to given repository layout used
checksums, returned by method {@link
- *
org.eclipse.aether.spi.connector.layout.RepositoryLayout#getChecksumAlgorithmFactories()}
(in fact, is super set
+ *
org.eclipse.aether.spi.connector.layout.RepositoryLayout#getChecksumAlgorithmFactories(boolean)}
(in fact, is super set
* of it).
*/
Collection<ChecksumAlgorithmFactory> getChecksumAlgorithmFactories();
diff --git
a/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/connector/layout/RepositoryLayout.java
b/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/connector/layout/RepositoryLayout.java
index d0110e679..c503e832f 100644
---
a/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/connector/layout/RepositoryLayout.java
+++
b/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/connector/layout/RepositoryLayout.java
@@ -115,13 +115,31 @@ public interface RepositoryLayout {
/**
* Returns immutable list of {@link ChecksumAlgorithmFactory} this
instance of layout uses, never {@code null}.
- * The order also represents the order how remote external checksums are
retrieved and validated.
+ * This (legacy, but not deprecated) method will return <em>all checksums
this layout uses</em>, but
+ * these may be different in case upload or download checksums are
explicitly configured. This method will
+ * reflect the checksum order used for download, but may have more
elements than actually used in download
+ * validation, if the generated checksums for upload has extra elements.
*
* @see
org.eclipse.aether.spi.connector.checksum.ChecksumPolicy.ChecksumKind
+ * @see #getChecksumAlgorithmFactories(boolean)
* @since 1.8.0
*/
List<ChecksumAlgorithmFactory> getChecksumAlgorithmFactories();
+ /**
+ * Returns immutable list of {@link ChecksumAlgorithmFactory} this
instance of layout uses for download or upload,
+ * never {@code null}. The order also represents the order how remote
external checksums are retrieved and
+ * validated (if for download).
+ *
+ * @param upload {@code false} if the caller needs checksums used for
download validation, or {@code true} if the
+ * caller needs checksums generated for upload.
+ * @see
org.eclipse.aether.spi.connector.checksum.ChecksumPolicy.ChecksumKind
+ * @since 2.0.15
+ */
+ default List<ChecksumAlgorithmFactory>
getChecksumAlgorithmFactories(boolean upload) {
+ return getChecksumAlgorithmFactories();
+ }
+
/**
* Tells whether given artifact have remote external checksums according
to current layout or not. If it returns
* {@code true}, then layout configured checksums will be expected: on
upload they will be calculated and deployed
@@ -132,7 +150,7 @@ public interface RepositoryLayout {
*
* The result affects only layout provided checksums. See
* {@link
org.eclipse.aether.spi.connector.checksum.ChecksumPolicy.ChecksumKind#REMOTE_EXTERNAL}.
- * On download, the {@link
org.eclipse.aether.spi.connector.layout.RepositoryLayout#getChecksumAlgorithmFactories()}
+ * On download, the {@link
org.eclipse.aether.spi.connector.layout.RepositoryLayout#getChecksumAlgorithmFactories(boolean)}
* layout required checksums are calculated, and non layout-provided
checksums are still utilized.
*
* Typical case to return {@code false} (to omit checksums) is for
artifact signatures, that are already a