You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by cs...@apache.org on 2021/12/14 14:26:06 UTC

[maven-resolver] 01/01: Checksum is not a digest

This is an automated email from the ASF dual-hosted git repository.

cstamas pushed a commit to branch checksums
in repository https://gitbox.apache.org/repos/asf/maven-resolver.git

commit ede442ff75f4da8c7797d87529086307146f9e5b
Author: Tamas Cservenak <ta...@cservenak.net>
AuthorDate: Tue Dec 14 15:25:09 2021 +0100

    Checksum is not a digest
    
    Distance ourselves from MessageDigest, and open up ways
    to define and support different (real) checksum implementations
    as well.
---
 .../connector/basic/BasicRepositoryConnector.java  | 17 +++--
 .../basic/BasicRepositoryConnectorFactory.java     | 23 +++++-
 .../aether/connector/basic/ChecksumCalculator.java | 59 +++++++++------
 .../connector/basic/ChecksumImplementation.java    | 41 ++++++++++
 .../basic/ChecksumImplementationSelector.java      | 37 +++++++++
 .../aether/connector/basic/ChecksumValidator.java  | 14 +++-
 .../DefaultChecksumImplementationSelector.java     | 87 ++++++++++++++++++++++
 .../FooChecksumImplementationProvider.java         | 62 +++++++++++++++
 .../connector/basic/ChecksumCalculatorTest.java    |  4 +-
 .../connector/basic/ChecksumValidatorTest.java     |  4 +-
 10 files changed, 311 insertions(+), 37 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 3fed9a1..76a6097 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
@@ -99,6 +99,8 @@ final class BasicRepositoryConnector
 
     private final ChecksumPolicyProvider checksumPolicyProvider;
 
+    private final ChecksumImplementationSelector checksumImplementationSelector;
+
     private final PartialFile.Factory partialFileFactory;
 
     private final int maxThreads;
@@ -111,9 +113,13 @@ final class BasicRepositoryConnector
 
     private boolean closed;
 
-    BasicRepositoryConnector( RepositorySystemSession session, RemoteRepository repository,
-                                     TransporterProvider transporterProvider, RepositoryLayoutProvider layoutProvider,
-                                     ChecksumPolicyProvider checksumPolicyProvider, FileProcessor fileProcessor )
+    BasicRepositoryConnector( RepositorySystemSession session,
+                              RemoteRepository repository,
+                              TransporterProvider transporterProvider,
+                              RepositoryLayoutProvider layoutProvider,
+                              ChecksumPolicyProvider checksumPolicyProvider,
+                              ChecksumImplementationSelector checksumImplementationSelector,
+                              FileProcessor fileProcessor )
         throws NoRepositoryConnectorException
     {
         try
@@ -133,6 +139,7 @@ final class BasicRepositoryConnector
             throw new NoRepositoryConnectorException( repository, e.getMessage(), e );
         }
         this.checksumPolicyProvider = checksumPolicyProvider;
+        this.checksumImplementationSelector = checksumImplementationSelector;
 
         this.session = session;
         this.repository = repository;
@@ -406,8 +413,8 @@ final class BasicRepositoryConnector
         {
             super( path, listener );
             this.file = requireNonNull( file, "destination file cannot be null" );
-            checksumValidator =
-                new ChecksumValidator( file, fileProcessor, this, checksumPolicy, safe( checksums ) );
+            checksumValidator = new ChecksumValidator( file, fileProcessor, this,
+                checksumPolicy, safe( checksums ), checksumImplementationSelector );
         }
 
         public void checkRemoteAccess()
diff --git a/maven-resolver-connector-basic/src/main/java/org/eclipse/aether/connector/basic/BasicRepositoryConnectorFactory.java b/maven-resolver-connector-basic/src/main/java/org/eclipse/aether/connector/basic/BasicRepositoryConnectorFactory.java
index aa747a9..a4ed966 100644
--- a/maven-resolver-connector-basic/src/main/java/org/eclipse/aether/connector/basic/BasicRepositoryConnectorFactory.java
+++ b/maven-resolver-connector-basic/src/main/java/org/eclipse/aether/connector/basic/BasicRepositoryConnectorFactory.java
@@ -51,6 +51,8 @@ public final class BasicRepositoryConnectorFactory
 
     private ChecksumPolicyProvider checksumPolicyProvider;
 
+    private ChecksumImplementationSelector checksumImplementationSelector;
+
     private FileProcessor fileProcessor;
 
     private float priority;
@@ -67,11 +69,14 @@ public final class BasicRepositoryConnectorFactory
 
     @Inject
     BasicRepositoryConnectorFactory( TransporterProvider transporterProvider, RepositoryLayoutProvider layoutProvider,
-                                     ChecksumPolicyProvider checksumPolicyProvider, FileProcessor fileProcessor )
+                                     ChecksumPolicyProvider checksumPolicyProvider,
+                                     ChecksumImplementationSelector checksumImplementationSelector,
+                                     FileProcessor fileProcessor )
     {
         setTransporterProvider( transporterProvider );
         setRepositoryLayoutProvider( layoutProvider );
         setChecksumPolicyProvider( checksumPolicyProvider );
+        setChecksumImplementationSelector( checksumImplementationSelector );
         setFileProcessor( fileProcessor );
     }
 
@@ -121,6 +126,20 @@ public final class BasicRepositoryConnectorFactory
     }
 
     /**
+     * Sets the checksum implementation selector to use for this component.
+     *
+     * @param checksumImplementationSelector The checksum implementation selector to use, must not be {@code null}.
+     * @return This component for chaining, never {@code null}.
+     */
+    public BasicRepositoryConnectorFactory setChecksumImplementationSelector(
+        ChecksumImplementationSelector checksumImplementationSelector )
+    {
+        this.checksumImplementationSelector = requireNonNull(
+                checksumImplementationSelector, "checksum implementation selector cannot be null" );
+        return this;
+    }
+
+    /**
      * Sets the file processor to use for this component.
      *
      * @param fileProcessor The file processor to use, must not be {@code null}.
@@ -156,7 +175,7 @@ public final class BasicRepositoryConnectorFactory
         requireNonNull( "repository", "repository cannot be null" );
 
         return new BasicRepositoryConnector( session, repository, transporterProvider, layoutProvider,
-                                             checksumPolicyProvider, fileProcessor );
+                                             checksumPolicyProvider, checksumImplementationSelector, fileProcessor );
     }
 
 }
diff --git a/maven-resolver-connector-basic/src/main/java/org/eclipse/aether/connector/basic/ChecksumCalculator.java b/maven-resolver-connector-basic/src/main/java/org/eclipse/aether/connector/basic/ChecksumCalculator.java
index 0173fbb..ffe7865 100644
--- a/maven-resolver-connector-basic/src/main/java/org/eclipse/aether/connector/basic/ChecksumCalculator.java
+++ b/maven-resolver-connector-basic/src/main/java/org/eclipse/aether/connector/basic/ChecksumCalculator.java
@@ -25,7 +25,6 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.nio.Buffer;
 import java.nio.ByteBuffer;
-import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -38,6 +37,8 @@ import java.util.Set;
 import org.eclipse.aether.spi.connector.layout.RepositoryLayout;
 import org.eclipse.aether.util.ChecksumUtils;
 
+import static java.util.Objects.requireNonNull;
+
 /**
  * Calculates checksums for a downloaded file.
  */
@@ -48,45 +49,44 @@ final class ChecksumCalculator
     {
         final String algorithm;
 
-        final MessageDigest digest;
+        final ChecksumImplementation engine;
 
         Exception error;
 
-        Checksum( String algorithm )
+        Checksum( String algorithm, ChecksumImplementation engine )
         {
-            this.algorithm = algorithm;
-            MessageDigest digest = null;
-            try
-            {
-                digest = MessageDigest.getInstance( algorithm );
-            }
-            catch ( NoSuchAlgorithmException e )
-            {
-                error = e;
-            }
-            this.digest = digest;
+            this.algorithm = requireNonNull( algorithm );
+            this.engine = requireNonNull( engine );
+
+        }
+
+        Checksum( String algorithm, Exception error )
+        {
+            this.algorithm = requireNonNull( algorithm );
+            this.engine = null;
+            this.error = requireNonNull( error );
         }
 
         public void update( ByteBuffer buffer )
         {
-            if ( digest != null )
+            if ( engine != null )
             {
-                digest.update( buffer );
+                engine.update( buffer );
             }
         }
 
         public void reset()
         {
-            if ( digest != null )
+            if ( engine != null )
             {
-                digest.reset();
+                engine.reset();
                 error = null;
             }
         }
 
         public void error( Exception error )
         {
-            if ( digest != null )
+            if ( engine != null )
             {
                 this.error = error;
             }
@@ -98,7 +98,7 @@ final class ChecksumCalculator
             {
                 return error;
             }
-            return ChecksumUtils.toHexString( digest.digest() );
+            return ChecksumUtils.toHexString( engine.digest() );
         }
 
     }
@@ -107,16 +107,20 @@ final class ChecksumCalculator
 
     private final File targetFile;
 
-    public static ChecksumCalculator newInstance( File targetFile, Collection<RepositoryLayout.Checksum> checksums )
+    public static ChecksumCalculator newInstance( ChecksumImplementationSelector selector,
+                                                  File targetFile,
+                                                  Collection<RepositoryLayout.Checksum> checksums )
     {
         if ( checksums == null || checksums.isEmpty() )
         {
             return null;
         }
-        return new ChecksumCalculator( targetFile, checksums );
+        return new ChecksumCalculator( selector, targetFile, checksums );
     }
 
-    private ChecksumCalculator( File targetFile, Collection<RepositoryLayout.Checksum> checksums )
+    private ChecksumCalculator( ChecksumImplementationSelector selector,
+                                File targetFile,
+                                Collection<RepositoryLayout.Checksum> checksums )
     {
         this.checksums = new ArrayList<>();
         Set<String> algos = new HashSet<>();
@@ -125,7 +129,14 @@ final class ChecksumCalculator
             String algo = checksum.getAlgorithm();
             if ( algos.add( algo ) )
             {
-                this.checksums.add( new Checksum( algo ) );
+                try
+                {
+                    this.checksums.add( new Checksum( algo, selector.select( algo ) ) );
+                }
+                catch ( NoSuchAlgorithmException e )
+                {
+                    this.checksums.add( new Checksum( algo, e ) );
+                }
             }
         }
         this.targetFile = targetFile;
diff --git a/maven-resolver-connector-basic/src/main/java/org/eclipse/aether/connector/basic/ChecksumImplementation.java b/maven-resolver-connector-basic/src/main/java/org/eclipse/aether/connector/basic/ChecksumImplementation.java
new file mode 100644
index 0000000..02cdc36
--- /dev/null
+++ b/maven-resolver-connector-basic/src/main/java/org/eclipse/aether/connector/basic/ChecksumImplementation.java
@@ -0,0 +1,41 @@
+package org.eclipse.aether.connector.basic;
+
+/*
+ * 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.nio.ByteBuffer;
+
+/**
+ * Implementation performing checksum calculation for specific algorithm. Instances of this interface as stateful,
+ * should be reused only after {@link #reset()}.
+ *
+ * <strong>Important note:</strong> if implementation of this interface is component, it MUST NOT be singleton, but
+ * must adhere to "prototype" pattern. Alternative is just to implement a provider, and on each get invocation create
+ * new instance.
+ *
+ * @since TBD
+ */
+public interface ChecksumImplementation
+{
+  void update( ByteBuffer input );
+
+  void reset();
+
+  byte[] digest();
+}
diff --git a/maven-resolver-connector-basic/src/main/java/org/eclipse/aether/connector/basic/ChecksumImplementationSelector.java b/maven-resolver-connector-basic/src/main/java/org/eclipse/aether/connector/basic/ChecksumImplementationSelector.java
new file mode 100644
index 0000000..b4169b1
--- /dev/null
+++ b/maven-resolver-connector-basic/src/main/java/org/eclipse/aether/connector/basic/ChecksumImplementationSelector.java
@@ -0,0 +1,37 @@
+package org.eclipse.aether.connector.basic;
+
+/*
+ * 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.security.NoSuchAlgorithmException;
+
+/**
+ * Selector that selects implemntation based on passed in algorithm name.
+ *
+ * @since TBD
+ */
+public interface ChecksumImplementationSelector
+{
+  /**
+   * Returns a new instance ready to perform checksum calculation for given algorithm, never {@code null}.
+   *
+   * @throws NoSuchAlgorithmException if algorithm asked for is not supported.
+   */
+  ChecksumImplementation select( String algorithm ) throws NoSuchAlgorithmException;
+}
diff --git a/maven-resolver-connector-basic/src/main/java/org/eclipse/aether/connector/basic/ChecksumValidator.java b/maven-resolver-connector-basic/src/main/java/org/eclipse/aether/connector/basic/ChecksumValidator.java
index 5a77bf7..31b2df2 100644
--- a/maven-resolver-connector-basic/src/main/java/org/eclipse/aether/connector/basic/ChecksumValidator.java
+++ b/maven-resolver-connector-basic/src/main/java/org/eclipse/aether/connector/basic/ChecksumValidator.java
@@ -65,11 +65,16 @@ final class ChecksumValidator
 
     private final Collection<Checksum> checksums;
 
+    private final ChecksumImplementationSelector checksumImplementationSelector;
+
     private final Map<File, Object> checksumFiles;
 
-    ChecksumValidator( File dataFile, FileProcessor fileProcessor,
-                              ChecksumFetcher checksumFetcher, ChecksumPolicy checksumPolicy,
-                              Collection<Checksum> checksums )
+    ChecksumValidator( File dataFile,
+                       FileProcessor fileProcessor,
+                       ChecksumFetcher checksumFetcher,
+                       ChecksumPolicy checksumPolicy,
+                       Collection<Checksum> checksums,
+                       ChecksumImplementationSelector checksumImplementationSelector )
     {
         this.dataFile = dataFile;
         this.tempFiles = new HashSet<>();
@@ -77,6 +82,7 @@ final class ChecksumValidator
         this.checksumFetcher = checksumFetcher;
         this.checksumPolicy = checksumPolicy;
         this.checksums = checksums;
+        this.checksumImplementationSelector = checksumImplementationSelector;
         checksumFiles = new HashMap<>();
     }
 
@@ -84,7 +90,7 @@ final class ChecksumValidator
     {
         if ( checksumPolicy != null )
         {
-            return ChecksumCalculator.newInstance( targetFile, checksums );
+            return ChecksumCalculator.newInstance( checksumImplementationSelector, targetFile, checksums );
         }
         return null;
     }
diff --git a/maven-resolver-connector-basic/src/main/java/org/eclipse/aether/connector/basic/checksum/DefaultChecksumImplementationSelector.java b/maven-resolver-connector-basic/src/main/java/org/eclipse/aether/connector/basic/checksum/DefaultChecksumImplementationSelector.java
new file mode 100644
index 0000000..84422cd
--- /dev/null
+++ b/maven-resolver-connector-basic/src/main/java/org/eclipse/aether/connector/basic/checksum/DefaultChecksumImplementationSelector.java
@@ -0,0 +1,87 @@
+package org.eclipse.aether.connector.basic.checksum;
+
+/*
+ * 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.nio.ByteBuffer;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Locale;
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Provider;
+import javax.inject.Singleton;
+
+import org.eclipse.aether.connector.basic.ChecksumImplementation;
+import org.eclipse.aether.connector.basic.ChecksumImplementationSelector;
+
+import static java.util.Objects.requireNonNull;
+
+/**
+ * Default implementation of {@link ChecksumImplementationSelector}.
+ */
+@Singleton
+@Named
+public class DefaultChecksumImplementationSelector
+    implements ChecksumImplementationSelector
+{
+    private final Map<String, Provider<ChecksumImplementation>> providers;
+
+    @Inject
+    public DefaultChecksumImplementationSelector( final Map<String, Provider<ChecksumImplementation>> providers )
+    {
+        this.providers = requireNonNull( providers );
+    }
+
+    @Override
+    public ChecksumImplementation select( final String algorithm ) throws NoSuchAlgorithmException
+    {
+        requireNonNull( algorithm, "algorithm name must not be null" );
+        Provider<ChecksumImplementation> provider = providers.get( algorithm.toUpperCase( Locale.ENGLISH ) );
+        if ( provider != null )
+        {
+            return provider.get();
+        }
+
+        // fallback to MessageDigest backed one
+        MessageDigest messageDigest = MessageDigest.getInstance( algorithm );
+        return new ChecksumImplementation()
+        {
+            @Override
+            public void update( final ByteBuffer input )
+            {
+                messageDigest.update( input );
+            }
+
+            @Override
+            public void reset()
+            {
+                messageDigest.reset();
+            }
+
+            @Override
+            public byte[] digest()
+            {
+                return messageDigest.digest();
+            }
+        };
+    }
+}
diff --git a/maven-resolver-connector-basic/src/main/java/org/eclipse/aether/connector/basic/checksum/FooChecksumImplementationProvider.java b/maven-resolver-connector-basic/src/main/java/org/eclipse/aether/connector/basic/checksum/FooChecksumImplementationProvider.java
new file mode 100644
index 0000000..1ccf178
--- /dev/null
+++ b/maven-resolver-connector-basic/src/main/java/org/eclipse/aether/connector/basic/checksum/FooChecksumImplementationProvider.java
@@ -0,0 +1,62 @@
+package org.eclipse.aether.connector.basic.checksum;
+
+/*
+ * 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.nio.ByteBuffer;
+
+import javax.inject.Named;
+import javax.inject.Provider;
+import javax.inject.Singleton;
+
+import org.eclipse.aether.connector.basic.ChecksumImplementation;
+
+/**
+ * Provides FOO calculating checksum implementation.
+ *
+ * @since TBD
+ */
+@Singleton
+@Named( "FOO" )
+public class FooChecksumImplementationProvider
+    implements Provider<ChecksumImplementation>
+{
+    @Override
+    public ChecksumImplementation get()
+    {
+        return new ChecksumImplementation()
+        {
+            @Override
+            public void update( final ByteBuffer input )
+            {
+            }
+
+            @Override
+            public void reset()
+            {
+            }
+
+            @Override
+            public byte[] digest()
+            {
+                return new byte[] { 0x1, 0x2 };
+            }
+        };
+    }
+}
diff --git a/maven-resolver-connector-basic/src/test/java/org/eclipse/aether/connector/basic/ChecksumCalculatorTest.java b/maven-resolver-connector-basic/src/test/java/org/eclipse/aether/connector/basic/ChecksumCalculatorTest.java
index a903386..27a1373 100644
--- a/maven-resolver-connector-basic/src/test/java/org/eclipse/aether/connector/basic/ChecksumCalculatorTest.java
+++ b/maven-resolver-connector-basic/src/test/java/org/eclipse/aether/connector/basic/ChecksumCalculatorTest.java
@@ -28,9 +28,11 @@ import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
 import java.security.NoSuchAlgorithmException;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 
+import org.eclipse.aether.connector.basic.checksum.DefaultChecksumImplementationSelector;
 import org.eclipse.aether.internal.test.util.TestFileUtils;
 import org.eclipse.aether.spi.connector.layout.RepositoryLayout;
 import org.junit.Before;
@@ -56,7 +58,7 @@ public class ChecksumCalculatorTest
         {
             checksums.add( new RepositoryLayout.Checksum( algo, URI.create( "irrelevant" ) ) );
         }
-        return ChecksumCalculator.newInstance( file, checksums );
+        return ChecksumCalculator.newInstance( new DefaultChecksumImplementationSelector( Collections.emptyMap() ), file, checksums );
     }
 
     private ByteBuffer toBuffer( String data )
diff --git a/maven-resolver-connector-basic/src/test/java/org/eclipse/aether/connector/basic/ChecksumValidatorTest.java b/maven-resolver-connector-basic/src/test/java/org/eclipse/aether/connector/basic/ChecksumValidatorTest.java
index c0d1467..8950aee 100644
--- a/maven-resolver-connector-basic/src/test/java/org/eclipse/aether/connector/basic/ChecksumValidatorTest.java
+++ b/maven-resolver-connector-basic/src/test/java/org/eclipse/aether/connector/basic/ChecksumValidatorTest.java
@@ -26,11 +26,13 @@ import java.io.IOException;
 import java.net.URI;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 
+import org.eclipse.aether.connector.basic.checksum.DefaultChecksumImplementationSelector;
 import org.eclipse.aether.internal.test.util.TestFileProcessor;
 import org.eclipse.aether.internal.test.util.TestFileUtils;
 import org.eclipse.aether.spi.connector.checksum.ChecksumPolicy;
@@ -194,7 +196,7 @@ public class ChecksumValidatorTest
 
     private ChecksumValidator newValidator( String... algos )
     {
-        return new ChecksumValidator( dataFile, new TestFileProcessor(), fetcher, policy, newChecksums( algos ) );
+        return new ChecksumValidator( dataFile, new TestFileProcessor(), fetcher, policy, newChecksums( algos ), new DefaultChecksumImplementationSelector( Collections.emptyMap() ));
     }
 
     private Map<String, ?> checksums( String... algoDigestPairs )