Skip to content

Commit 5e743fb

Browse files
committed
Fully honour local repository location configured in settings.xml
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
1 parent bbb0b7a commit 5e743fb

7 files changed

+252
-14
lines changed

spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/RepositoryConfigurationFactory.java

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@
2121
import java.util.ArrayList;
2222
import java.util.List;
2323

24+
import org.apache.maven.settings.Settings;
25+
import org.apache.maven.settings.building.DefaultSettingsBuilderFactory;
26+
import org.apache.maven.settings.building.DefaultSettingsBuildingRequest;
27+
import org.apache.maven.settings.building.SettingsBuildingException;
28+
import org.apache.maven.settings.building.SettingsBuildingRequest;
2429
import org.springframework.boot.cli.compiler.grape.RepositoryConfiguration;
2530
import org.springframework.util.StringUtils;
2631

@@ -66,12 +71,35 @@ public static List<RepositoryConfiguration> createDefaultRepositoryConfiguration
6671
public static void addDefaultCacheAsRespository(
6772
List<RepositoryConfiguration> repositoryConfiguration) {
6873
RepositoryConfiguration repository = new RepositoryConfiguration("local",
69-
new File(getM2HomeDirectory(), "repository").toURI(), true);
74+
getLocalRepositoryDirectory().toURI(), true);
7075
if (!repositoryConfiguration.contains(repository)) {
7176
repositoryConfiguration.add(0, repository);
7277
}
7378
}
7479

80+
private static File getLocalRepositoryDirectory() {
81+
String localRepository = loadSettings().getLocalRepository();
82+
if (StringUtils.hasText(localRepository)) {
83+
return new File(localRepository);
84+
}
85+
return new File(getM2HomeDirectory(), "repository");
86+
}
87+
88+
private static Settings loadSettings() {
89+
File settingsFile = new File(System.getProperty("user.home"), ".m2/settings.xml");
90+
SettingsBuildingRequest request = new DefaultSettingsBuildingRequest();
91+
request.setUserSettingsFile(settingsFile);
92+
request.setSystemProperties(System.getProperties());
93+
try {
94+
return new DefaultSettingsBuilderFactory().newInstance().build(request)
95+
.getEffectiveSettings();
96+
}
97+
catch (SettingsBuildingException ex) {
98+
throw new IllegalStateException("Failed to build settings from "
99+
+ settingsFile, ex);
100+
}
101+
}
102+
75103
private static File getM2HomeDirectory() {
76104
String mavenRoot = System.getProperty("maven.home");
77105
if (StringUtils.hasLength(mavenRoot)) {

spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/grape/DefaultRepositorySystemSessionAutoConfiguration.java

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -57,15 +57,7 @@ public void apply(DefaultRepositorySystemSession session,
5757
}
5858

5959
private File getM2RepoDirectory() {
60-
return new File(getM2HomeDirectory(), "repository");
61-
}
62-
63-
private File getM2HomeDirectory() {
64-
String grapeRoot = System.getProperty("grape.root");
65-
if (StringUtils.hasLength(grapeRoot)) {
66-
return new File(grapeRoot);
67-
}
68-
return getDefaultM2HomeDirectory();
60+
return new File(getDefaultM2HomeDirectory(), "repository");
6961
}
7062

7163
private File getDefaultM2HomeDirectory() {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright 2012-2015 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.cli.compiler.grape;
18+
19+
import java.io.File;
20+
21+
import org.eclipse.aether.DefaultRepositorySystemSession;
22+
import org.eclipse.aether.RepositorySystem;
23+
import org.eclipse.aether.repository.LocalRepository;
24+
import org.eclipse.aether.repository.LocalRepositoryManager;
25+
import org.springframework.util.StringUtils;
26+
27+
/**
28+
* Honours the configuration of {@code grape.root} by customizing the session's local
29+
* repository location.
30+
*
31+
* @author Andy Wilkinson
32+
* @since 1.2.5
33+
*/
34+
public class GrapeRootRepositorySystemSessionAutoConfiguration implements
35+
RepositorySystemSessionAutoConfiguration {
36+
37+
@Override
38+
public void apply(DefaultRepositorySystemSession session,
39+
RepositorySystem repositorySystem) {
40+
String grapeRoot = System.getProperty("grape.root");
41+
if (StringUtils.hasLength(grapeRoot)) {
42+
configureLocalRepository(session, repositorySystem, grapeRoot);
43+
}
44+
}
45+
46+
private void configureLocalRepository(DefaultRepositorySystemSession session,
47+
RepositorySystem repositorySystem, String grapeRoot) {
48+
File repositoryDir = new File(grapeRoot, "repository");
49+
LocalRepository localRepository = new LocalRepository(repositoryDir);
50+
LocalRepositoryManager localRepositoryManager = repositorySystem
51+
.newLocalRepositoryManager(session, localRepository);
52+
session.setLocalRepositoryManager(localRepositoryManager);
53+
}
54+
55+
}

spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/grape/SettingsXmlRepositorySystemSessionAutoConfiguration.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ private Settings loadSettings() {
9696
File settingsFile = new File(this.homeDir, ".m2/settings.xml");
9797
SettingsBuildingRequest request = new DefaultSettingsBuildingRequest();
9898
request.setUserSettingsFile(settingsFile);
99+
request.setSystemProperties(System.getProperties());
99100
try {
100101
return new DefaultSettingsBuilderFactory().newInstance().build(request)
101102
.getEffectiveSettings();
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
org.springframework.boot.cli.compiler.grape.SettingsXmlRepositorySystemSessionAutoConfiguration
1+
org.springframework.boot.cli.compiler.grape.SettingsXmlRepositorySystemSessionAutoConfiguration
2+
org.springframework.boot.cli.compiler.grape.GrapeRootRepositorySystemSessionAutoConfiguration
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/*
2+
* Copyright 2012-2015 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.cli.compiler.grape;
18+
19+
import org.apache.maven.repository.internal.MavenRepositorySystemUtils;
20+
import org.eclipse.aether.DefaultRepositorySystemSession;
21+
import org.eclipse.aether.RepositorySystem;
22+
import org.eclipse.aether.internal.impl.SimpleLocalRepositoryManagerFactory;
23+
import org.eclipse.aether.repository.LocalRepository;
24+
import org.eclipse.aether.repository.LocalRepositoryManager;
25+
import org.junit.Test;
26+
import org.junit.runner.RunWith;
27+
import org.mockito.Mock;
28+
import org.mockito.invocation.InvocationOnMock;
29+
import org.mockito.runners.MockitoJUnitRunner;
30+
import org.mockito.stubbing.Answer;
31+
32+
import static org.hamcrest.Matchers.endsWith;
33+
import static org.hamcrest.Matchers.is;
34+
import static org.hamcrest.Matchers.notNullValue;
35+
import static org.hamcrest.Matchers.nullValue;
36+
import static org.junit.Assert.assertThat;
37+
import static org.mockito.BDDMockito.given;
38+
import static org.mockito.Matchers.any;
39+
import static org.mockito.Matchers.eq;
40+
import static org.mockito.Mockito.times;
41+
import static org.mockito.Mockito.verify;
42+
43+
/**
44+
* Tests for {@link GrapeRootRepositorySystemSessionAutoConfiguration}
45+
*
46+
* @author Andy Wilkinson
47+
*/
48+
@RunWith(MockitoJUnitRunner.class)
49+
public class GrapeRootRepositorySystemSessionAutoConfigurationTests {
50+
51+
private DefaultRepositorySystemSession session = MavenRepositorySystemUtils
52+
.newSession();
53+
54+
@Mock
55+
private RepositorySystem repositorySystem;
56+
57+
@Test
58+
public void noLocalRepositoryWhenNoGrapeRoot() {
59+
given(
60+
this.repositorySystem.newLocalRepositoryManager(eq(this.session),
61+
any(LocalRepository.class))).willAnswer(
62+
new Answer<LocalRepositoryManager>() {
63+
64+
@Override
65+
public LocalRepositoryManager answer(InvocationOnMock invocation)
66+
throws Throwable {
67+
LocalRepository localRepository = invocation.getArgumentAt(1,
68+
LocalRepository.class);
69+
return new SimpleLocalRepositoryManagerFactory()
70+
.newInstance(
71+
GrapeRootRepositorySystemSessionAutoConfigurationTests.this.session,
72+
localRepository);
73+
}
74+
});
75+
76+
new GrapeRootRepositorySystemSessionAutoConfiguration().apply(this.session,
77+
this.repositorySystem);
78+
79+
verify(this.repositorySystem, times(0)).newLocalRepositoryManager(
80+
eq(this.session), any(LocalRepository.class));
81+
82+
assertThat(this.session.getLocalRepository(), is(nullValue()));
83+
}
84+
85+
@Test
86+
public void grapeRootConfiguresLocalRepositoryLocation() {
87+
given(
88+
this.repositorySystem.newLocalRepositoryManager(eq(this.session),
89+
any(LocalRepository.class))).willAnswer(
90+
new LocalRepositoryManagerAnswer());
91+
92+
System.setProperty("grape.root", "foo");
93+
try {
94+
new GrapeRootRepositorySystemSessionAutoConfiguration().apply(this.session,
95+
this.repositorySystem);
96+
}
97+
finally {
98+
System.clearProperty("grape.root");
99+
}
100+
101+
verify(this.repositorySystem, times(1)).newLocalRepositoryManager(
102+
eq(this.session), any(LocalRepository.class));
103+
104+
assertThat(this.session.getLocalRepository(), is(notNullValue()));
105+
assertThat(this.session.getLocalRepository().getBasedir().getAbsolutePath(),
106+
endsWith("/foo/repository"));
107+
}
108+
109+
private class LocalRepositoryManagerAnswer implements Answer<LocalRepositoryManager> {
110+
@Override
111+
public LocalRepositoryManager answer(InvocationOnMock invocation)
112+
throws Throwable {
113+
LocalRepository localRepository = invocation.getArgumentAt(1,
114+
LocalRepository.class);
115+
return new SimpleLocalRepositoryManagerFactory().newInstance(
116+
GrapeRootRepositorySystemSessionAutoConfigurationTests.this.session,
117+
localRepository);
118+
}
119+
120+
}
121+
122+
}

spring-boot-cli/src/test/java/org/springframework/boot/cli/compiler/grape/SettingsXmlRepositorySystemSessionAutoConfigurationTests.java

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@
2020
import org.apache.maven.settings.building.SettingsBuildingException;
2121
import org.eclipse.aether.DefaultRepositorySystemSession;
2222
import org.eclipse.aether.RepositorySystem;
23+
import org.eclipse.aether.internal.impl.SimpleLocalRepositoryManagerFactory;
2324
import org.eclipse.aether.repository.Authentication;
2425
import org.eclipse.aether.repository.AuthenticationContext;
26+
import org.eclipse.aether.repository.LocalRepository;
2527
import org.eclipse.aether.repository.LocalRepositoryManager;
2628
import org.eclipse.aether.repository.Proxy;
2729
import org.eclipse.aether.repository.RemoteRepository;
@@ -30,10 +32,17 @@
3032
import org.junit.rules.ExpectedException;
3133
import org.junit.runner.RunWith;
3234
import org.mockito.Mock;
35+
import org.mockito.invocation.InvocationOnMock;
3336
import org.mockito.runners.MockitoJUnitRunner;
37+
import org.mockito.stubbing.Answer;
3438

39+
import static org.hamcrest.Matchers.endsWith;
3540
import static org.junit.Assert.assertEquals;
3641
import static org.junit.Assert.assertNotNull;
42+
import static org.junit.Assert.assertThat;
43+
import static org.mockito.BDDMockito.given;
44+
import static org.mockito.Matchers.any;
45+
import static org.mockito.Matchers.eq;
3746

3847
/**
3948
* Tests for {@link SettingsXmlRepositorySystemSessionAutoConfiguration}.
@@ -49,9 +58,6 @@ public class SettingsXmlRepositorySystemSessionAutoConfigurationTests {
4958
@Mock
5059
private RepositorySystem repositorySystem;
5160

52-
@Mock
53-
LocalRepositoryManager localRepositoryManager;
54-
5561
@Test
5662
public void basicSessionCustomization() throws SettingsBuildingException {
5763
assertSessionCustomization("src/test/resources/maven-settings/basic");
@@ -62,6 +68,39 @@ public void encryptedSettingsSessionCustomization() throws SettingsBuildingExcep
6268
assertSessionCustomization("src/test/resources/maven-settings/encrypted");
6369
}
6470

71+
@Test
72+
public void propertyInterpolation() throws SettingsBuildingException {
73+
final DefaultRepositorySystemSession session = MavenRepositorySystemUtils
74+
.newSession();
75+
given(
76+
this.repositorySystem.newLocalRepositoryManager(eq(session),
77+
any(LocalRepository.class))).willAnswer(
78+
new Answer<LocalRepositoryManager>() {
79+
80+
@Override
81+
public LocalRepositoryManager answer(InvocationOnMock invocation)
82+
throws Throwable {
83+
LocalRepository localRepository = invocation.getArgumentAt(1,
84+
LocalRepository.class);
85+
return new SimpleLocalRepositoryManagerFactory().newInstance(
86+
session, localRepository);
87+
}
88+
});
89+
90+
System.setProperty("foo", "bar");
91+
try {
92+
new SettingsXmlRepositorySystemSessionAutoConfiguration(
93+
"src/test/resources/maven-settings/property-interpolation").apply(
94+
session, this.repositorySystem);
95+
}
96+
finally {
97+
System.clearProperty("foo");
98+
}
99+
100+
assertThat(session.getLocalRepository().getBasedir().getAbsolutePath(),
101+
endsWith("/bar/repository"));
102+
}
103+
65104
private void assertSessionCustomization(String userHome) {
66105
DefaultRepositorySystemSession session = MavenRepositorySystemUtils.newSession();
67106

0 commit comments

Comments
 (0)