michael-o commented on code in PR #200:
URL: https://github.com/apache/maven-resolver/pull/200#discussion_r990814811


##########
maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/checksum/FileTrustedChecksumsSourceSupport.java:
##########
@@ -93,24 +94,48 @@ public Map<String, String> getTrustedArtifactChecksums( 
RepositorySystemSession
         boolean enabled = ConfigUtils.getBoolean( session, false, 
CONFIG_PROP_PREFIX + this.name );
         if ( enabled )
         {
-            Path basedir = getBasedir( session );
+            Path basedir = getBasedir( session, false );
             if ( basedir != null && !checksumAlgorithmFactories.isEmpty() )
             {
-                Map<String, String> result = performLookup(
-                        session, basedir, artifact, artifactRepository, 
checksumAlgorithmFactories );
-
-                return result == null || result.isEmpty() ? null : result;
+                return requireNonNull(
+                        performLookup( session, basedir, artifact, 
artifactRepository, checksumAlgorithmFactories )
+                );
+            }
+            else
+            {
+                return Collections.emptyMap();
             }
         }
         return null;
     }
 
+    @Override
+    public Writer getTrustedArtifactChecksumsWriter( RepositorySystemSession 
session )
+    {
+        requireNonNull( session, "session is null" );
+        boolean enabled = ConfigUtils.getBoolean( session, false, 
CONFIG_PROP_PREFIX + this.name );
+        if ( enabled )
+        {
+            return getWriter( session, getBasedir( session, true ) );
+        }
+        return null;
+    }
+
+    /**
+     * Implementors MUST NOT return {@code null} at this point, the source is 
enabled, worst can happen is checksums

Review Comment:
   ...if the source is enabled...?



##########
maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/checksum/SummaryFileTrustedChecksumsSource.java:
##########
@@ -117,14 +111,47 @@ protected Map<String, String> performLookup( 
RepositorySystemSession session,
         return checksums;
     }
 
-    private ConcurrentHashMap<String, String> loadProvidedChecksums( Path 
checksumsFile )
+    @Override
+    protected Writer getWriter( RepositorySystemSession session, Path basedir )
+    {
+        final boolean originAware = isOriginAware( session );
+        return ( artifact, artifactRepository, checksumAlgorithmFactories, 
trustedArtifactChecksums ) ->
+        {
+            try
+            {
+                for ( ChecksumAlgorithmFactory checksumAlgorithmFactory : 
checksumAlgorithmFactories )
+                {
+                    String checksum = requireNonNull(
+                            trustedArtifactChecksums.get( 
checksumAlgorithmFactory.getName() ) );
+                    String summaryLine = ArtifactIdUtils.toId( artifact ) + " 
" + checksum + "\n";

Review Comment:
   `System.lineSeparator()`



##########
maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/resolution/TrustedChecksumArtifactResolverPostProcessor.java:
##########
@@ -0,0 +1,226 @@
+package org.eclipse.aether.internal.impl.resolution;
+
+/*
+ * 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.
+ */
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+import org.eclipse.aether.RepositorySystemSession;
+import org.eclipse.aether.artifact.Artifact;
+import org.eclipse.aether.internal.impl.checksum.Sha1ChecksumAlgorithmFactory;
+import org.eclipse.aether.repository.ArtifactRepository;
+import org.eclipse.aether.resolution.ArtifactResult;
+import org.eclipse.aether.spi.checksums.TrustedChecksumsSource;
+import org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmFactory;
+import 
org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmFactorySelector;
+import org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmHelper;
+import org.eclipse.aether.transfer.ChecksumFailureException;
+import org.eclipse.aether.util.ConfigUtils;
+import org.eclipse.aether.util.artifact.ArtifactIdUtils;
+
+import static java.util.Objects.requireNonNull;
+
+/**
+ * Artifact resolver processor that verifies the checksums all the resolved 
artifacts against trusted checksums. Is also

Review Comment:
   It is also...that do support...    (because sources is plural)



##########
maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/checksum/FileTrustedChecksumsSourceSupport.java:
##########
@@ -93,24 +94,48 @@ public Map<String, String> getTrustedArtifactChecksums( 
RepositorySystemSession
         boolean enabled = ConfigUtils.getBoolean( session, false, 
CONFIG_PROP_PREFIX + this.name );
         if ( enabled )
         {
-            Path basedir = getBasedir( session );
+            Path basedir = getBasedir( session, false );
             if ( basedir != null && !checksumAlgorithmFactories.isEmpty() )
             {
-                Map<String, String> result = performLookup(
-                        session, basedir, artifact, artifactRepository, 
checksumAlgorithmFactories );
-
-                return result == null || result.isEmpty() ? null : result;
+                return requireNonNull(
+                        performLookup( session, basedir, artifact, 
artifactRepository, checksumAlgorithmFactories )
+                );
+            }
+            else
+            {
+                return Collections.emptyMap();
             }
         }
         return null;
     }
 
+    @Override
+    public Writer getTrustedArtifactChecksumsWriter( RepositorySystemSession 
session )
+    {
+        requireNonNull( session, "session is null" );
+        boolean enabled = ConfigUtils.getBoolean( session, false, 
CONFIG_PROP_PREFIX + this.name );
+        if ( enabled )
+        {
+            return getWriter( session, getBasedir( session, true ) );
+        }
+        return null;
+    }
+
+    /**
+     * Implementors MUST NOT return {@code null} at this point, the source is 
enabled, worst can happen is checksums
+     * for asked artifact are not available.
+     */
     protected abstract Map<String, String> performLookup( 
RepositorySystemSession session,
                                                           Path basedir,
                                                           Artifact artifact,
                                                           ArtifactRepository 
artifactRepository,
                                                           
List<ChecksumAlgorithmFactory> checksumAlgorithmFactories );
 
+    /**
+     * If a subclass of this support class decides it should not be writable, 
this method should return {@code null}.
+     */
+    protected abstract Writer getWriter( RepositorySystemSession session, Path 
basedir );

Review Comment:
   The writer for what?



##########
maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/checksum/SparseDirectoryTrustedChecksumsSource.java:
##########
@@ -117,9 +109,53 @@ protected Map<String, String> performLookup( 
RepositorySystemSession session,
             catch ( IOException e )
             {
                 // unexpected, log, skip
-                LOGGER.warn( "Could not read provided checksum for '{}' at 
path '{}'", artifact, checksumPath, e );
+                LOGGER.warn( "Could not read {} trusted checksum on path 
'{}'", artifact, checksumPath, e );

Review Comment:
   `...artifact '{}' trusted...`
   
   logically identical to line 96



##########
maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/checksum/SparseDirectoryTrustedChecksumsSource.java:
##########
@@ -82,26 +84,16 @@ protected Map<String, String> performLookup( 
RepositorySystemSession session,
                                                  ArtifactRepository 
artifactRepository,
                                                  
List<ChecksumAlgorithmFactory> checksumAlgorithmFactories )
     {
-        final String prefix;
-        if ( isOriginAware( session ) )
-        {
-            prefix = artifactRepository.getId() + "/";
-        }
-        else
-        {
-            prefix = "";
-        }
-
+        final boolean originAware = isOriginAware( session );
         final HashMap<String, String> checksums = new HashMap<>();
-        final String artifactPath = localPathComposer.getPathForArtifact( 
artifact, false );
         for ( ChecksumAlgorithmFactory checksumAlgorithmFactory : 
checksumAlgorithmFactories )
         {
             Path checksumPath = basedir.resolve(
-                    prefix + artifactPath + "." + 
checksumAlgorithmFactory.getFileExtension() );
+                    calculateArtifactPath( originAware, artifact, 
artifactRepository, checksumAlgorithmFactory ) );
 
             if ( !Files.isRegularFile( checksumPath ) )
             {
-                LOGGER.debug( "Artifact '{}' checksum '{}' not found in path 
'{}'",
+                LOGGER.debug( "Artifact {} trusted checksum '{}' not found on 
path '{}'",

Review Comment:
   `Artifact '{}'...`



##########
maven-resolver-spi/src/main/java/org/eclipse/aether/spi/checksums/TrustedChecksumsSource.java:
##########
@@ -39,16 +39,44 @@
 public interface TrustedChecksumsSource
 {
     /**
-     * May return the trusted checksums (for given artifact) from trusted 
source, or {@code null}.
+     * May return the trusted checksums (for given artifact) from trusted 
source, or {@code null} if not enabled.
+     * Enabled trusted checksum source SHOULD return non-null (empty map) 
result, when it has no data for given
+     * artifact. Empty map means in this case "no information", but how that 
case is interpreted depends on consumer
+     * for trusted checksums.
      *
      * @param session                    The repository system session, never 
{@code null}.
      * @param artifact                   The artifact we want checksums for, 
never {@code null}.
      * @param artifactRepository         The origin repository: local, 
workspace, remote repository, never {@code null}.
      * @param checksumAlgorithmFactories The checksum algorithms that are 
expected, never {@code null}.
-     * @return Map of expected checksums, or {@code null}.
+     * @return Map of expected checksums, or {@code null} if not enabled.
      */
     Map<String, String> getTrustedArtifactChecksums( RepositorySystemSession 
session,
                                                      Artifact artifact,
                                                      ArtifactRepository 
artifactRepository,
                                                      
List<ChecksumAlgorithmFactory> checksumAlgorithmFactories );
+
+    /**
+     * A writer that is able to write/add trusted checksums to this 
implementation.
+     */
+    interface Writer

Review Comment:
   This is rather a factory, no? The default method is more like a 
`newInstance()`?



##########
maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/resolution/TrustedChecksumArtifactResolverPostProcessor.java:
##########
@@ -0,0 +1,226 @@
+package org.eclipse.aether.internal.impl.resolution;
+
+/*
+ * 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.
+ */
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+import org.eclipse.aether.RepositorySystemSession;
+import org.eclipse.aether.artifact.Artifact;
+import org.eclipse.aether.internal.impl.checksum.Sha1ChecksumAlgorithmFactory;
+import org.eclipse.aether.repository.ArtifactRepository;
+import org.eclipse.aether.resolution.ArtifactResult;
+import org.eclipse.aether.spi.checksums.TrustedChecksumsSource;
+import org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmFactory;
+import 
org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmFactorySelector;
+import org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmHelper;
+import org.eclipse.aether.transfer.ChecksumFailureException;
+import org.eclipse.aether.util.ConfigUtils;
+import org.eclipse.aether.util.artifact.ArtifactIdUtils;
+
+import static java.util.Objects.requireNonNull;
+
+/**
+ * Artifact resolver processor that verifies the checksums all the resolved 
artifacts against trusted checksums. Is also
+ * able to "record" (calculate and write them to trusted checksum sources that 
does support this operation).
+ *
+ * @since TBD
+ */
+@Singleton
+@Named( TrustedChecksumArtifactResolverPostProcessor.NAME )
+public final class TrustedChecksumArtifactResolverPostProcessor
+        extends ArtifactResolverPostProcessorSupport
+{
+    public static final String NAME = "trusted-checksum";
+
+    private static final String CONF_CHECKSUM_ALGORITHM = "checksumAlgorithm";
+
+    private static final String CONF_FAIL_IF_MISSING = "failIfMissing";
+
+    private static final String CONF_RECORD = "record";
+
+    private final ChecksumAlgorithmFactorySelector 
checksumAlgorithmFactorySelector;
+
+    private final Map<String, TrustedChecksumsSource> trustedChecksumsSources;
+
+    @Inject
+    public TrustedChecksumArtifactResolverPostProcessor(
+            ChecksumAlgorithmFactorySelector checksumAlgorithmFactorySelector,
+            Map<String, TrustedChecksumsSource> trustedChecksumsSources )
+    {
+        super( NAME );
+        this.checksumAlgorithmFactorySelector = requireNonNull( 
checksumAlgorithmFactorySelector );
+        this.trustedChecksumsSources = requireNonNull( trustedChecksumsSources 
);
+    }
+
+    @Override
+    protected Outcome doProcess( RepositorySystemSession session, 
List<ArtifactResult> artifactResults )
+    {
+        final List<ChecksumAlgorithmFactory> checksumAlgorithmFactories = 
Collections.singletonList(
+                checksumAlgorithmFactorySelector.select( 
ConfigUtils.getString( session,
+                        Sha1ChecksumAlgorithmFactory.NAME, configPropKey( 
CONF_CHECKSUM_ALGORITHM ) ) ) );
+        final boolean failIfMissing = ConfigUtils.getBoolean(
+                session, false, configPropKey( CONF_FAIL_IF_MISSING ) );
+        final boolean record = ConfigUtils.getBoolean( session, false, 
configPropKey( CONF_RECORD ) );

Review Comment:
   No conf prefix, nothing?



##########
maven-resolver-spi/src/main/java/org/eclipse/aether/spi/resolution/ArtifactResolverPostProcessor.java:
##########
@@ -0,0 +1,63 @@
+package org.eclipse.aether.spi.resolution;
+
+/*
+ * 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.
+ */
+
+import java.util.List;
+
+import org.eclipse.aether.RepositorySystemSession;
+import org.eclipse.aether.resolution.ArtifactResult;
+
+/**
+ * Artifact resolver post-resolution processor component, is able to hook into 
resolver and post-process the resolved
+ * artifact results, if needed even produce resolution failure. It will always 
be invoked (even when failure is about
+ * to happen), so detecting these cases are left to post processor 
implementations.
+ *
+ * @since TBD
+ */
+public interface ArtifactResolverPostProcessor
+{
+    /**
+     * Enum representing post-processing outcome.
+     */
+    enum Outcome
+    {
+        /**
+         * Post-processing was ok, continue.
+         */
+        CONTINUE,

Review Comment:
   This implied that the other enum value breaks the loop which it doesn't not? 
Should be `SUCCESSFUL` or `COMPLETED`, no?



##########
maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/resolution/TrustedChecksumArtifactResolverPostProcessor.java:
##########
@@ -0,0 +1,226 @@
+package org.eclipse.aether.internal.impl.resolution;
+
+/*
+ * 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.
+ */
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+import org.eclipse.aether.RepositorySystemSession;
+import org.eclipse.aether.artifact.Artifact;
+import org.eclipse.aether.internal.impl.checksum.Sha1ChecksumAlgorithmFactory;
+import org.eclipse.aether.repository.ArtifactRepository;
+import org.eclipse.aether.resolution.ArtifactResult;
+import org.eclipse.aether.spi.checksums.TrustedChecksumsSource;
+import org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmFactory;
+import 
org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmFactorySelector;
+import org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmHelper;
+import org.eclipse.aether.transfer.ChecksumFailureException;
+import org.eclipse.aether.util.ConfigUtils;
+import org.eclipse.aether.util.artifact.ArtifactIdUtils;
+
+import static java.util.Objects.requireNonNull;
+
+/**
+ * Artifact resolver processor that verifies the checksums all the resolved 
artifacts against trusted checksums. Is also
+ * able to "record" (calculate and write them to trusted checksum sources that 
does support this operation).
+ *
+ * @since TBD
+ */
+@Singleton
+@Named( TrustedChecksumArtifactResolverPostProcessor.NAME )
+public final class TrustedChecksumArtifactResolverPostProcessor
+        extends ArtifactResolverPostProcessorSupport
+{
+    public static final String NAME = "trusted-checksum";
+
+    private static final String CONF_CHECKSUM_ALGORITHM = "checksumAlgorithm";
+
+    private static final String CONF_FAIL_IF_MISSING = "failIfMissing";
+
+    private static final String CONF_RECORD = "record";
+
+    private final ChecksumAlgorithmFactorySelector 
checksumAlgorithmFactorySelector;
+
+    private final Map<String, TrustedChecksumsSource> trustedChecksumsSources;
+
+    @Inject
+    public TrustedChecksumArtifactResolverPostProcessor(
+            ChecksumAlgorithmFactorySelector checksumAlgorithmFactorySelector,
+            Map<String, TrustedChecksumsSource> trustedChecksumsSources )
+    {
+        super( NAME );
+        this.checksumAlgorithmFactorySelector = requireNonNull( 
checksumAlgorithmFactorySelector );
+        this.trustedChecksumsSources = requireNonNull( trustedChecksumsSources 
);
+    }
+
+    @Override
+    protected Outcome doProcess( RepositorySystemSession session, 
List<ArtifactResult> artifactResults )
+    {
+        final List<ChecksumAlgorithmFactory> checksumAlgorithmFactories = 
Collections.singletonList(
+                checksumAlgorithmFactorySelector.select( 
ConfigUtils.getString( session,
+                        Sha1ChecksumAlgorithmFactory.NAME, configPropKey( 
CONF_CHECKSUM_ALGORITHM ) ) ) );
+        final boolean failIfMissing = ConfigUtils.getBoolean(
+                session, false, configPropKey( CONF_FAIL_IF_MISSING ) );
+        final boolean record = ConfigUtils.getBoolean( session, false, 
configPropKey( CONF_RECORD ) );
+
+        Outcome outcome = Outcome.CONTINUE;
+        for ( ArtifactResult artifactResult : artifactResults )
+        {
+            Artifact artifact = artifactResult.getArtifact();
+            if ( artifact != null && artifact.getFile() != null )
+            {
+                if ( record )
+                {
+                    recordArtifactChecksums( session, artifactResult, 
checksumAlgorithmFactories );
+                }
+                else if ( !validateArtifactChecksums( session, artifactResult, 
checksumAlgorithmFactories,
+                        failIfMissing ) )
+                {
+                    artifactResult.setArtifact( artifact.setFile( null ) ); // 
make it unresolved
+                    outcome = Outcome.FAILED;
+                }
+            }
+        }
+        return outcome;
+    }
+
+    /**
+     * Calculates and records checksums into trusted sources that support 
writing.
+     */
+    private void recordArtifactChecksums( RepositorySystemSession session,
+                                          ArtifactResult artifactResult,
+                                          List<ChecksumAlgorithmFactory> 
checksumAlgorithmFactories )
+    {
+        Artifact artifact = artifactResult.getArtifact();
+        ArtifactRepository artifactRepository = artifactResult.getRepository();
+
+        try
+        {
+            final Map<String, String> calculatedChecksums = 
ChecksumAlgorithmHelper.calculate(
+                    artifact.getFile(), checksumAlgorithmFactories );
+
+            for ( TrustedChecksumsSource trustedChecksumsSource : 
trustedChecksumsSources.values() )
+            {
+                TrustedChecksumsSource.Writer writer = trustedChecksumsSource
+                        .getTrustedArtifactChecksumsWriter( session );
+
+                if ( writer != null )
+                {
+                    writer.addTrustedArtifactChecksums( artifact, 
artifactRepository, checksumAlgorithmFactories,
+                            calculatedChecksums );
+                }
+            }
+        }
+        catch ( IOException e )
+        {
+            throw new UncheckedIOException( e );
+        }
+    }
+
+    /**
+     * Validates trusted checksums against {@link ArtifactResult}, returns 
{@code true} denoting "valid" checksums or
+     * {@code false} denoting "invalid" checksums.
+     */
+    private boolean validateArtifactChecksums( RepositorySystemSession session,
+                                               ArtifactResult artifactResult,
+                                               List<ChecksumAlgorithmFactory> 
checksumAlgorithmFactories,
+                                               boolean failIfMissing )
+    {
+        Artifact artifact = artifactResult.getArtifact();
+        ArtifactRepository artifactRepository = artifactResult.getRepository();
+
+        boolean valid = true;
+        boolean validated = false;
+        try
+        {
+            // full set: calculate all algorithms we were asked for
+            final Map<String, String> calculatedChecksums = 
ChecksumAlgorithmHelper.calculate(
+                    artifact.getFile(), checksumAlgorithmFactories );
+
+            for ( Map.Entry<String, TrustedChecksumsSource> entry : 
trustedChecksumsSources.entrySet() )
+            {
+                final String trustedSourceName = entry.getKey();
+                final TrustedChecksumsSource trustedChecksumsSource = 
entry.getValue();
+
+                // upper bound set: ask source for checksums, ideally same as 
calculatedChecksums but may be less
+                Map<String, String> trustedChecksums = 
trustedChecksumsSource.getTrustedArtifactChecksums(
+                        session, artifact, artifactRepository, 
checksumAlgorithmFactories );
+
+                if ( trustedChecksums == null )
+                {
+                    continue; // not enabled
+                }
+                validated = true;
+
+                if ( !calculatedChecksums.equals( trustedChecksums ) )
+                {
+                    Set<String> missingTrustedAlg = new HashSet<>( 
calculatedChecksums.keySet() );
+                    missingTrustedAlg.removeAll( trustedChecksums.keySet() );
+
+                    if ( !missingTrustedAlg.isEmpty() && failIfMissing )
+                    {
+                        artifactResult.addException( new 
ChecksumFailureException( "Missing from " + trustedSourceName
+                                + " trusted checksum(s) " + missingTrustedAlg 
+ " for artifact "
+                                + ArtifactIdUtils.toId( artifact ) ) );
+                        valid = false;
+                    }
+
+                    // compare values but only present ones, failIfMissing 
handled above
+                    // we still want to report all: algX - missing, algY - 
mismatch, etc
+                    for ( ChecksumAlgorithmFactory checksumAlgorithmFactory : 
checksumAlgorithmFactories )
+                    {
+                        String calculatedChecksum = calculatedChecksums.get( 
checksumAlgorithmFactory.getName() );
+                        String trustedChecksum = trustedChecksums.get( 
checksumAlgorithmFactory.getName() );
+                        if ( trustedChecksum != null && !Objects.equals( 
calculatedChecksum, trustedChecksum ) )
+                        {
+                            artifactResult.addException( new 
ChecksumFailureException( "Artifact "
+                                    + ArtifactIdUtils.toId( artifact ) + " 
trusted checksum mismatch: "
+                                    + trustedSourceName + "=" + 
trustedChecksum + "; calculated="
+                                    + calculatedChecksum ) );
+                            valid = false;
+                        }
+                    }
+                }
+            }
+
+            if ( !validated && failIfMissing  )
+            {
+                artifactResult.addException( new ChecksumFailureException( 
"There are no enabled trusted checksum"
+                        + " source(s) to validate with." ) );

Review Comment:
   ...validate against



##########
maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/resolution/TrustedChecksumArtifactResolverPostProcessor.java:
##########
@@ -0,0 +1,226 @@
+package org.eclipse.aether.internal.impl.resolution;
+
+/*
+ * 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.
+ */
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+import org.eclipse.aether.RepositorySystemSession;
+import org.eclipse.aether.artifact.Artifact;
+import org.eclipse.aether.internal.impl.checksum.Sha1ChecksumAlgorithmFactory;
+import org.eclipse.aether.repository.ArtifactRepository;
+import org.eclipse.aether.resolution.ArtifactResult;
+import org.eclipse.aether.spi.checksums.TrustedChecksumsSource;
+import org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmFactory;
+import 
org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmFactorySelector;
+import org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmHelper;
+import org.eclipse.aether.transfer.ChecksumFailureException;
+import org.eclipse.aether.util.ConfigUtils;
+import org.eclipse.aether.util.artifact.ArtifactIdUtils;
+
+import static java.util.Objects.requireNonNull;
+
+/**
+ * Artifact resolver processor that verifies the checksums all the resolved 
artifacts against trusted checksums. Is also

Review Comment:
   Artifact resolver processor that verifies the checksums of all resolved 
artifacts against trusted checksums.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscr...@maven.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org

Reply via email to