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 2022/04/14 08:47:43 UTC

[maven-resolver] 01/01: [EXPERIMENT] Make LRM path composition reusable

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

cstamas pushed a commit to branch make-local-path-composer-reusable
in repository https://gitbox.apache.org/repos/asf/maven-resolver.git

commit 8af7e1304161f375515daf23597c652fe3f8504a
Author: Tamas Cservenak <ta...@cservenak.net>
AuthorDate: Thu Apr 14 10:45:40 2022 +0200

    [EXPERIMENT] Make LRM path composition reusable
    
    LocalRepositoryManager path composition was enclosed
    into SimpleLocalRepositoryManager in not-quite reusable
    manner. Make it reusable, by making it into a component.
    
    Currently FileProvidedChecksumsSource was reusing local
    paths, is adjusted now.
    
    Also, make LRM implementations more encapsulated and
    clear up many ctors leaving only one for simplicity.
---
 .../eclipse/aether/impl/DefaultServiceLocator.java |   3 +
 .../eclipse/aether/impl/guice/AetherModule.java    |   4 +
 .../aether/internal/impl/ArtifactPathComposer.java |  36 +++++++
 .../internal/impl/DefaultArtifactPathComposer.java | 110 +++++++++++++++++++++
 .../impl/EnhancedLocalRepositoryManager.java       |   3 +-
 .../EnhancedLocalRepositoryManagerFactory.java     |  25 +++--
 .../internal/impl/FileProvidedChecksumsSource.java |  10 +-
 .../impl/SimpleLocalRepositoryManager.java         | 108 ++++----------------
 .../impl/SimpleLocalRepositoryManagerFactory.java  |  29 +++++-
 .../impl/EnhancedLocalRepositoryManagerTest.java   |   2 +-
 .../impl/FileProvidedChecksumsSourceTest.java      |   2 +-
 .../impl/SimpleLocalRepositoryManagerTest.java     |   3 +-
 12 files changed, 225 insertions(+), 110 deletions(-)

diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/DefaultServiceLocator.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/DefaultServiceLocator.java
index c17e2378..e3bf55a2 100644
--- a/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/DefaultServiceLocator.java
+++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/DefaultServiceLocator.java
@@ -31,6 +31,8 @@ import java.util.Map;
 import static java.util.Objects.requireNonNull;
 
 import org.eclipse.aether.RepositorySystem;
+import org.eclipse.aether.internal.impl.ArtifactPathComposer;
+import org.eclipse.aether.internal.impl.DefaultArtifactPathComposer;
 import org.eclipse.aether.internal.impl.DefaultArtifactResolver;
 import org.eclipse.aether.internal.impl.DefaultChecksumPolicyProvider;
 import org.eclipse.aether.internal.impl.DefaultTrackingFileManager;
@@ -227,6 +229,7 @@ public final class DefaultServiceLocator
         addService( TrackingFileManager.class, DefaultTrackingFileManager.class );
         addService( NamedLockFactorySelector.class, SimpleNamedLockFactorySelector.class );
         addService( ChecksumAlgorithmFactorySelector.class, DefaultChecksumAlgorithmFactorySelector.class );
+        addService( ArtifactPathComposer.class, DefaultArtifactPathComposer.class );
     }
 
     private <T> Entry<T> getEntry( Class<T> type, boolean create )
diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/guice/AetherModule.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/guice/AetherModule.java
index 93ef99ec..49e29adc 100644
--- a/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/guice/AetherModule.java
+++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/guice/AetherModule.java
@@ -40,6 +40,8 @@ import org.eclipse.aether.impl.OfflineController;
 import org.eclipse.aether.impl.RemoteRepositoryManager;
 import org.eclipse.aether.impl.RepositoryConnectorProvider;
 import org.eclipse.aether.impl.RepositoryEventDispatcher;
+import org.eclipse.aether.internal.impl.ArtifactPathComposer;
+import org.eclipse.aether.internal.impl.DefaultArtifactPathComposer;
 import org.eclipse.aether.internal.impl.DefaultTrackingFileManager;
 import org.eclipse.aether.internal.impl.FileProvidedChecksumsSource;
 import org.eclipse.aether.internal.impl.TrackingFileManager;
@@ -171,6 +173,8 @@ public class AetherModule
                 .to( DefaultRepositoryEventDispatcher.class ).in( Singleton.class );
         bind( OfflineController.class ) //
                 .to( DefaultOfflineController.class ).in( Singleton.class );
+
+        bind( ArtifactPathComposer.class ).to( DefaultArtifactPathComposer.class ).in( Singleton.class );
         bind( LocalRepositoryProvider.class ) //
                 .to( DefaultLocalRepositoryProvider.class ).in( Singleton.class );
         bind( LocalRepositoryManagerFactory.class ).annotatedWith( Names.named( "simple" ) ) //
diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/ArtifactPathComposer.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/ArtifactPathComposer.java
new file mode 100644
index 00000000..e2c0c63d
--- /dev/null
+++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/ArtifactPathComposer.java
@@ -0,0 +1,36 @@
+package org.eclipse.aether.internal.impl;
+
+/*
+ * 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 org.eclipse.aether.artifact.Artifact;
+import org.eclipse.aether.metadata.Metadata;
+
+/**
+ * Composes {@link Artifact} and {@link Metadata} relative paths to be used in
+ * {@link org.eclipse.aether.repository.LocalRepositoryManager}.
+ *
+ * @since TBD
+ */
+public interface ArtifactPathComposer
+{
+    String getPathForArtifact( Artifact artifact, boolean local );
+
+    String getPathForMetadata( Metadata metadata, String repositoryKey );
+}
diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultArtifactPathComposer.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultArtifactPathComposer.java
new file mode 100644
index 00000000..3c5b4faf
--- /dev/null
+++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultArtifactPathComposer.java
@@ -0,0 +1,110 @@
+package org.eclipse.aether.internal.impl;
+
+/*
+ * 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.Named;
+import javax.inject.Singleton;
+
+import org.eclipse.aether.artifact.Artifact;
+import org.eclipse.aether.metadata.Metadata;
+
+/**
+ * Default implementation of {@link ArtifactPathComposer}.
+ *
+ * @since TBD
+ */
+@Singleton
+@Named
+public final class DefaultArtifactPathComposer implements ArtifactPathComposer
+{
+    @Override
+    public String getPathForArtifact( Artifact artifact, boolean local )
+    {
+        StringBuilder path = new StringBuilder( 128 );
+
+        path.append( artifact.getGroupId().replace( '.', '/' ) ).append( '/' );
+
+        path.append( artifact.getArtifactId() ).append( '/' );
+
+        path.append( artifact.getBaseVersion() ).append( '/' );
+
+        path.append( artifact.getArtifactId() ).append( '-' );
+        if ( local )
+        {
+            path.append( artifact.getBaseVersion() );
+        }
+        else
+        {
+            path.append( artifact.getVersion() );
+        }
+
+        if ( artifact.getClassifier().length() > 0 )
+        {
+            path.append( '-' ).append( artifact.getClassifier() );
+        }
+
+        if ( artifact.getExtension().length() > 0 )
+        {
+            path.append( '.' ).append( artifact.getExtension() );
+        }
+
+        return path.toString();
+    }
+
+    @Override
+    public String getPathForMetadata( Metadata metadata, String repositoryKey )
+    {
+        StringBuilder path = new StringBuilder( 128 );
+
+        if ( metadata.getGroupId().length() > 0 )
+        {
+            path.append( metadata.getGroupId().replace( '.', '/' ) ).append( '/' );
+
+            if ( metadata.getArtifactId().length() > 0 )
+            {
+                path.append( metadata.getArtifactId() ).append( '/' );
+
+                if ( metadata.getVersion().length() > 0 )
+                {
+                    path.append( metadata.getVersion() ).append( '/' );
+                }
+            }
+        }
+
+        path.append( insertRepositoryKey( metadata.getType(), repositoryKey ) );
+
+        return path.toString();
+    }
+
+    private String insertRepositoryKey( String filename, String repositoryKey )
+    {
+        String result;
+        int idx = filename.indexOf( '.' );
+        if ( idx < 0 )
+        {
+            result = filename + '-' + repositoryKey;
+        }
+        else
+        {
+            result = filename.substring( 0, idx ) + '-' + repositoryKey + filename.substring( idx );
+        }
+        return result;
+    }
+}
diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/EnhancedLocalRepositoryManager.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/EnhancedLocalRepositoryManager.java
index 65da5321..13110db6 100644
--- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/EnhancedLocalRepositoryManager.java
+++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/EnhancedLocalRepositoryManager.java
@@ -68,10 +68,11 @@ class EnhancedLocalRepositoryManager
     private final TrackingFileManager trackingFileManager;
 
     EnhancedLocalRepositoryManager( File basedir,
+                                    ArtifactPathComposer artifactPathComposer,
                                     RepositorySystemSession session,
                                     TrackingFileManager trackingFileManager )
     {
-        super( basedir, "enhanced" );
+        super( basedir, "enhanced", artifactPathComposer );
         String filename = ConfigUtils.getString( session, "", "aether.enhancedLocalRepository.trackingFilename" );
         if ( filename.isEmpty() || filename.contains( "/" ) || filename.contains( "\\" )
             || filename.contains( ".." ) )
diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/EnhancedLocalRepositoryManagerFactory.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/EnhancedLocalRepositoryManagerFactory.java
index d5d64b1c..ab6ce00d 100644
--- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/EnhancedLocalRepositoryManagerFactory.java
+++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/EnhancedLocalRepositoryManagerFactory.java
@@ -19,8 +19,6 @@ package org.eclipse.aether.internal.impl;
  * under the License.
  */
 
-import java.util.Objects;
-
 import javax.inject.Inject;
 import javax.inject.Named;
 import javax.inject.Singleton;
@@ -33,6 +31,8 @@ import org.eclipse.aether.spi.localrepo.LocalRepositoryManagerFactory;
 import org.eclipse.aether.spi.locator.Service;
 import org.eclipse.aether.spi.locator.ServiceLocator;
 
+import static java.util.Objects.requireNonNull;
+
 /**
  * Creates enhanced local repository managers for repository types {@code "default"} or {@code "" (automatic)}. Enhanced
  * local repository manager is built upon the classical Maven 2.0 local repository structure but additionally keeps
@@ -47,6 +47,8 @@ public class EnhancedLocalRepositoryManagerFactory
 {
     private float priority = 10.0f;
 
+    private ArtifactPathComposer artifactPathComposer;
+
     private TrackingFileManager trackingFileManager;
 
     public EnhancedLocalRepositoryManagerFactory()
@@ -55,26 +57,32 @@ public class EnhancedLocalRepositoryManagerFactory
     }
 
     @Inject
-    public EnhancedLocalRepositoryManagerFactory( final TrackingFileManager trackingFileManager )
+    public EnhancedLocalRepositoryManagerFactory( final ArtifactPathComposer artifactPathComposer,
+                                                  final TrackingFileManager trackingFileManager )
     {
-        this.trackingFileManager = Objects.requireNonNull( trackingFileManager );
+        this.artifactPathComposer = requireNonNull( artifactPathComposer );
+        this.trackingFileManager = requireNonNull( trackingFileManager );
     }
 
     @Override
     public void initService( final ServiceLocator locator )
     {
-        this.trackingFileManager = Objects.requireNonNull( locator.getService( TrackingFileManager.class ) );
+        this.artifactPathComposer = requireNonNull( locator.getService( ArtifactPathComposer.class ) );
+        this.trackingFileManager = requireNonNull( locator.getService( TrackingFileManager.class ) );
     }
 
+    @Override
     public LocalRepositoryManager newInstance( RepositorySystemSession session, LocalRepository repository )
         throws NoLocalRepositoryManagerException
     {
-        Objects.requireNonNull( session, "session cannot be null" );
-        Objects.requireNonNull( repository, "repository cannot be null" );
+        requireNonNull( session, "session cannot be null" );
+        requireNonNull( repository, "repository cannot be null" );
 
         if ( "".equals( repository.getContentType() ) || "default".equals( repository.getContentType() ) )
         {
-            return new EnhancedLocalRepositoryManager( repository.getBasedir(), session, trackingFileManager );
+            return new EnhancedLocalRepositoryManager(
+                    repository.getBasedir(), artifactPathComposer, session, trackingFileManager
+            );
         }
         else
         {
@@ -82,6 +90,7 @@ public class EnhancedLocalRepositoryManagerFactory
         }
     }
 
+    @Override
     public float getPriority()
     {
         return priority;
diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/FileProvidedChecksumsSource.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/FileProvidedChecksumsSource.java
index 2289fa56..f3bb7f8e 100644
--- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/FileProvidedChecksumsSource.java
+++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/FileProvidedChecksumsSource.java
@@ -32,7 +32,6 @@ import org.slf4j.LoggerFactory;
 import javax.inject.Inject;
 import javax.inject.Named;
 import javax.inject.Singleton;
-import java.io.File;
 import java.io.IOException;
 import java.net.URI;
 import java.nio.file.Files;
@@ -68,14 +67,13 @@ public final class FileProvidedChecksumsSource
 
     private final FileProcessor fileProcessor;
 
-    private final SimpleLocalRepositoryManager simpleLocalRepositoryManager;
+    private final ArtifactPathComposer artifactPathComposer;
 
     @Inject
-    public FileProvidedChecksumsSource( FileProcessor fileProcessor )
+    public FileProvidedChecksumsSource( FileProcessor fileProcessor, ArtifactPathComposer artifactPathComposer )
     {
         this.fileProcessor = requireNonNull( fileProcessor );
-        // we really needs just "local layout" from it (relative paths), so baseDir here is irrelevant
-        this.simpleLocalRepositoryManager = new SimpleLocalRepositoryManager( new File( "" ) );
+        this.artifactPathComposer = requireNonNull( artifactPathComposer );
     }
 
     @Override
@@ -92,7 +90,7 @@ public final class FileProvidedChecksumsSource
         for ( ChecksumAlgorithmFactory checksumAlgorithmFactory : checksumAlgorithmFactories )
         {
             checksumFilePaths.add( new ChecksumFilePath(
-                    simpleLocalRepositoryManager.getPathForArtifact( transfer.getArtifact(), false ) + '.'
+                    artifactPathComposer.getPathForArtifact( transfer.getArtifact(), false ) + '.'
                     + checksumAlgorithmFactory.getFileExtension(), checksumAlgorithmFactory ) );
         }
         return getProvidedChecksums( baseDir, checksumFilePaths, ArtifactIdUtils.toId( transfer.getArtifact() ) );
diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/SimpleLocalRepositoryManager.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/SimpleLocalRepositoryManager.java
index 9023d17a..c208e53c 100644
--- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/SimpleLocalRepositoryManager.java
+++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/SimpleLocalRepositoryManager.java
@@ -46,66 +46,34 @@ class SimpleLocalRepositoryManager
 
     private final LocalRepository repository;
 
-    SimpleLocalRepositoryManager( File basedir )
-    {
-        this( basedir, "simple" );
-    }
-
-    SimpleLocalRepositoryManager( String basedir )
-    {
-        this( ( basedir != null ) ? new File( basedir ) : null, "simple" );
-    }
+    private final ArtifactPathComposer artifactPathComposer;
 
-    SimpleLocalRepositoryManager( File basedir, String type )
+    SimpleLocalRepositoryManager( File basedir, String type, ArtifactPathComposer artifactPathComposer )
     {
         requireNonNull( basedir, "base directory cannot be null" );
         repository = new LocalRepository( basedir.getAbsoluteFile(), type );
+        this.artifactPathComposer = requireNonNull( artifactPathComposer );
     }
 
+    @Override
     public LocalRepository getRepository()
     {
         return repository;
     }
 
-    String getPathForArtifact( Artifact artifact, boolean local )
+    protected String getPathForArtifact( Artifact artifact, boolean local )
     {
-        StringBuilder path = new StringBuilder( 128 );
-
-        path.append( artifact.getGroupId().replace( '.', '/' ) ).append( '/' );
-
-        path.append( artifact.getArtifactId() ).append( '/' );
-
-        path.append( artifact.getBaseVersion() ).append( '/' );
-
-        path.append( artifact.getArtifactId() ).append( '-' );
-        if ( local )
-        {
-            path.append( artifact.getBaseVersion() );
-        }
-        else
-        {
-            path.append( artifact.getVersion() );
-        }
-
-        if ( artifact.getClassifier().length() > 0 )
-        {
-            path.append( '-' ).append( artifact.getClassifier() );
-        }
-
-        if ( artifact.getExtension().length() > 0 )
-        {
-            path.append( '.' ).append( artifact.getExtension() );
-        }
-
-        return path.toString();
+        return artifactPathComposer.getPathForArtifact( artifact, local );
     }
 
+    @Override
     public String getPathForLocalArtifact( Artifact artifact )
     {
         requireNonNull( artifact, "artifact cannot be null" );
         return getPathForArtifact( artifact, true );
     }
 
+    @Override
     public String getPathForRemoteArtifact( Artifact artifact, RemoteRepository repository, String context )
     {
         requireNonNull( artifact, "artifact cannot be null" );
@@ -113,20 +81,22 @@ class SimpleLocalRepositoryManager
         return getPathForArtifact( artifact, false );
     }
 
+    @Override
     public String getPathForLocalMetadata( Metadata metadata )
     {
         requireNonNull( metadata, "metadata cannot be null" );
-        return getPath( metadata, "local" );
+        return artifactPathComposer.getPathForMetadata( metadata, "local" );
     }
 
+    @Override
     public String getPathForRemoteMetadata( Metadata metadata, RemoteRepository repository, String context )
     {
         requireNonNull( metadata, "metadata cannot be null" );
         requireNonNull( repository, "repository cannot be null" );
-        return getPath( metadata, getRepositoryKey( repository, context ) );
+        return artifactPathComposer.getPathForMetadata( metadata, getRepositoryKey( repository, context ) );
     }
 
-    String getRepositoryKey( RemoteRepository repository, String context )
+    protected String getRepositoryKey( RemoteRepository repository, String context )
     {
         String key;
 
@@ -166,45 +136,7 @@ class SimpleLocalRepositoryManager
         return key;
     }
 
-    private String getPath( Metadata metadata, String repositoryKey )
-    {
-        StringBuilder path = new StringBuilder( 128 );
-
-        if ( metadata.getGroupId().length() > 0 )
-        {
-            path.append( metadata.getGroupId().replace( '.', '/' ) ).append( '/' );
-
-            if ( metadata.getArtifactId().length() > 0 )
-            {
-                path.append( metadata.getArtifactId() ).append( '/' );
-
-                if ( metadata.getVersion().length() > 0 )
-                {
-                    path.append( metadata.getVersion() ).append( '/' );
-                }
-            }
-        }
-
-        path.append( insertRepositoryKey( metadata.getType(), repositoryKey ) );
-
-        return path.toString();
-    }
-
-    private String insertRepositoryKey( String filename, String repositoryKey )
-    {
-        String result;
-        int idx = filename.indexOf( '.' );
-        if ( idx < 0 )
-        {
-            result = filename + '-' + repositoryKey;
-        }
-        else
-        {
-            result = filename.substring( 0, idx ) + '-' + repositoryKey + filename.substring( idx );
-        }
-        return result;
-    }
-
+    @Override
     public LocalArtifactResult find( RepositorySystemSession session, LocalArtifactRequest request )
     {
         requireNonNull( session, "session cannot be null" );
@@ -222,6 +154,7 @@ class SimpleLocalRepositoryManager
         return result;
     }
 
+    @Override
     public void add( RepositorySystemSession session, LocalArtifactRegistration request )
     {
         requireNonNull( session, "session cannot be null" );
@@ -230,11 +163,6 @@ class SimpleLocalRepositoryManager
     }
 
     @Override
-    public String toString()
-    {
-        return String.valueOf( getRepository() );
-    }
-
     public LocalMetadataResult find( RepositorySystemSession session, LocalMetadataRequest request )
     {
         requireNonNull( session, "session cannot be null" );
@@ -265,6 +193,7 @@ class SimpleLocalRepositoryManager
         return result;
     }
 
+    @Override
     public void add( RepositorySystemSession session, LocalMetadataRegistration request )
     {
         requireNonNull( session, "session cannot be null" );
@@ -272,4 +201,9 @@ class SimpleLocalRepositoryManager
         // noop
     }
 
+    @Override
+    public String toString()
+    {
+        return String.valueOf( getRepository() );
+    }
 }
diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/SimpleLocalRepositoryManagerFactory.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/SimpleLocalRepositoryManagerFactory.java
index 6903e4ce..d62301f5 100644
--- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/SimpleLocalRepositoryManagerFactory.java
+++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/SimpleLocalRepositoryManagerFactory.java
@@ -19,6 +19,7 @@ package org.eclipse.aether.internal.impl;
  * under the License.
  */
 
+import javax.inject.Inject;
 import javax.inject.Named;
 import javax.inject.Singleton;
 
@@ -29,6 +30,10 @@ import org.eclipse.aether.repository.LocalRepository;
 import org.eclipse.aether.repository.LocalRepositoryManager;
 import org.eclipse.aether.repository.NoLocalRepositoryManagerException;
 import org.eclipse.aether.spi.localrepo.LocalRepositoryManagerFactory;
+import org.eclipse.aether.spi.locator.Service;
+import org.eclipse.aether.spi.locator.ServiceLocator;
+
+import static java.util.Objects.requireNonNull;
 
 /**
  * Creates local repository managers for repository type {@code "simple"}.
@@ -36,24 +41,39 @@ import org.eclipse.aether.spi.localrepo.LocalRepositoryManagerFactory;
 @Singleton
 @Named( "simple" )
 public class SimpleLocalRepositoryManagerFactory
-    implements LocalRepositoryManagerFactory
+    implements LocalRepositoryManagerFactory, Service
 {
     private float priority;
 
+    private ArtifactPathComposer artifactPathComposer;
+
     public SimpleLocalRepositoryManagerFactory()
     {
         // enable no-arg constructor
     }
 
+    @Inject
+    public SimpleLocalRepositoryManagerFactory( final ArtifactPathComposer artifactPathComposer )
+    {
+        this.artifactPathComposer = requireNonNull( artifactPathComposer );
+    }
+
+    @Override
+    public void initService( final ServiceLocator locator )
+    {
+        this.artifactPathComposer = Objects.requireNonNull( locator.getService( ArtifactPathComposer.class ) );
+    }
+
+    @Override
     public LocalRepositoryManager newInstance( RepositorySystemSession session, LocalRepository repository )
         throws NoLocalRepositoryManagerException
     {
-        Objects.requireNonNull( session, "session cannot be null" );
-        Objects.requireNonNull( repository, "repository cannot be null" );
+        requireNonNull( session, "session cannot be null" );
+        requireNonNull( repository, "repository cannot be null" );
 
         if ( "".equals( repository.getContentType() ) || "simple".equals( repository.getContentType() ) )
         {
-            return new SimpleLocalRepositoryManager( repository.getBasedir() );
+            return new SimpleLocalRepositoryManager( repository.getBasedir(), "simple", artifactPathComposer );
         }
         else
         {
@@ -61,6 +81,7 @@ public class SimpleLocalRepositoryManagerFactory
         }
     }
 
+    @Override
     public float getPriority()
     {
         return priority;
diff --git a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/EnhancedLocalRepositoryManagerTest.java b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/EnhancedLocalRepositoryManagerTest.java
index 729b0123..f4da7edc 100644
--- a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/EnhancedLocalRepositoryManagerTest.java
+++ b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/EnhancedLocalRepositoryManagerTest.java
@@ -99,7 +99,7 @@ public class EnhancedLocalRepositoryManagerTest
         basedir = TestFileUtils.createTempDir( "enhanced-repo" );
         session = TestUtils.newSession();
         trackingFileManager = new DefaultTrackingFileManager();
-        manager = new EnhancedLocalRepositoryManager( basedir, session, trackingFileManager );
+        manager = new EnhancedLocalRepositoryManager( basedir, new DefaultArtifactPathComposer(), session, trackingFileManager );
 
         artifactFile = new File( basedir, manager.getPathForLocalArtifact( artifact ) );
     }
diff --git a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/FileProvidedChecksumsSourceTest.java b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/FileProvidedChecksumsSourceTest.java
index e062a32b..14ec97cd 100644
--- a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/FileProvidedChecksumsSourceTest.java
+++ b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/FileProvidedChecksumsSourceTest.java
@@ -57,7 +57,7 @@ public class FileProvidedChecksumsSourceTest
     RemoteRepository repository = new RemoteRepository.Builder("test", "default", "https://irrelevant.com").build();
     session = TestUtils.newSession();
     repositoryLayout = new Maven2RepositoryLayoutFactory().newInstance(session, repository);
-    subject = new FileProvidedChecksumsSource(new TestFileProcessor() );
+    subject = new FileProvidedChecksumsSource(new TestFileProcessor(), new DefaultArtifactPathComposer() );
 
     // populate local repository
     Path baseDir = session.getLocalRepository().getBasedir().toPath().resolve( FileProvidedChecksumsSource.LOCAL_REPO_PREFIX);
diff --git a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/SimpleLocalRepositoryManagerTest.java b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/SimpleLocalRepositoryManagerTest.java
index 9a985261..17268b42 100644
--- a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/SimpleLocalRepositoryManagerTest.java
+++ b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/SimpleLocalRepositoryManagerTest.java
@@ -27,7 +27,6 @@ import java.io.IOException;
 import org.eclipse.aether.RepositorySystemSession;
 import org.eclipse.aether.artifact.Artifact;
 import org.eclipse.aether.artifact.DefaultArtifact;
-import org.eclipse.aether.internal.impl.SimpleLocalRepositoryManager;
 import org.eclipse.aether.internal.test.util.TestFileUtils;
 import org.eclipse.aether.internal.test.util.TestUtils;
 import org.eclipse.aether.repository.LocalArtifactRequest;
@@ -53,7 +52,7 @@ public class SimpleLocalRepositoryManagerTest
         throws IOException
     {
         basedir = TestFileUtils.createTempDir( "simple-repo" );
-        manager = new SimpleLocalRepositoryManager( basedir );
+        manager = new SimpleLocalRepositoryManager( basedir, "simple", new DefaultArtifactPathComposer() );
         session = TestUtils.newSession();
     }