Skip to content

Commit 6abb1e0

Browse files
committed
RewriteMavenParser honors Maven settings.xml
- Inject MavenParser into AddMinimalPomXml - Refactor RewriteMavenParser
1 parent a7f199c commit 6abb1e0

File tree

11 files changed

+284
-19
lines changed

11 files changed

+284
-19
lines changed

components/recipe-test-support/src/main/java/org/springframework/sbm/test/RecipeTestSupport.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
package org.springframework.sbm.test;
1717

1818
import com.fasterxml.jackson.databind.ObjectMapper;
19+
import org.springframework.sbm.build.impl.MavenSettingsInitializer;
20+
import org.springframework.sbm.build.impl.RewriteMavenParser;
1921
import org.springframework.sbm.engine.context.ProjectContextHolder;
2022
import org.springframework.sbm.engine.context.RewriteJavaSearchActionDeserializer;
2123
import org.springframework.sbm.engine.recipe.*;
@@ -69,7 +71,9 @@ private RecipeTestSupport() {
6971
RewriteSourceFileWrapper.class,
7072
SbmRecipeLoader.class,
7173
BasePackageCalculator.class,
72-
ProjectContextHolder.class
74+
ProjectContextHolder.class,
75+
RewriteMavenParser.class,
76+
MavenSettingsInitializer.class
7377
};
7478

7579

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright 2021 - 2022 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+
* https://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+
package org.springframework.sbm.build.impl;
17+
18+
import org.openrewrite.ExecutionContext;
19+
import org.openrewrite.maven.MavenExecutionContextView;
20+
import org.openrewrite.maven.MavenSettings;
21+
import org.springframework.stereotype.Component;
22+
23+
import java.nio.file.Files;
24+
import java.nio.file.Path;
25+
26+
/**
27+
* @author Fabian Krüger
28+
*/
29+
@Component
30+
public class MavenSettingsInitializer {
31+
public void initializeMavenSettings(ExecutionContext executionContext) {
32+
// Read .m2/settings.xml
33+
// TODO: Add support for global Maven settings (${maven.home}/conf/settings.xml).
34+
MavenExecutionContextView mavenExecutionContextView = MavenExecutionContextView.view(executionContext);
35+
Path mavenSettingsFile = Path.of(System.getProperty("user.home")).resolve(".m2/settings.xml");
36+
if (Files.exists(mavenSettingsFile)) {
37+
MavenSettings mavenSettings = MavenSettings.parse(mavenSettingsFile, mavenExecutionContextView);
38+
mavenExecutionContextView.setMavenSettings(mavenSettings);
39+
}
40+
}
41+
}

components/sbm-core/src/main/java/org/springframework/sbm/build/impl/RewriteMavenParser.java

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,27 +28,34 @@
2828
import java.util.List;
2929
import java.util.Optional;
3030

31+
/**
32+
* Class to parse Maven build files.
33+
*
34+
* It reads {@code .mvn/maven.config when a project root dir is provided.
35+
* Maven's {@code settings.xml} is read when it exits. The result is stored in {@code ExecutionContext}.
36+
* When an {@code ExecutionContext} is provided the MavenSettings are initilized again to guarantee that
37+
* all settings from {@code settings.xml} are respected.
38+
*/
3139
@Component
3240
public class RewriteMavenParser implements Parser<Xml.Document> {
3341

34-
private final MavenParser parser;
42+
private MavenParser parser;
43+
private final MavenSettingsInitializer mavenSettingsInitializer;
3544

36-
// FIXME: #7 This does not work for singleton Spring bean, also profiles and cache cannot be changed
37-
public RewriteMavenParser(Path projectRoot) {
38-
this.parser = initMavenParser(new RewriteExecutionContext(), Optional.ofNullable(projectRoot));
39-
}
40-
41-
public RewriteMavenParser() {
42-
this.parser = initMavenParser(new RewriteExecutionContext(), Optional.empty());
45+
public RewriteMavenParser(MavenSettingsInitializer mavenSettingsInitializer) {
46+
this.mavenSettingsInitializer = mavenSettingsInitializer;
47+
initMavenParser(new RewriteExecutionContext(), null);
4348
}
4449

4550
@NotNull
46-
private MavenParser initMavenParser(RewriteExecutionContext executionContext, Optional<Path> projectRoot) {
51+
private void initMavenParser(ExecutionContext executionContext, Path projectRoot) {
52+
mavenSettingsInitializer.initializeMavenSettings(executionContext);
53+
4754
MavenParser.Builder builder = MavenParser.builder();
48-
if(projectRoot.isPresent()) {
49-
builder.mavenConfig(projectRoot.get().resolve(".mvn/maven.config"));
55+
if (projectRoot != null && projectRoot.resolve(".mvn/maven.config").toFile().exists()) {
56+
builder.mavenConfig(projectRoot.resolve(".mvn/maven.config"));
5057
}
51-
builder.build();
58+
this.parser = builder.build();
5259
// if(executionContext.getMavenProfiles().length > 0) {
5360
// builder.activeProfiles(executionContext.getMavenProfiles());
5461
// }
@@ -58,16 +65,32 @@ private MavenParser initMavenParser(RewriteExecutionContext executionContext, Op
5865
// if(executionContext.getMavenPomCache() != null) {
5966
// builder.cache(executionContext.getMavenPomCache());
6067
// }
61-
return builder.build();
6268
}
6369

6470
@Override
6571
public List<Xml.Document> parse(String... sources) {
6672
return parser.parse(sources);
6773
}
6874

75+
@Override
76+
public List<Xml.Document> parse(ExecutionContext ctx, String... sources) {
77+
mavenSettingsInitializer.initializeMavenSettings(ctx);
78+
parser.parse(ctx, sources);
79+
return Parser.super.parse(ctx, sources);
80+
}
81+
82+
/**
83+
* @param sources the sources to parse
84+
* @param relativeTo the project root, if null is given .mvn/maven.config will not be read
85+
* @param ctx the ExecutionContext,
86+
*/
6987
@Override
7088
public List<Xml.Document> parseInputs(Iterable<Input> sources, @Nullable Path relativeTo, ExecutionContext ctx) {
89+
if (relativeTo != null) {
90+
initMavenParser(ctx, relativeTo);
91+
} else {
92+
mavenSettingsInitializer.initializeMavenSettings(ctx);
93+
}
7194
return parser.parseInputs(sources, relativeTo, ctx);
7295
}
7396

components/sbm-core/src/main/java/org/springframework/sbm/build/migration/actions/AddMinimalPomXml.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ public class AddMinimalPomXml extends AbstractAction {
4343
@Setter
4444
private Configuration configuration;
4545

46+
@Autowired
47+
@JsonIgnore
48+
private RewriteMavenParser rewriteMavenParser;
49+
4650
@Override
4751
public void apply(ProjectContext context) {
4852
String projectDir = context.getProjectRootDirectory().toString();
@@ -61,9 +65,9 @@ public void apply(ProjectContext context) {
6165
}
6266

6367
String src = writer.toString();
64-
RewriteMavenParser rewriteMavenParser = new RewriteMavenParser();
6568
Parser.Input input = new Parser.Input(Path.of("pom.xml"), () -> new ByteArrayInputStream(src.getBytes(StandardCharsets.UTF_8)));
66-
Xml.Document maven = rewriteMavenParser.parseInputs(List.of(input), null, new RewriteExecutionContext(getEventPublisher())).get(0);
69+
Xml.Document maven = rewriteMavenParser
70+
.parseInputs(List.of(input), null, new RewriteExecutionContext(getEventPublisher())).get(0);
6771
OpenRewriteMavenBuildFile rewriteMavenBuildFile = new OpenRewriteMavenBuildFile(
6872
context.getProjectRootDirectory(),
6973
maven, getEventPublisher(), new RewriteExecutionContext(getEventPublisher())
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
* Copyright 2021 - 2022 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+
* https://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+
package org.springframework.sbm.build.impl;
17+
18+
import org.junit.jupiter.api.*;
19+
import org.openrewrite.maven.MavenExecutionContextView;
20+
import org.openrewrite.maven.tree.MavenRepository;
21+
import org.springframework.sbm.openrewrite.RewriteExecutionContext;
22+
23+
import java.net.URI;
24+
import java.net.URISyntaxException;
25+
import java.nio.file.Path;
26+
27+
import static org.assertj.core.api.Assertions.assertThat;
28+
import static org.junit.jupiter.api.Assertions.*;
29+
30+
/**
31+
* @author Fabian Krüger
32+
*/
33+
class MavenSettingsInitializerTest {
34+
35+
// localRepository.getUri() will differ from '"file:" + userHome + "/.m2/repository/"' because
36+
// MavenRepository.MAVEN_LOCAL_DEFAULT gets returned and this field is statically initialized.
37+
// For this test it means that running the test in isolation succeeds but running it in combination
38+
// with a test that loads MavenRepository before 'user.home' was changed in this test, it fails.
39+
// And maybe even worse, running this test before others would set the local maven repository to the
40+
// dummy dir used in this test.
41+
// To prevent this it will be initialized (if it wasn't already) with the original settings with this line:
42+
MavenRepository mavenLocalDefault = MavenRepository.MAVEN_LOCAL_DEFAULT;
43+
private String actualUserHome;
44+
private Path fakedUserHome;
45+
46+
@BeforeEach
47+
void beforeEach() {
48+
// Faking the local maven dir to provide the settings.xml for this test
49+
fakedUserHome = Path.of("./testcode/project-with-maven-settings/user-home").toAbsolutePath().normalize();
50+
actualUserHome = System.getProperty("user.home");
51+
System.setProperty("user.home", fakedUserHome.toString());
52+
}
53+
54+
@Test
55+
void mavenParserMustAdhereToSettingsXmlTest() throws URISyntaxException {
56+
57+
58+
RewriteExecutionContext executionContext = new RewriteExecutionContext();
59+
MavenSettingsInitializer sut = new MavenSettingsInitializer();
60+
sut.initializeMavenSettings(executionContext);
61+
MavenExecutionContextView mavenExecutionContextView = MavenExecutionContextView.view(executionContext);
62+
63+
assertThat(mavenExecutionContextView.getRepositories()).hasSize(1);
64+
65+
MavenRepository mavenRepository = mavenExecutionContextView.getRepositories().get(0);
66+
67+
assertThat(mavenRepository.getId()).isEqualTo("central");
68+
assertThat(mavenRepository.getUri()).isEqualTo("https://jcenter.bintray.com");
69+
assertThat(mavenRepository.isReleases()).isTrue();
70+
assertThat(mavenRepository.isSnapshots()).isFalse();
71+
72+
MavenRepository localRepository = mavenExecutionContextView.getLocalRepository();
73+
assertThat(localRepository.isSnapshots()).isTrue();
74+
75+
// assertThat(localRepository.getUri()).isEqualTo("file:" + fakedUserHome + "/.m2/repository/");
76+
assertThat(localRepository.getUri()).isEqualTo(MavenRepository.MAVEN_LOCAL_DEFAULT.getUri());
77+
assertThat(localRepository.isSnapshots()).isTrue();
78+
assertThat(localRepository.isKnownToExist()).isTrue();
79+
assertThat(localRepository.getUsername()).isNull();
80+
assertThat(localRepository.getPassword()).isNull();
81+
}
82+
83+
@AfterEach
84+
public void reset() {
85+
// reset
86+
System.setProperty("user.home", actualUserHome);
87+
}
88+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright 2021 - 2022 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+
* https://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+
package org.springframework.sbm.build.impl;
17+
18+
import org.junit.jupiter.api.Test;
19+
import org.junit.jupiter.api.extension.ExtendWith;
20+
import org.mockito.InjectMocks;
21+
import org.mockito.Mock;
22+
import org.mockito.junit.jupiter.MockitoExtension;
23+
import org.openrewrite.ExecutionContext;
24+
import org.springframework.sbm.build.util.PomBuilder;
25+
import org.springframework.sbm.openrewrite.RewriteExecutionContext;
26+
27+
import static org.mockito.ArgumentMatchers.any;
28+
import static org.mockito.Mockito.times;
29+
import static org.mockito.Mockito.verify;
30+
31+
/**
32+
* @author Fabian Krüger
33+
*/
34+
@ExtendWith(MockitoExtension.class)
35+
class RewriteMavenParserTest {
36+
37+
@Mock
38+
MavenSettingsInitializer mavenSettingsInitializer;
39+
@InjectMocks
40+
RewriteMavenParser sut;
41+
42+
@Test
43+
void noExecutionContextGiven() {
44+
verify(mavenSettingsInitializer).initializeMavenSettings(any(ExecutionContext.class));
45+
}
46+
47+
@Test
48+
void customExecutionContextGiven() {
49+
String pom = PomBuilder.buiildPom("com.example:project:1.0").build();
50+
ExecutionContext ctx = new RewriteExecutionContext();
51+
sut.parse(ctx, pom);
52+
// first time when initializing the parser
53+
// second time in the parse method to guarantee ExecutionContext is enriched with MavenSettings
54+
verify(mavenSettingsInitializer, times(2)).initializeMavenSettings(ctx);
55+
}
56+
57+
}

components/sbm-core/src/test/java/org/springframework/sbm/java/impl/ClasspathRegistryTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.openrewrite.maven.tree.ResolvedDependency;
2323
import org.openrewrite.maven.tree.Scope;
2424
import org.openrewrite.xml.tree.Xml;
25+
import org.springframework.sbm.build.impl.MavenSettingsInitializer;
2526
import org.springframework.sbm.build.impl.RewriteMavenParser;
2627

2728
import java.util.List;
@@ -101,7 +102,7 @@ void classpathRegistryShouldKeepOnlyExternalDependencies() {
101102
assertThat(sut.getCurrentDependencies()).isEmpty();
102103
assertThat(sut.getInitialDependencies()).isEmpty();
103104

104-
List<Xml.Document> poms = new RewriteMavenParser().parse(parentPom, pom1, pom2);
105+
List<Xml.Document> poms = new RewriteMavenParser(new MavenSettingsInitializer()).parse(parentPom, pom1, pom2);
105106

106107
Set<ResolvedDependency> resolvedDependencies = poms
107108
.get(2)

components/sbm-core/src/test/java/org/springframework/sbm/project/parser/JavaProvenanceMarkerFactoryTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.openrewrite.marker.BuildTool;
2424
import org.openrewrite.marker.Marker;
2525
import org.openrewrite.xml.tree.Xml;
26+
import org.springframework.sbm.build.impl.MavenSettingsInitializer;
2627
import org.springframework.sbm.build.impl.RewriteMavenParser;
2728
import org.springframework.sbm.openrewrite.RewriteExecutionContext;
2829

@@ -63,7 +64,7 @@ void test() {
6364
"</project>";
6465

6566
Path projectDirectory = Path.of("./faked-project-dir/pom.xml");
66-
Xml.Document maven = new RewriteMavenParser().parse(pomXmlSource).get(0).withSourcePath(Path.of("pom.xml"));
67+
Xml.Document maven = new RewriteMavenParser(new MavenSettingsInitializer()).parse(pomXmlSource).get(0).withSourcePath(Path.of("pom.xml"));
6768

6869
List<Marker> javaProvenanceMarkers = sut.createJavaProvenanceMarkers(maven, projectDirectory, new RewriteExecutionContext());
6970

components/sbm-core/src/test/java/org/springframework/sbm/project/parser/ProjectContextInitializerTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.springframework.context.ApplicationEventPublisher;
3030
import org.springframework.core.io.Resource;
3131
import org.springframework.core.io.ResourceLoader;
32+
import org.springframework.sbm.build.impl.MavenSettingsInitializer;
3233
import org.springframework.sbm.build.impl.RewriteMavenArtifactDownloader;
3334
import org.springframework.sbm.build.impl.RewriteMavenParser;
3435
import org.springframework.sbm.build.migration.MavenPomCacheProvider;
@@ -78,6 +79,7 @@
7879
RewritePropertiesParser.class,
7980
MavenProjectParser.class,
8081
RewriteMavenParser.class,
82+
MavenSettingsInitializer.class,
8183
RewriteXmlParser.class,
8284
ResourceHelper.class,
8385
ResourceLoader.class,

components/sbm-core/src/test/java/org/springframework/sbm/project/resource/TestProjectContext.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.springframework.core.annotation.Order;
2424
import org.springframework.core.io.DefaultResourceLoader;
2525
import org.springframework.core.io.Resource;
26+
import org.springframework.sbm.build.impl.MavenSettingsInitializer;
2627
import org.springframework.sbm.build.impl.OpenRewriteMavenBuildFile;
2728
import org.springframework.sbm.build.impl.RewriteMavenArtifactDownloader;
2829
import org.springframework.sbm.build.impl.RewriteMavenParser;
@@ -551,7 +552,7 @@ private ProjectContextInitializer createProjectContextInitializer(ProjectContext
551552
new ResourceParser.ResourceFilter(),
552553
eventPublisher);
553554

554-
RewriteMavenParser mavenParser = new RewriteMavenParser();
555+
RewriteMavenParser mavenParser = new RewriteMavenParser(new MavenSettingsInitializer());
555556

556557
MavenArtifactDownloader artifactDownloader = new RewriteMavenArtifactDownloader();
557558

0 commit comments

Comments
 (0)