Skip to content

Commit c10881b

Browse files
authored
deps: Upgrade OpenRewrite 7.35.0 (#728)
* refactor: Formatting, check marker exists before adding * fix: Use nullsafe equals * refactor: Remove obsolete test and strange reference to the same * cleanup: Delete obsolete test * doc: Add javadoc * dep: Bump Open Rewrite to 7.35.0 * OpenRewrite 7.35.0 uses snakeyaml 1.33 * fix: ResourceParser excludes parsers with no input * refactor: Improve adding dependencies by adding all at once instead of in in a loop * refactor: Improve exception message * enhance OpenRewriteMavenBuildFile to take and provide MavenBuildFileRefactoring to apply OpenRewrite recipes to one or all maven build files * refactor: Replace concatenated with multiline string * test: Enabled test again * test: refactor and add assertions * test: Refactor and add test * test: Fix test by replacing dummy with real dependencies * fix: Filter local projects when resolving the paths to dependency jars * refactor: Handle exception in print() * fix: Replace pom model refresh * fix: Set release and snapshot property for Maven repository * refactor: Replace deprecated method call * doc: Fiddle with comments after update of asciidoclet * cleanup: Replace concatenated with multiline String * dep: Adopt Api to 7.35. * cleanup: Cleanup comment * cleanup: Remove unused imports * refactor: Make JavaParser final * test: Add (disabled) test for adding dependencies * test: Add test for deletion of Maven property in multi module project * test: Add test for setting a property in a pom file * test: Add test for sorting poms in MavenProjectParser * test: Add tests for GH issues 2601 and 2624 * test: Delete obsolete test * test: Fix test data * test: Fix UpgradeDepenenciesMigrationTest by adding blank lines to expected pom * This is useful when a stateful JavParser has been created by Spring Boot that should be used * test: Refactor add dependency test * test: Set packaging to pom in test data * fix: Fix Removal of redundant compiler plugins * fix: Use RewriteJavaParser and set changed classpath * test: Fix ConvertJaxRsAnnotationTest * test: Fix by adding expected dependency (again)
1 parent 2ab022c commit c10881b

File tree

53 files changed

+1814
-1037
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+1814
-1037
lines changed

components/openrewrite-spring-recipes/src/main/java/org/springframework/sbm/OrRecipesConfig.java

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

1818
import org.openrewrite.maven.AddPluginDependency;
19+
import org.openrewrite.maven.UpdateMavenModel;
1920
import org.springframework.context.annotation.Bean;
2021
import org.springframework.context.annotation.Configuration;
2122
import org.springframework.sbm.build.impl.OpenRewriteMavenBuildFile;
@@ -25,6 +26,7 @@
2526
import org.springframework.sbm.engine.recipe.Condition;
2627
import org.springframework.sbm.engine.recipe.Recipe;
2728
import org.springframework.sbm.spring.migration.actions.OpenRewriteRecipeAdapterAction;
29+
import org.springframework.sbm.support.openrewrite.GenericOpenRewriteRecipe;
2830

2931
import java.lang.reflect.InvocationTargetException;
3032
import java.util.List;
@@ -69,7 +71,7 @@ Recipe recipeSpringBoot1To2Migration(RewriteRecipesRepository repo) {
6971

7072
r.doNext(new RemoveMavenPlugin("org.codehaus.mojo", "cobertura-maven-plugin"));
7173
r.doNext(new AddPluginDependency("ro.isdc.wro4j", "wro4j-maven-plugin", "org.mockito", "mockito-core", "${mockito.version}"));
72-
r.doNext(new OpenRewriteMavenBuildFile.RefreshPomModel());
74+
r.doNext(new GenericOpenRewriteRecipe<>(() -> new UpdateMavenModel<>()));
7375

7476
AnyDeclaredDependencyExistMatchingRegex condition = new AnyDeclaredDependencyExistMatchingRegex();
7577
condition.setDependencies(List.of("org\\.springframework\\.boot:.*:1\\..*"));

components/openrewrite-spring-recipes/src/test/java/org/springframework/sbm/SpringBoot23To24MigrationTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ public void recipeUpdatesBootDependenciesAndParentVersion() throws IOException {
115115

116116
List<Resource> resources = List.of();
117117

118-
ProjectContext projectContext = contextInitializer.initProjectContext(Path.of("./testcode/boot-23-app/given"), resources, new RewriteExecutionContext());
118+
ProjectContext projectContext = contextInitializer.initProjectContext(Path.of("./testcode/boot-23-app/given"), resources);
119119
projectContext.getApplicationModules().getRootModule().getMainResourceSet().addStringResource("src/main/resources/data.sql", "# Empty file");
120120

121121

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ public static ProjectContext createProjectContextFromDir(String projectRootDir,
6565
ProjectContextInitializer projectContextBuilder = ctx.getBean(ProjectContextInitializer.class);
6666
ScanCommand scanCommand = ctx.getBean(ScanCommand.class);
6767
List<Resource> resources = scanCommand.scanProjectRoot(to.toString());
68-
ProjectContext projectContext = projectContextBuilder.initProjectContext(projectRoot, resources, new RewriteExecutionContext());
68+
ProjectContext projectContext = projectContextBuilder.initProjectContext(projectRoot, resources);
6969
projectContextHolder.setContext(projectContext);
7070
},
7171
beanClasses.toArray(new Class[]{})

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,7 @@
1616
package org.springframework.sbm.test;
1717

1818
import com.fasterxml.jackson.databind.ObjectMapper;
19+
import org.springframework.sbm.build.impl.MavenBuildFileRefactoringFactory;
1920
import org.springframework.sbm.build.impl.MavenSettingsInitializer;
2021
import org.springframework.sbm.build.impl.RewriteMavenParser;
2122
import org.springframework.sbm.engine.context.ProjectContextHolder;
@@ -24,6 +25,7 @@
2425
import org.springframework.sbm.java.impl.RewriteJavaParser;
2526
import org.springframework.sbm.java.util.BasePackageCalculator;
2627
import org.springframework.sbm.project.RewriteSourceFileWrapper;
28+
import org.springframework.sbm.project.resource.ProjectResourceSetHolder;
2729
import org.springframework.sbm.project.resource.SbmApplicationProperties;
2830
import org.springframework.sbm.project.resource.ResourceHelper;
2931
import org.springframework.sbm.search.recipe.actions.OpenRewriteJavaSearchAction;
@@ -73,7 +75,9 @@ private RecipeTestSupport() {
7375
BasePackageCalculator.class,
7476
ProjectContextHolder.class,
7577
RewriteMavenParser.class,
76-
MavenSettingsInitializer.class
78+
MavenSettingsInitializer.class,
79+
MavenBuildFileRefactoringFactory.class,
80+
ProjectResourceSetHolder.class
7781
};
7882

7983

components/sbm-core/src/main/java/org/springframework/sbm/build/api/BuildFile.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121

2222
import java.nio.file.Path;
2323
import java.util.List;
24-
import java.util.Map;
2524
import java.util.Optional;
2625
import java.util.Set;
2726

@@ -87,7 +86,9 @@ public interface BuildFile extends ProjectResource {
8786

8887
void removeDependenciesInner(List<Dependency> dependencies);
8988

90-
List<Dependency> getDependencyManagement();
89+
List<Dependency> getEffectiveDependencyManagement();
90+
91+
List<Dependency> getRequestedDependencyManagement();
9192

9293
List<Dependency> getRequestedManagedDependencies();
9394

@@ -115,6 +116,9 @@ public interface BuildFile extends ProjectResource {
115116

116117
Path getMainResourceFolder();
117118

119+
/**
120+
* Sets existing property or adds new property.
121+
*/
118122
void setProperty(String key, String value);
119123

120124
String getProperty(String key);

components/sbm-core/src/main/java/org/springframework/sbm/build/api/SpringManagedDependencies.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package org.springframework.sbm.build.api;
1717

18+
import org.openrewrite.maven.MavenDownloadingException;
1819
import org.openrewrite.maven.internal.MavenPomDownloader;
1920
import org.openrewrite.maven.tree.GroupArtifactVersion;
2021
import org.openrewrite.maven.tree.MavenRepository;
@@ -32,7 +33,7 @@
3233
public class SpringManagedDependencies {
3334

3435
private static List<MavenRepository> SPRING_REPOSITORIES = List.of(
35-
new MavenRepository("spring-release", "https://repo.spring.io/release", true, false, null, null)
36+
new MavenRepository("spring-release", "https://repo.spring.io/release", "true", "false", true, null, null, null)
3637
);
3738

3839
private List<org.openrewrite.maven.tree.Dependency> dependencies;
@@ -47,9 +48,13 @@ public static SpringManagedDependencies by(String groupId, String artifact, Stri
4748
}
4849

4950
private SpringManagedDependencies(GroupArtifactVersion groupArtifactVersion){
50-
dependencies = new MavenPomDownloader(Collections.emptyMap(), new RewriteExecutionContext())
51-
.download(groupArtifactVersion, null, null, SPRING_REPOSITORIES)
52-
.getDependencies();
51+
try {
52+
dependencies = new MavenPomDownloader(Collections.emptyMap(), new RewriteExecutionContext())
53+
.download(groupArtifactVersion, null, null, SPRING_REPOSITORIES)
54+
.getDependencies();
55+
} catch (MavenDownloadingException e) {
56+
throw new RuntimeException(e);
57+
}
5358
}
5459

5560
public Stream<Dependency> stream(){

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

Lines changed: 142 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -15,25 +15,43 @@
1515
*/
1616
package org.springframework.sbm.build.impl;
1717

18+
import lombok.Getter;
1819
import lombok.RequiredArgsConstructor;
19-
import org.openrewrite.Recipe;
20-
import org.openrewrite.Result;
21-
import org.openrewrite.maven.MavenParser;
20+
import org.jetbrains.annotations.NotNull;
21+
import org.openrewrite.*;
22+
import org.openrewrite.marker.Markers;
23+
import org.openrewrite.marker.SearchResult;
2224
import org.openrewrite.maven.MavenVisitor;
25+
import org.openrewrite.maven.tree.MavenResolutionResult;
2326
import org.openrewrite.xml.tree.Xml;
2427
import org.springframework.sbm.openrewrite.RewriteExecutionContext;
28+
import org.springframework.sbm.project.resource.ProjectResourceSet;
2529
import org.springframework.sbm.project.resource.RewriteSourceFileHolder;
2630
import org.springframework.sbm.support.openrewrite.GenericOpenRewriteRecipe;
2731

32+
import java.io.ByteArrayInputStream;
33+
import java.nio.charset.StandardCharsets;
34+
import java.nio.file.Files;
35+
import java.util.ArrayList;
2836
import java.util.Arrays;
2937
import java.util.List;
3038
import java.util.stream.Collectors;
3139

40+
/**
41+
* This class provides a facade to apply OpenRewrite {@code Recipe}s and {@code Visitor}s to the project Maven build files.
42+
*
43+
* @author Fabian Krüger
44+
*/
3245
@RequiredArgsConstructor
33-
class MavenBuildFileRefactoring<P> {
34-
35-
private final RewriteSourceFileHolder<Xml.Document> pom;
46+
public class MavenBuildFileRefactoring<T extends SourceFile> {
47+
private final ProjectResourceSet projectResourceSet;
48+
private final RewriteMavenParser mavenParser;
3649

50+
/**
51+
* Applies the provided {@code Visitor}s to all Maven build files in the {@code ProjectContext}.
52+
*
53+
* The changes are immediately reflected in the wrapping {@code BuildFile}s.
54+
*/
3755
public void execute(MavenVisitor... visitors) {
3856
List<Result> results = Arrays.stream(visitors)
3957
.map(v -> new GenericOpenRewriteRecipe(() -> v))
@@ -43,32 +61,136 @@ public void execute(MavenVisitor... visitors) {
4361
processResults(results);
4462
}
4563

46-
public void execute(Recipe... visitors) {
47-
for (Recipe recipe : visitors) {
64+
/**
65+
* Applies the provided {@code Recipe}s to all Maven build files in the {@code ProjectContext}.
66+
*
67+
* The changes are immediately reflected in the wrapping {@code BuildFile}s.
68+
*/
69+
public void execute(Recipe... recipes) {
70+
for (Recipe recipe : recipes) {
4871
List<Result> results = executeRecipe(recipe);
4972
processResults(results);
5073
}
5174
}
5275

76+
/**
77+
* Applies the provided {@code Recipe}s to the provided Maven build file.
78+
*
79+
* The changes are immediately reflected in the wrapping {@code BuildFile}.
80+
* A caller must decide if refreshing the Pom files in {@code ProjectContext} is required after this method.
81+
*/
82+
public <V extends TreeVisitor<?, ExecutionContext>> void execute(RewriteSourceFileHolder<Xml.Document> resource, Recipe... recipes) {
83+
for (Recipe recipe : recipes) {
84+
List<Result> results = executeRecipe(recipe, resource);
85+
processResults(results);
86+
}
87+
}
88+
89+
public void refreshPomModels() {
90+
// store buildfiles and their index in project resource list
91+
List<BuildFileWithIndex> buildFilesWithIndex = new ArrayList<>();
92+
List<RewriteSourceFileHolder<? extends SourceFile>> projectResources = projectResourceSet.list();
93+
for(RewriteSourceFileHolder<? extends SourceFile> sf : projectResources) {
94+
if(isMavenBuildFile(sf)) {
95+
int index = projectResources.indexOf(sf);
96+
Xml.Document xmlDoc = (Xml.Document) sf.getSourceFile();
97+
buildFilesWithIndex.add(new BuildFileWithIndex(index, (RewriteSourceFileHolder<Xml.Document>) sf));
98+
}
99+
}
100+
101+
// create parser inputs from buildfiles content
102+
List<Parser.Input> parserInputs = buildFilesWithIndex
103+
.stream()
104+
.map(BuildFileWithIndex::getXmlDoc)
105+
.map(m -> new Parser.Input(m.getSourcePath(), null, () -> new ByteArrayInputStream(
106+
m.print().getBytes(StandardCharsets.UTF_8)), !Files.exists(m.getSourcePath())))
107+
.collect(Collectors.toList());
108+
109+
// parse buildfiles
110+
List<Xml.Document> newMavenFiles = mavenParser.parseInputs(parserInputs, null, new RewriteExecutionContext());
111+
112+
// replace new model in build files
113+
newMavenFiles.stream()
114+
.forEach(mf -> {
115+
replaceModelInBuildFile(projectResources, buildFilesWithIndex, newMavenFiles, mf);
116+
});
117+
}
118+
119+
private void replaceModelInBuildFile(
120+
List<RewriteSourceFileHolder<? extends SourceFile>> projectResources,
121+
List<BuildFileWithIndex> buildFilesWithIndex,
122+
List<Xml.Document> newMavenFiles,
123+
Xml.Document mf
124+
) {
125+
// get index in list of build files
126+
int indexInNewMavenFiles = newMavenFiles.indexOf(mf);
127+
RewriteSourceFileHolder<Xml.Document> originalPom = buildFilesWithIndex.get(indexInNewMavenFiles).getXmlDoc();
128+
int indexInProjectResources = projectResources.indexOf(originalPom);
129+
// replace marker
130+
Markers markers = originalPom.getSourceFile().getMarkers().removeByType(MavenResolutionResult.class);
131+
MavenResolutionResult updatedModel = mf.getMarkers().findFirst(MavenResolutionResult.class).get();
132+
markers = markers.addIfAbsent(updatedModel);
133+
Xml.Document refreshedPom = originalPom.getSourceFile().withMarkers(markers);
134+
RewriteSourceFileHolder<Xml.Document> rewriteSourceFileHolder = (RewriteSourceFileHolder<Xml.Document>) projectResources.get(indexInProjectResources);
135+
rewriteSourceFileHolder.replaceWith(refreshedPom);
136+
}
137+
138+
private boolean isMavenBuildFile(RewriteSourceFileHolder<? extends SourceFile> sf) {
139+
return Xml.Document.class.isInstance(sf.getSourceFile()) && Xml.Document.class.cast(sf.getSourceFile()).getMarkers().findFirst(MavenResolutionResult.class).isPresent();
140+
}
141+
142+
@Getter
143+
class BuildFileWithIndex {
144+
private final int index;
145+
private final RewriteSourceFileHolder<Xml.Document> xmlDoc;
146+
147+
public BuildFileWithIndex(int index, RewriteSourceFileHolder<Xml.Document> xmlDoc) {
148+
149+
this.index = index;
150+
this.xmlDoc = xmlDoc;
151+
}
152+
}
153+
53154
private List<Result> executeRecipe(Recipe recipe) {
54-
List<Result> results = recipe.run(List.of(pom.getSourceFile()), new RewriteExecutionContext()).getResults();
155+
List<Result> results = recipe.run(getDocumentsWrappedInOpenRewriteMavenBuildFile(), new RewriteExecutionContext()).getResults();
156+
return results;
157+
}
158+
159+
private List<Result> executeRecipe(Recipe recipe, RewriteSourceFileHolder<Xml.Document> resource) {
160+
List<Result> results = recipe.run(List.of(resource.getSourceFile()), new RewriteExecutionContext()).getResults();
55161
return results;
56162
}
57163

164+
private List<Xml.Document> getDocumentsWrappedInOpenRewriteMavenBuildFile() {
165+
return getOpenRewriteMavenBuildFiles()
166+
.stream()
167+
.map(bf -> bf.getSourceFile())
168+
.collect(Collectors.toList());
169+
}
170+
171+
@NotNull
172+
private List<OpenRewriteMavenBuildFile> getOpenRewriteMavenBuildFiles() {
173+
return this.projectResourceSet
174+
.stream()
175+
.filter(r -> OpenRewriteMavenBuildFile.class.isInstance(r))
176+
.map(OpenRewriteMavenBuildFile.class::cast)
177+
.collect(Collectors.toList());
178+
}
179+
58180
private void processResults(List<Result> results) {
59181
if (!results.isEmpty()) {
60-
// FIXME: Works only on a single POM and does not apply to all other resources
61-
pom.replaceWith((Xml.Document) results.get(0).getAfter());
62-
// results.forEach(c -> processResult(c));
182+
results.forEach(r -> {
183+
if(!(r.getAfter() instanceof Xml.Document)) {
184+
throw new RuntimeException("Return type of refactoring result is not Xml.Document but " + r.getAfter().getClass() + " with content: \n" + r.getAfter().printAll());
185+
}
186+
OpenRewriteMavenBuildFile openRewriteMavenBuildFile = getOpenRewriteMavenBuildFiles()
187+
.stream()
188+
.filter(bf -> bf.getSourceFile().getId().equals(r.getAfter().getId()))
189+
.findFirst()
190+
.orElseThrow(() -> new RuntimeException("Could not find a BuildFile that wraps Xml.Document with id '%s' in the Result.".formatted(r.getAfter().getId())));
191+
openRewriteMavenBuildFile.replaceWith((Xml.Document) r.getAfter());
192+
});
63193
}
64194
}
65195

66-
private void processResult(Result result) {
67-
MavenParser parser = MavenParser
68-
.builder()
69-
.build();
70-
Xml.Document wrappedMavenFile = parser.parse(result.getAfter().printAll()).get(0);
71-
wrappedMavenFile = (Xml.Document) wrappedMavenFile.withSourcePath(pom.getSourceFile().getSourcePath());
72-
pom.replaceWith(wrappedMavenFile);
73-
}
74196
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
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 lombok.RequiredArgsConstructor;
19+
import org.openrewrite.xml.tree.Xml;
20+
import org.springframework.sbm.project.resource.ProjectResourceSetHolder;
21+
import org.springframework.stereotype.Component;
22+
23+
/**
24+
* @author Fabian Krüger
25+
*/
26+
@Component
27+
@RequiredArgsConstructor
28+
public class MavenBuildFileRefactoringFactory {
29+
private final ProjectResourceSetHolder projectResourceSetHolder;
30+
private final RewriteMavenParser rewriteMavenParser;
31+
32+
public MavenBuildFileRefactoring createRefactoring() {
33+
return new MavenBuildFileRefactoring<Xml.Document>(projectResourceSetHolder.getProjectResourceSet(), rewriteMavenParser);
34+
}
35+
}

0 commit comments

Comments
 (0)