You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by sj...@apache.org on 2023/02/15 21:45:41 UTC

[maven-resolver] 01/01: [MRESOLVER-310] Preserve configuration of Enhanced LRM in local repo

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

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

commit 814930770272085dbeca05840149604fd523eb3e
Author: Slawomir Jaranowski <s....@gmail.com>
AuthorDate: Wed Feb 15 22:45:21 2023 +0100

    [MRESOLVER-310] Preserve configuration of Enhanced LRM in local repo
---
 .../DefaultLocalPathPrefixComposerFactory.java     |   5 +-
 .../impl/EnhancedLocalRepositoryConfig.java        | 170 +++++++++++++++++++++
 .../EnhancedLocalRepositoryManagerFactory.java     |   8 +-
 .../impl/LocalPathPrefixComposerFactory.java       |   6 +-
 .../LocalPathPrefixComposerFactorySupport.java     |  10 --
 .../DefaultLocalPathPrefixComposerFactoryTest.java |  18 ++-
 .../impl/EnhancedLocalRepositoryManagerTest.java   |   5 +-
 .../EnhancedSplitLocalRepositoryManagerTest.java   |   9 +-
 8 files changed, 204 insertions(+), 27 deletions(-)

diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultLocalPathPrefixComposerFactory.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultLocalPathPrefixComposerFactory.java
index 7fce1a04..f1ba820d 100644
--- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultLocalPathPrefixComposerFactory.java
+++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultLocalPathPrefixComposerFactory.java
@@ -35,9 +35,10 @@ import org.eclipse.aether.RepositorySystemSession;
 public final class DefaultLocalPathPrefixComposerFactory extends LocalPathPrefixComposerFactorySupport
 {
     @Override
-    public LocalPathPrefixComposer createComposer( RepositorySystemSession session )
+    public LocalPathPrefixComposer createComposer( RepositorySystemSession session,
+                                                   EnhancedLocalRepositoryConfig repositoryConfig )
     {
-        return new DefaultLocalPathPrefixComposer( isSplit( session ), getLocalPrefix( session ),
+        return new DefaultLocalPathPrefixComposer( repositoryConfig.isSplit(), getLocalPrefix( session ),
                 isSplitLocal( session ), getRemotePrefix( session ), isSplitRemote( session ),
                 isSplitRemoteRepository( session ), isSplitRemoteRepositoryLast( session ),
                 getReleasesPrefix( session ), getSnapshotsPrefix( session ) );
diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/EnhancedLocalRepositoryConfig.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/EnhancedLocalRepositoryConfig.java
new file mode 100644
index 00000000..a9114fff
--- /dev/null
+++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/EnhancedLocalRepositoryConfig.java
@@ -0,0 +1,170 @@
+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 java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UncheckedIOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Properties;
+
+import org.apache.commons.lang3.StringUtils;
+import org.eclipse.aether.RepositorySystemSession;
+import org.eclipse.aether.util.ConfigUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static java.nio.file.StandardOpenOption.CREATE;
+import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;
+import static java.nio.file.StandardOpenOption.WRITE;
+
+/**
+ * Enhanced Local Repository configuration holder.
+ */
+class EnhancedLocalRepositoryConfig
+{
+    private static final Logger LOGGER = LoggerFactory.getLogger( EnhancedLocalRepositoryConfig.class );
+
+    private static final String CONFIG_PROP_TRACKING_FILENAME = "aether.enhancedLocalRepository.trackingFilename";
+
+    private static final String DEFAULT_TRACKING_FILENAME = "_remote.repositories";
+
+    protected static final String CONF_PROP_SPLIT = "aether.enhancedLocalRepository.split";
+
+    protected static final String DEFAULT_SPLIT = "false";
+
+    private Properties config;
+
+    EnhancedLocalRepositoryConfig( RepositorySystemSession session, File basedir )
+    {
+        try
+        {
+            config = loadConfiguration( basedir );
+            int configHash0 = configurationHash( config );
+            populateConfiguration( config, session );
+            int configHash1 = configurationHash( config );
+
+            if ( configHash0 != configHash1 )
+            {
+                storeConfig( config, basedir );
+            }
+            else
+            {
+                LOGGER.debug( "Use saved ELRM configuration" );
+            }
+        }
+        catch ( IOException e )
+        {
+            throw new UncheckedIOException( e );
+        }
+    }
+
+    private static void populateConfiguration( Properties configurations, RepositorySystemSession session )
+    {
+        populateConfiguration( configurations, session, CONFIG_PROP_TRACKING_FILENAME, DEFAULT_TRACKING_FILENAME );
+        populateConfiguration( configurations, session, CONF_PROP_SPLIT, DEFAULT_SPLIT );
+    }
+
+    private static void populateConfiguration( Properties configurations, RepositorySystemSession session, String key,
+                                               String defaultValue )
+    {
+        String valueConf = configurations.getProperty( key );
+        String valueSession = ConfigUtils.getString( session, null, key );
+
+        if ( StringUtils.isNotBlank( valueConf ) && StringUtils.isNotBlank( valueSession )
+            && !valueConf.equals( valueSession ) )
+        {
+            LOGGER.debug( "New config {}={} for ELRM will not be used", key, valueSession );
+        }
+
+        if ( StringUtils.isBlank( valueConf ) && StringUtils.isNotBlank( valueSession ) )
+        {
+            configurations.setProperty( key, valueSession );
+        }
+        else if ( StringUtils.isBlank( valueConf ) && StringUtils.isBlank( valueSession ) )
+        {
+            configurations.setProperty( key, defaultValue );
+        }
+    }
+
+    private static int configurationHash( Properties configurations )
+    {
+        return configurations.entrySet().stream()
+            .mapToInt( e -> Objects.hash( e.getKey(), e.getValue() ) )
+            .reduce( 1, ( i1, i2 ) -> 31 * i1 * i2 );
+    }
+
+    private static Properties loadConfiguration( File basedir ) throws IOException
+    {
+        Properties props = new Properties();
+        Path configPath = Optional.ofNullable( basedir )
+            .map( File::toPath )
+            .map( p -> p.resolve( "elrm.properties" ) )
+            .filter( Files::isReadable )
+            .orElse( null );
+
+        if ( configPath != null )
+        {
+            try ( InputStream inputStream = Files.newInputStream( configPath ) )
+            {
+                props.load( inputStream );
+            }
+        }
+        return props;
+    }
+
+    private void storeConfig( Properties configurations, File basedir ) throws IOException
+    {
+        Path configPath = Optional.ofNullable( basedir )
+            .map( File::toPath )
+            .map( p -> p.resolve( "elrm.properties" ) )
+            .orElse( null );
+
+        if ( configPath != null )
+        {
+            Path parent = configPath.getParent();
+            if ( parent != null )
+            {
+                Files.createDirectories( parent );
+            }
+
+            LOGGER.debug( "Create local repository configuration: {}", configPath );
+            try ( OutputStream outputStream = Files.newOutputStream( configPath, WRITE, TRUNCATE_EXISTING, CREATE ) )
+            {
+                configurations.store( outputStream, "Enhanced Local Repository Configuration" );
+            }
+        }
+    }
+
+    public String getTrackingFilename()
+    {
+        return config.getProperty( CONFIG_PROP_TRACKING_FILENAME );
+    }
+
+    public boolean isSplit()
+    {
+        return Boolean.parseBoolean( config.getProperty( CONF_PROP_SPLIT ) );
+    }
+}
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 98fcddb5..db93fdf9 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
@@ -30,7 +30,6 @@ 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 org.eclipse.aether.util.ConfigUtils;
 
 import static java.util.Objects.requireNonNull;
 
@@ -88,7 +87,10 @@ public class EnhancedLocalRepositoryManagerFactory
         requireNonNull( session, "session cannot be null" );
         requireNonNull( repository, "repository cannot be null" );
 
-        String trackingFilename = ConfigUtils.getString( session, "", CONFIG_PROP_TRACKING_FILENAME );
+        EnhancedLocalRepositoryConfig repositoryConfig =
+            new EnhancedLocalRepositoryConfig( session, repository.getBasedir() );
+
+        String trackingFilename = repositoryConfig.getTrackingFilename();
         if ( trackingFilename.isEmpty() || trackingFilename.contains( "/" ) || trackingFilename.contains( "\\" )
                 || trackingFilename.contains( ".." ) )
         {
@@ -102,7 +104,7 @@ public class EnhancedLocalRepositoryManagerFactory
                     localPathComposer,
                     trackingFilename,
                     trackingFileManager,
-                    localPathPrefixComposerFactory.createComposer( session )
+                    localPathPrefixComposerFactory.createComposer( session, repositoryConfig )
             );
         }
         else
diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/LocalPathPrefixComposerFactory.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/LocalPathPrefixComposerFactory.java
index 2ef76937..41efb6c2 100644
--- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/LocalPathPrefixComposerFactory.java
+++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/LocalPathPrefixComposerFactory.java
@@ -31,8 +31,10 @@ public interface LocalPathPrefixComposerFactory
     /**
      * Creates {@link LocalPathPrefixComposer} instance out of whatever configuration it finds in passed in session.
      *
-     * @param session The repository session, never {@code null}.
+     * @param session          The repository session, never {@code null}.
+     * @param repositoryConfig The locla repository configuration
      * @return The created instance, never {@code null}.
      */
-    LocalPathPrefixComposer createComposer( RepositorySystemSession session );
+    LocalPathPrefixComposer createComposer( RepositorySystemSession session,
+                                            EnhancedLocalRepositoryConfig repositoryConfig );
 }
diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/LocalPathPrefixComposerFactorySupport.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/LocalPathPrefixComposerFactorySupport.java
index eff360eb..f1301500 100644
--- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/LocalPathPrefixComposerFactorySupport.java
+++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/LocalPathPrefixComposerFactorySupport.java
@@ -38,10 +38,6 @@ import org.eclipse.aether.util.ConfigUtils;
  */
 public abstract class LocalPathPrefixComposerFactorySupport implements LocalPathPrefixComposerFactory
 {
-    protected static final String CONF_PROP_SPLIT = "aether.enhancedLocalRepository.split";
-
-    protected static final boolean DEFAULT_SPLIT = false;
-
     protected static final String CONF_PROP_LOCAL_PREFIX = "aether.enhancedLocalRepository.localPrefix";
 
     protected static final String DEFAULT_LOCAL_PREFIX = "installed";
@@ -76,12 +72,6 @@ public abstract class LocalPathPrefixComposerFactorySupport implements LocalPath
 
     protected static final String DEFAULT_SNAPSHOTS_PREFIX = "snapshots";
 
-    protected boolean isSplit( RepositorySystemSession session )
-    {
-        return ConfigUtils.getBoolean(
-                session, DEFAULT_SPLIT, CONF_PROP_SPLIT );
-    }
-
     protected String getLocalPrefix( RepositorySystemSession session )
     {
         return ConfigUtils.getString(
diff --git a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/DefaultLocalPathPrefixComposerFactoryTest.java b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/DefaultLocalPathPrefixComposerFactoryTest.java
index 2728c5bb..3ce4e1df 100644
--- a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/DefaultLocalPathPrefixComposerFactoryTest.java
+++ b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/DefaultLocalPathPrefixComposerFactoryTest.java
@@ -31,6 +31,8 @@ import org.junit.Test;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 /**
  * UT for {@link DefaultLocalPathPrefixComposerFactory}.
@@ -51,13 +53,15 @@ public class DefaultLocalPathPrefixComposerFactoryTest
 
     private final RemoteRepository repository = new RemoteRepository.Builder( "my-repo", "default", "https://repo.maven.apache.org/maven2/" ).build();
 
+    private final EnhancedLocalRepositoryConfig repositoryConfig = mock( EnhancedLocalRepositoryConfig.class );
+
     @Test
     public void defaultConfigNoSplitAllNulls()
     {
         DefaultRepositorySystemSession session = TestUtils.newSession();
 
         LocalPathPrefixComposerFactory factory = new DefaultLocalPathPrefixComposerFactory();
-        LocalPathPrefixComposer composer = factory.createComposer( session );
+        LocalPathPrefixComposer composer = factory.createComposer( session, repositoryConfig );
         assertNotNull( composer );
 
         String prefix;
@@ -78,10 +82,10 @@ public class DefaultLocalPathPrefixComposerFactoryTest
     public void splitEnabled()
     {
         DefaultRepositorySystemSession session = TestUtils.newSession();
-        session.setConfigProperty( "aether.enhancedLocalRepository.split", Boolean.TRUE.toString() );
+        when( repositoryConfig.isSplit() ).thenReturn( true );
 
         LocalPathPrefixComposerFactory factory = new DefaultLocalPathPrefixComposerFactory();
-        LocalPathPrefixComposer composer = factory.createComposer( session );
+        LocalPathPrefixComposer composer = factory.createComposer( session, repositoryConfig );
         assertNotNull( composer );
 
         String prefix;
@@ -106,12 +110,12 @@ public class DefaultLocalPathPrefixComposerFactoryTest
     public void saneConfig()
     {
         DefaultRepositorySystemSession session = TestUtils.newSession();
-        session.setConfigProperty( "aether.enhancedLocalRepository.split", Boolean.TRUE.toString() );
+        when( repositoryConfig.isSplit() ).thenReturn( true );
         session.setConfigProperty( "aether.enhancedLocalRepository.splitLocal", Boolean.TRUE.toString() );
         session.setConfigProperty( "aether.enhancedLocalRepository.splitRemoteRepository", Boolean.TRUE.toString() );
 
         LocalPathPrefixComposerFactory factory = new DefaultLocalPathPrefixComposerFactory();
-        LocalPathPrefixComposer composer = factory.createComposer( session );
+        LocalPathPrefixComposer composer = factory.createComposer( session, repositoryConfig );
         assertNotNull( composer );
 
         String prefix;
@@ -168,13 +172,13 @@ public class DefaultLocalPathPrefixComposerFactoryTest
     public void fullConfig()
     {
         DefaultRepositorySystemSession session = TestUtils.newSession();
-        session.setConfigProperty( "aether.enhancedLocalRepository.split", Boolean.TRUE.toString() );
+        when( repositoryConfig.isSplit() ).thenReturn( true );
         session.setConfigProperty( "aether.enhancedLocalRepository.splitLocal", Boolean.TRUE.toString() );
         session.setConfigProperty( "aether.enhancedLocalRepository.splitRemote", Boolean.TRUE.toString() );
         session.setConfigProperty( "aether.enhancedLocalRepository.splitRemoteRepository", Boolean.TRUE.toString() );
 
         LocalPathPrefixComposerFactory factory = new DefaultLocalPathPrefixComposerFactory();
-        LocalPathPrefixComposer composer = factory.createComposer( session );
+        LocalPathPrefixComposer composer = factory.createComposer( session, repositoryConfig );
         assertNotNull( composer );
 
         String prefix;
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 f69d8bd7..78426048 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
@@ -20,6 +20,7 @@ package org.eclipse.aether.internal.impl;
  */
 
 import static org.junit.Assert.*;
+import static org.mockito.Mockito.mock;
 
 import java.io.File;
 import java.io.IOException;
@@ -71,6 +72,8 @@ public class EnhancedLocalRepositoryManagerTest
 
     private Metadata noVerMetadata;
 
+    private final EnhancedLocalRepositoryConfig repositoryConfig = mock( EnhancedLocalRepositoryConfig.class );
+
     @Before
     public void setup()
         throws Exception
@@ -110,7 +113,7 @@ public class EnhancedLocalRepositoryManagerTest
                 new DefaultLocalPathComposer(),
                 "_remote.repositories",
                 trackingFileManager,
-                new DefaultLocalPathPrefixComposerFactory().createComposer( session )
+                new DefaultLocalPathPrefixComposerFactory().createComposer( session, repositoryConfig )
         );
     }
 
diff --git a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/EnhancedSplitLocalRepositoryManagerTest.java b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/EnhancedSplitLocalRepositoryManagerTest.java
index 54036460..b2017fed 100644
--- a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/EnhancedSplitLocalRepositoryManagerTest.java
+++ b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/EnhancedSplitLocalRepositoryManagerTest.java
@@ -25,20 +25,25 @@ import org.eclipse.aether.repository.RemoteRepository;
 import org.junit.Test;
 
 import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 public class EnhancedSplitLocalRepositoryManagerTest extends EnhancedLocalRepositoryManagerTest
 {
 
+    private final EnhancedLocalRepositoryConfig repositoryConfig = mock( EnhancedLocalRepositoryConfig.class );
+
     @Override
     protected EnhancedLocalRepositoryManager getManager()
     {
-        session.setConfigProperty( "aether.enhancedLocalRepository.split", Boolean.TRUE.toString() );
+        when( repositoryConfig.isSplit() ).thenReturn( true );
+
         return new EnhancedLocalRepositoryManager(
                 basedir,
                 new DefaultLocalPathComposer(),
                 "_remote.repositories",
                 trackingFileManager,
-                new DefaultLocalPathPrefixComposerFactory().createComposer( session )
+                new DefaultLocalPathPrefixComposerFactory().createComposer( session, repositoryConfig )
         );
     }