From 5e743fb2993fa88e89216c7e3901f282d38bd9a4 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 18 Jun 2015 10:59:39 +0100 Subject: [PATCH] Fully honour local repository location configured in settings.xml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, DefaultRepositorySystemSessionAutoConfiguration would read the local repository configuration from settings.xml, but did not perform any property interpolation. This would leave placeholders such as ${user.home} as-is and result in the use of the wrong location. To address this, the code that reads settings.xml has been updated to provide the current System properties as a property interpolation source. RepositoryConfigurationFactory configures the local repository as a "remote" repository when the local repository location has been overridden. This allows spring grab to copy dependencies from the local repository into the grab output location (configured via the grape.root system property) rather than having to download them again. This logic did not consider the customization of the local repository location via settings.xml so the dependencies would be downloaded again. To address this, RepositoryConfigurationFactory has been updated to attempt to use the location configured in settings.xml, before falling back to the default location. The logic that reads settings.xml has deliberately been duplicated. It could have been extracted into a separate class, but this is only a temporary measure until gh-3275 is tackled. Duplication was deemed preferable to adding a new public class in 1.2.x that we’d then want to remove in 1.3. Closes gh-3274 --- .../RepositoryConfigurationFactory.java | 30 ++++- ...ositorySystemSessionAutoConfiguration.java | 10 +- ...ositorySystemSessionAutoConfiguration.java | 55 ++++++++ ...ositorySystemSessionAutoConfiguration.java | 1 + ...e.RepositorySystemSessionAutoConfiguration | 3 +- ...rySystemSessionAutoConfigurationTests.java | 122 ++++++++++++++++++ ...rySystemSessionAutoConfigurationTests.java | 45 ++++++- 7 files changed, 252 insertions(+), 14 deletions(-) create mode 100644 spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/grape/GrapeRootRepositorySystemSessionAutoConfiguration.java create mode 100644 spring-boot-cli/src/test/java/org/springframework/boot/cli/compiler/grape/GrapeRootRepositorySystemSessionAutoConfigurationTests.java diff --git a/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/RepositoryConfigurationFactory.java b/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/RepositoryConfigurationFactory.java index 97845f4f88..6d1458d3e5 100644 --- a/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/RepositoryConfigurationFactory.java +++ b/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/RepositoryConfigurationFactory.java @@ -21,6 +21,11 @@ import java.net.URI; import java.util.ArrayList; import java.util.List; +import org.apache.maven.settings.Settings; +import org.apache.maven.settings.building.DefaultSettingsBuilderFactory; +import org.apache.maven.settings.building.DefaultSettingsBuildingRequest; +import org.apache.maven.settings.building.SettingsBuildingException; +import org.apache.maven.settings.building.SettingsBuildingRequest; import org.springframework.boot.cli.compiler.grape.RepositoryConfiguration; import org.springframework.util.StringUtils; @@ -66,12 +71,35 @@ public final class RepositoryConfigurationFactory { public static void addDefaultCacheAsRespository( List repositoryConfiguration) { RepositoryConfiguration repository = new RepositoryConfiguration("local", - new File(getM2HomeDirectory(), "repository").toURI(), true); + getLocalRepositoryDirectory().toURI(), true); if (!repositoryConfiguration.contains(repository)) { repositoryConfiguration.add(0, repository); } } + private static File getLocalRepositoryDirectory() { + String localRepository = loadSettings().getLocalRepository(); + if (StringUtils.hasText(localRepository)) { + return new File(localRepository); + } + return new File(getM2HomeDirectory(), "repository"); + } + + private static Settings loadSettings() { + File settingsFile = new File(System.getProperty("user.home"), ".m2/settings.xml"); + SettingsBuildingRequest request = new DefaultSettingsBuildingRequest(); + request.setUserSettingsFile(settingsFile); + request.setSystemProperties(System.getProperties()); + try { + return new DefaultSettingsBuilderFactory().newInstance().build(request) + .getEffectiveSettings(); + } + catch (SettingsBuildingException ex) { + throw new IllegalStateException("Failed to build settings from " + + settingsFile, ex); + } + } + private static File getM2HomeDirectory() { String mavenRoot = System.getProperty("maven.home"); if (StringUtils.hasLength(mavenRoot)) { diff --git a/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/grape/DefaultRepositorySystemSessionAutoConfiguration.java b/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/grape/DefaultRepositorySystemSessionAutoConfiguration.java index 4b81cbdfd8..d1bfda16fb 100644 --- a/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/grape/DefaultRepositorySystemSessionAutoConfiguration.java +++ b/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/grape/DefaultRepositorySystemSessionAutoConfiguration.java @@ -57,15 +57,7 @@ public class DefaultRepositorySystemSessionAutoConfiguration implements } private File getM2RepoDirectory() { - return new File(getM2HomeDirectory(), "repository"); - } - - private File getM2HomeDirectory() { - String grapeRoot = System.getProperty("grape.root"); - if (StringUtils.hasLength(grapeRoot)) { - return new File(grapeRoot); - } - return getDefaultM2HomeDirectory(); + return new File(getDefaultM2HomeDirectory(), "repository"); } private File getDefaultM2HomeDirectory() { diff --git a/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/grape/GrapeRootRepositorySystemSessionAutoConfiguration.java b/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/grape/GrapeRootRepositorySystemSessionAutoConfiguration.java new file mode 100644 index 0000000000..0fbb818b76 --- /dev/null +++ b/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/grape/GrapeRootRepositorySystemSessionAutoConfiguration.java @@ -0,0 +1,55 @@ +/* + * Copyright 2012-2015 the original author or authors. + * + * Licensed 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. + */ + +package org.springframework.boot.cli.compiler.grape; + +import java.io.File; + +import org.eclipse.aether.DefaultRepositorySystemSession; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.repository.LocalRepository; +import org.eclipse.aether.repository.LocalRepositoryManager; +import org.springframework.util.StringUtils; + +/** + * Honours the configuration of {@code grape.root} by customizing the session's local + * repository location. + * + * @author Andy Wilkinson + * @since 1.2.5 + */ +public class GrapeRootRepositorySystemSessionAutoConfiguration implements + RepositorySystemSessionAutoConfiguration { + + @Override + public void apply(DefaultRepositorySystemSession session, + RepositorySystem repositorySystem) { + String grapeRoot = System.getProperty("grape.root"); + if (StringUtils.hasLength(grapeRoot)) { + configureLocalRepository(session, repositorySystem, grapeRoot); + } + } + + private void configureLocalRepository(DefaultRepositorySystemSession session, + RepositorySystem repositorySystem, String grapeRoot) { + File repositoryDir = new File(grapeRoot, "repository"); + LocalRepository localRepository = new LocalRepository(repositoryDir); + LocalRepositoryManager localRepositoryManager = repositorySystem + .newLocalRepositoryManager(session, localRepository); + session.setLocalRepositoryManager(localRepositoryManager); + } + +} diff --git a/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/grape/SettingsXmlRepositorySystemSessionAutoConfiguration.java b/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/grape/SettingsXmlRepositorySystemSessionAutoConfiguration.java index 8d6f95603d..895868b9ff 100644 --- a/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/grape/SettingsXmlRepositorySystemSessionAutoConfiguration.java +++ b/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/grape/SettingsXmlRepositorySystemSessionAutoConfiguration.java @@ -96,6 +96,7 @@ public class SettingsXmlRepositorySystemSessionAutoConfiguration implements File settingsFile = new File(this.homeDir, ".m2/settings.xml"); SettingsBuildingRequest request = new DefaultSettingsBuildingRequest(); request.setUserSettingsFile(settingsFile); + request.setSystemProperties(System.getProperties()); try { return new DefaultSettingsBuilderFactory().newInstance().build(request) .getEffectiveSettings(); diff --git a/spring-boot-cli/src/main/resources/META-INF/services/org.springframework.boot.cli.compiler.grape.RepositorySystemSessionAutoConfiguration b/spring-boot-cli/src/main/resources/META-INF/services/org.springframework.boot.cli.compiler.grape.RepositorySystemSessionAutoConfiguration index 6020bac3eb..cf394a7e18 100644 --- a/spring-boot-cli/src/main/resources/META-INF/services/org.springframework.boot.cli.compiler.grape.RepositorySystemSessionAutoConfiguration +++ b/spring-boot-cli/src/main/resources/META-INF/services/org.springframework.boot.cli.compiler.grape.RepositorySystemSessionAutoConfiguration @@ -1 +1,2 @@ -org.springframework.boot.cli.compiler.grape.SettingsXmlRepositorySystemSessionAutoConfiguration \ No newline at end of file +org.springframework.boot.cli.compiler.grape.SettingsXmlRepositorySystemSessionAutoConfiguration +org.springframework.boot.cli.compiler.grape.GrapeRootRepositorySystemSessionAutoConfiguration \ No newline at end of file diff --git a/spring-boot-cli/src/test/java/org/springframework/boot/cli/compiler/grape/GrapeRootRepositorySystemSessionAutoConfigurationTests.java b/spring-boot-cli/src/test/java/org/springframework/boot/cli/compiler/grape/GrapeRootRepositorySystemSessionAutoConfigurationTests.java new file mode 100644 index 0000000000..64fcad630e --- /dev/null +++ b/spring-boot-cli/src/test/java/org/springframework/boot/cli/compiler/grape/GrapeRootRepositorySystemSessionAutoConfigurationTests.java @@ -0,0 +1,122 @@ +/* + * Copyright 2012-2015 the original author or authors. + * + * Licensed 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. + */ + +package org.springframework.boot.cli.compiler.grape; + +import org.apache.maven.repository.internal.MavenRepositorySystemUtils; +import org.eclipse.aether.DefaultRepositorySystemSession; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.internal.impl.SimpleLocalRepositoryManagerFactory; +import org.eclipse.aether.repository.LocalRepository; +import org.eclipse.aether.repository.LocalRepositoryManager; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.stubbing.Answer; + +import static org.hamcrest.Matchers.endsWith; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.Matchers.nullValue; +import static org.junit.Assert.assertThat; +import static org.mockito.BDDMockito.given; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +/** + * Tests for {@link GrapeRootRepositorySystemSessionAutoConfiguration} + * + * @author Andy Wilkinson + */ +@RunWith(MockitoJUnitRunner.class) +public class GrapeRootRepositorySystemSessionAutoConfigurationTests { + + private DefaultRepositorySystemSession session = MavenRepositorySystemUtils + .newSession(); + + @Mock + private RepositorySystem repositorySystem; + + @Test + public void noLocalRepositoryWhenNoGrapeRoot() { + given( + this.repositorySystem.newLocalRepositoryManager(eq(this.session), + any(LocalRepository.class))).willAnswer( + new Answer() { + + @Override + public LocalRepositoryManager answer(InvocationOnMock invocation) + throws Throwable { + LocalRepository localRepository = invocation.getArgumentAt(1, + LocalRepository.class); + return new SimpleLocalRepositoryManagerFactory() + .newInstance( + GrapeRootRepositorySystemSessionAutoConfigurationTests.this.session, + localRepository); + } + }); + + new GrapeRootRepositorySystemSessionAutoConfiguration().apply(this.session, + this.repositorySystem); + + verify(this.repositorySystem, times(0)).newLocalRepositoryManager( + eq(this.session), any(LocalRepository.class)); + + assertThat(this.session.getLocalRepository(), is(nullValue())); + } + + @Test + public void grapeRootConfiguresLocalRepositoryLocation() { + given( + this.repositorySystem.newLocalRepositoryManager(eq(this.session), + any(LocalRepository.class))).willAnswer( + new LocalRepositoryManagerAnswer()); + + System.setProperty("grape.root", "foo"); + try { + new GrapeRootRepositorySystemSessionAutoConfiguration().apply(this.session, + this.repositorySystem); + } + finally { + System.clearProperty("grape.root"); + } + + verify(this.repositorySystem, times(1)).newLocalRepositoryManager( + eq(this.session), any(LocalRepository.class)); + + assertThat(this.session.getLocalRepository(), is(notNullValue())); + assertThat(this.session.getLocalRepository().getBasedir().getAbsolutePath(), + endsWith("/foo/repository")); + } + + private class LocalRepositoryManagerAnswer implements Answer { + @Override + public LocalRepositoryManager answer(InvocationOnMock invocation) + throws Throwable { + LocalRepository localRepository = invocation.getArgumentAt(1, + LocalRepository.class); + return new SimpleLocalRepositoryManagerFactory().newInstance( + GrapeRootRepositorySystemSessionAutoConfigurationTests.this.session, + localRepository); + } + + } + +} diff --git a/spring-boot-cli/src/test/java/org/springframework/boot/cli/compiler/grape/SettingsXmlRepositorySystemSessionAutoConfigurationTests.java b/spring-boot-cli/src/test/java/org/springframework/boot/cli/compiler/grape/SettingsXmlRepositorySystemSessionAutoConfigurationTests.java index 54d4571f7f..94db7c64f4 100644 --- a/spring-boot-cli/src/test/java/org/springframework/boot/cli/compiler/grape/SettingsXmlRepositorySystemSessionAutoConfigurationTests.java +++ b/spring-boot-cli/src/test/java/org/springframework/boot/cli/compiler/grape/SettingsXmlRepositorySystemSessionAutoConfigurationTests.java @@ -20,8 +20,10 @@ import org.apache.maven.repository.internal.MavenRepositorySystemUtils; import org.apache.maven.settings.building.SettingsBuildingException; import org.eclipse.aether.DefaultRepositorySystemSession; import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.internal.impl.SimpleLocalRepositoryManagerFactory; import org.eclipse.aether.repository.Authentication; import org.eclipse.aether.repository.AuthenticationContext; +import org.eclipse.aether.repository.LocalRepository; import org.eclipse.aether.repository.LocalRepositoryManager; import org.eclipse.aether.repository.Proxy; import org.eclipse.aether.repository.RemoteRepository; @@ -30,10 +32,17 @@ import org.junit.Test; import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.mockito.Mock; +import org.mockito.invocation.InvocationOnMock; import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.stubbing.Answer; +import static org.hamcrest.Matchers.endsWith; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThat; +import static org.mockito.BDDMockito.given; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; /** * Tests for {@link SettingsXmlRepositorySystemSessionAutoConfiguration}. @@ -49,9 +58,6 @@ public class SettingsXmlRepositorySystemSessionAutoConfigurationTests { @Mock private RepositorySystem repositorySystem; - @Mock - LocalRepositoryManager localRepositoryManager; - @Test public void basicSessionCustomization() throws SettingsBuildingException { assertSessionCustomization("src/test/resources/maven-settings/basic"); @@ -62,6 +68,39 @@ public class SettingsXmlRepositorySystemSessionAutoConfigurationTests { assertSessionCustomization("src/test/resources/maven-settings/encrypted"); } + @Test + public void propertyInterpolation() throws SettingsBuildingException { + final DefaultRepositorySystemSession session = MavenRepositorySystemUtils + .newSession(); + given( + this.repositorySystem.newLocalRepositoryManager(eq(session), + any(LocalRepository.class))).willAnswer( + new Answer() { + + @Override + public LocalRepositoryManager answer(InvocationOnMock invocation) + throws Throwable { + LocalRepository localRepository = invocation.getArgumentAt(1, + LocalRepository.class); + return new SimpleLocalRepositoryManagerFactory().newInstance( + session, localRepository); + } + }); + + System.setProperty("foo", "bar"); + try { + new SettingsXmlRepositorySystemSessionAutoConfiguration( + "src/test/resources/maven-settings/property-interpolation").apply( + session, this.repositorySystem); + } + finally { + System.clearProperty("foo"); + } + + assertThat(session.getLocalRepository().getBasedir().getAbsolutePath(), + endsWith("/bar/repository")); + } + private void assertSessionCustomization(String userHome) { DefaultRepositorySystemSession session = MavenRepositorySystemUtils.newSession();