From 814930770272085dbeca05840149604fd523eb3e Mon Sep 17 00:00:00 2001 From: Slawomir Jaranowski Date: Wed, 15 Feb 2023 22:45:21 +0100 Subject: [PATCH] [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 -- ...ultLocalPathPrefixComposerFactoryTest.java | 18 +- .../EnhancedLocalRepositoryManagerTest.java | 5 +- ...hancedSplitLocalRepositoryManagerTest.java | 9 +- 8 files changed, 204 insertions(+), 27 deletions(-) create mode 100644 maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/EnhancedLocalRepositoryConfig.java 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 7fce1a042..f1ba820de 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 @@ 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 000000000..a9114fff5 --- /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 98fcddb55..db93fdf99 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.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 LocalRepositoryManager newInstance( RepositorySystemSession session, Loca 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 LocalRepositoryManager newInstance( RepositorySystemSession session, Loca 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 2ef76937e..41efb6c20 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 eff360ebb..f13015004 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 @@ */ 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 2728c5bbb..3ce4e1df0 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 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 void defaultConfigNoSplitAllNulls() 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 void splitEnabled() 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 void saneConfig() 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 f69d8bd75..78426048e 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 @@ */ 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 @@ protected EnhancedLocalRepositoryManager getManager() 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 540364604..b2017fedb 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.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 ) ); }