Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use maven embedder #68

Draft
wants to merge 76 commits into
base: main
Choose a base branch
from
Draft
Changes from 1 commit
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
bcab57a
Extract test helper module
fabapp2 Mar 18, 2024
6edd20d
Cloned MavenCli compiles
fabapp2 Feb 8, 2024
e97d2a9
It seems to build a Maven project
fabapp2 Feb 8, 2024
1a415ba
here we go...
fabapp2 Feb 8, 2024
2cb3d1d
Project builds with custom MavenCi and events are listened to
fabapp2 Feb 9, 2024
91e0a94
Remove methods not required anymore
fabapp2 Feb 9, 2024
3c5c011
Successfully creates MavenMojoProjectParser
fabapp2 Feb 9, 2024
0fcff35
Replaced reflection with setter
fabapp2 Feb 9, 2024
6a372ac
Remove tests
fabapp2 Feb 9, 2024
a7eaa6e
Cleanup
fabapp2 Feb 9, 2024
ba17f27
Comment
fabapp2 Feb 9, 2024
32cf76a
Comment
fabapp2 Feb 9, 2024
3afc9f8
Comment
fabapp2 Feb 9, 2024
50f16d3
Cleanup
fabapp2 Feb 9, 2024
ee64fee
Cleanup
fabapp2 Feb 9, 2024
5129a92
Runs inside Spring Boot application
fabapp2 Feb 9, 2024
f05adbc
Move testcode into module
fabapp2 Feb 19, 2024
938ef6a
Test that settings are read
fabapp2 Feb 19, 2024
eaeb6f1
WIP
fabapp2 Feb 20, 2024
4e28119
Add test
fabapp2 Feb 20, 2024
221423a
Rename module
fabapp2 Feb 20, 2024
4fdef37
Rename module and add to reactor
fabapp2 Feb 20, 2024
175c66b
Add name to pom
fabapp2 Feb 20, 2024
a15004d
Format code
fabapp2 Feb 20, 2024
7bbfa2c
Introduce maven embedder to launcher
fabapp2 Feb 20, 2024
e8a875f
Format Java
fabapp2 Feb 21, 2024
c55a19b
Adjust limitations section in docs
fabapp2 Feb 21, 2024
d882df6
Remove unrelated docs
fabapp2 Feb 21, 2024
4c68ad1
Fix comment
fabapp2 Feb 21, 2024
1e24718
Replace deprecated class
fabapp2 Feb 21, 2024
7df7c0a
Retrieve PlexusContainer from Maven Session
fabapp2 Feb 21, 2024
c3d8c33
Remove default profile
fabapp2 Feb 21, 2024
5224dab
Format Java
fabapp2 Feb 21, 2024
c9b387d
Remove outdated MavenExecutor
fabapp2 Feb 21, 2024
779669a
Remove obsolete classes
fabapp2 Feb 21, 2024
7e3120c
Format Java
fabapp2 Feb 21, 2024
50abe34
Use soft assertions again
fabapp2 Feb 21, 2024
6a638c3
Add another OpenRewriteProjectParser reusing as much as possible
fabapp2 Feb 21, 2024
42b28d0
Format Java
fabapp2 Feb 22, 2024
8568e5c
License header
fabapp2 Feb 22, 2024
d0d3eba
Format Java
fabapp2 Feb 22, 2024
b5eb2f2
Fix tests
fabapp2 Feb 22, 2024
0a07ab8
Fix test, parsing in parallel not possible anymore
fabapp2 Feb 22, 2024
5933a36
Inject ArtifactDownloader
fabapp2 Feb 22, 2024
44b7a95
Fix Maven event handling for multi module projects
fabapp2 Feb 22, 2024
cce916b
Format Java
fabapp2 Feb 22, 2024
a39c53e
Use softAssertion
fabapp2 Feb 22, 2024
59f93cc
Fix dependency versions
fabapp2 Feb 22, 2024
6d0b606
MavenExecutor does not resolve dependencies in reactor build
fabapp2 Feb 22, 2024
a4811c6
Rename package
fabapp2 Feb 22, 2024
ea590f0
Fix test
fabapp2 Feb 22, 2024
28a6e80
Rename test
fabapp2 Feb 22, 2024
cee971d
Bump maven-embedder
fabapp2 Feb 22, 2024
0171aaf
USe Boot version property form root
fabapp2 Feb 22, 2024
90c8660
Use new parser in tests as comparing parser
fabapp2 Feb 23, 2024
ace559a
Use MavenInvoker to see if the dependencies are resolved.
fabapp2 Feb 23, 2024
1c27fa8
Fix MavenProject mapping
fabapp2 Feb 23, 2024
e8f3540
Add rewrite bom
fabapp2 Feb 23, 2024
97010c9
Format Java
fabapp2 Feb 23, 2024
ab01d3d
Remove version conflicts
fabapp2 Feb 23, 2024
85c46ec
Unified Maven dependency versions
fabapp2 Feb 26, 2024
a6f00f3
Add original author
fabapp2 Feb 26, 2024
de6bc91
Wip
fabapp2 Feb 28, 2024
65046fb
README
fabapp2 Mar 5, 2024
df3b532
Format
fabapp2 Mar 6, 2024
fb91a75
Make build (use-maven-embedder)
fabapp2 Mar 18, 2024
fac2030
Adjust API call
fabapp2 Mar 19, 2024
3f92c5b
Use dynamic port in test
fabapp2 Mar 22, 2024
e4c796a
Remove MavenProjectAnalyzer
fabapp2 Mar 22, 2024
1925e04
Fix test
fabapp2 Mar 22, 2024
8b44485
Fix execution listener in MavenInvoker
fabapp2 Mar 22, 2024
c78d86f
Add scope to dep
fabapp2 Mar 22, 2024
4fcf7d0
Add code to test project
fabapp2 Mar 22, 2024
5d7e39e
Use RuntimeInformation from Maven
fabapp2 Mar 22, 2024
4244f98
Fix tst project
fabapp2 Mar 22, 2024
0d535c4
Add info to println
fabapp2 Mar 25, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Format Java
fabapp2 committed Mar 18, 2024
commit 42b28d0727dc7f6b95de2abe77aee4b23b99e27c
Original file line number Diff line number Diff line change
@@ -50,131 +50,148 @@
*/
public class OpenRewriteProjectParser {

private final SpringRewriteProperties properties;
private final ExecutionContext executionContext;

public OpenRewriteProjectParser(SpringRewriteProperties properties, ExecutionContext executionContext) {
this.properties = properties;
this.executionContext = executionContext;
}

public RewriteProjectParsingResult parse(Path givenBaseDir) {

AtomicReference<List<SourceFile>> mavenSessionRef = new AtomicReference<>();
new MavenExecutor(executionEvent -> {
MavenSession mavenSession = executionEvent.getSession();
Log logger = new Slf4jToMavenLoggerAdapter(LoggerFactory.getLogger("OpenRewriteProjectParser"));
boolean pomCacheEnabled = properties.isPomCacheEnabled();
@Nullable String pomCacheDirectory = properties.getPomCacheDirectory();
Class<RuntimeInformation> aClass = RuntimeInformation.class;
RuntimeInformation runtimeInformation = lookup(mavenSession.getContainer(), aClass);
boolean skipMavenParsing = properties.isSkipMavenParsing();
Collection<String> exclusions = properties.getIgnoredPathPatterns();
Collection<String> plainTextMasks = properties.getPlainTextMasks();
int sizeThresholdMb = properties.getSizeThresholdMb();
SettingsDecrypter settingsDecrypter = lookup(mavenSession.getContainer(), SettingsDecrypter.class);
boolean runPerSubmodule = properties.isRunPerSubmodule();
boolean parseAdditionalResources = properties.isParseAdditionalResources();

MavenMojoProjectParser mojoProjectParser = new MavenMojoProjectParser(logger, givenBaseDir, pomCacheEnabled, pomCacheDirectory, runtimeInformation, skipMavenParsing, exclusions, plainTextMasks, sizeThresholdMb, mavenSession, settingsDecrypter, runPerSubmodule, parseAdditionalResources);
FakedRewriteRunMojo fakedRewriteRunMojo = FakedRewriteRunMojo.from(mavenSession);
Environment env = Environment.builder().build();
try {
// LargeSoruceSet hides access to source files
// LargeSourceSet largeSourceSet = fakedRewriteRunMojo.loadSourceSet(givenBaseDir, env, executionContext);
List<SourceFile> sourceFiles = fakedRewriteRunMojo.loadSources(givenBaseDir, env, executionContext);
mavenSessionRef.set(sourceFiles);
} catch (DependencyResolutionRequiredException e) {
throw new RuntimeException(e);
} catch (MojoExecutionException e) {
throw new RuntimeException(e);
}
}).execute(List.of("clean", "package", "--fail-at-end"), givenBaseDir);

RewriteProjectParsingResult parsingResult = new RewriteProjectParsingResult(mavenSessionRef.get(), executionContext);

return parsingResult;
}

private static <T> T lookup(PlexusContainer plexusContainer, Class<T> aClass) {
try {
return plexusContainer.lookup(aClass);
} catch (ComponentLookupException e) {
throw new RuntimeException(e);
}
}

private static class FakedRewriteRunMojo extends AbstractRewriteDryRunMojo {
private final MavenSession mavenSession1;

public FakedRewriteRunMojo(MavenSession mavenSession) {
mavenSession1 = mavenSession;
}

public static FakedRewriteRunMojo from(MavenSession mavenSession) {
FakedRewriteRunMojo fakedRewriteRunMojo = new FakedRewriteRunMojo(mavenSession);
// project
setField(fakedRewriteRunMojo, "project", mavenSession.getCurrentProject());
// runtime
PlexusContainer plexusContainer = mavenSession.getContainer();
RuntimeInformation runtimeInformation = lookup(plexusContainer, RuntimeInformation.class);
setField(fakedRewriteRunMojo, "runtime", runtimeInformation);
setField(fakedRewriteRunMojo, "mavenSession", mavenSession);
setField(fakedRewriteRunMojo, "settingsDecrypter", lookup(plexusContainer, SettingsDecrypter.class));
return fakedRewriteRunMojo;
}

private static void setField(FakedRewriteRunMojo fakedRewriteRunMojo, String fieldName, Object value) {
Field project = ReflectionUtils.findField(FakedRewriteRunMojo.class, fieldName);
ReflectionUtils.makeAccessible(project);
ReflectionUtils.setField(project, fakedRewriteRunMojo, value);
}

@Override
public ResultsContainer listResults(ExecutionContext ctx) {
try {
super.project = mavenSession.getCurrentProject();
return super.listResults(ctx);
} catch (MojoExecutionException e) {
throw new RuntimeException(e);
}
}

public List<SourceFile> loadSources(Path repositoryRoot, Environment env, ExecutionContext ctx) throws DependencyResolutionRequiredException, MojoExecutionException {
List<NamedStyles> styles = loadStyles(project, env);

//Parse and collect source files from each project in the maven session.
MavenMojoProjectParser projectParser = new MavenMojoProjectParser(getLog(), repositoryRoot, pomCacheEnabled, pomCacheDirectory, runtime, skipMavenParsing, getExclusions(), getPlainTextMasks(), sizeThresholdMb, mavenSession, settingsDecrypter, runPerSubmodule, true);

Stream<SourceFile> sourceFiles = projectParser.listSourceFiles(project, styles, ctx);
Method m = ReflectionUtils.findMethod(AbstractRewriteMojo.class, "sourcesWithAutoDetectedStyles", Stream.class);
ReflectionUtils.makeAccessible(m);
List<SourceFile> sourceFileList = (List<SourceFile>) ReflectionUtils.invokeMethod(m, this, sourceFiles);
return sourceFileList;
}
}

/**
* Container for gathered Maven runtime information required for parsing.
*/
private record MavenRuntimeInformation(RuntimeInformation runtimeInformation) {

public static MavenRuntimeInformation gathering(MavenSession mavenSession) {

RuntimeInformation runtimeInformation = lookup(mavenSession.getContainer(), RuntimeInformation.class);


MavenRuntimeInformation mavenRuntimeInformation = new MavenRuntimeInformation(runtimeInformation);
return mavenRuntimeInformation;
}

private static <T> T lookup(PlexusContainer plexusContainer, Class<T> aClass) {
try {
return plexusContainer.lookup(aClass);
} catch (ComponentLookupException e) {
throw new RuntimeException(e);
}
}

}
private final SpringRewriteProperties properties;

private final ExecutionContext executionContext;

public OpenRewriteProjectParser(SpringRewriteProperties properties, ExecutionContext executionContext) {
this.properties = properties;
this.executionContext = executionContext;
}

public RewriteProjectParsingResult parse(Path givenBaseDir) {

AtomicReference<List<SourceFile>> mavenSessionRef = new AtomicReference<>();
new MavenExecutor(executionEvent -> {
MavenSession mavenSession = executionEvent.getSession();
Log logger = new Slf4jToMavenLoggerAdapter(LoggerFactory.getLogger("OpenRewriteProjectParser"));
boolean pomCacheEnabled = properties.isPomCacheEnabled();
@Nullable
String pomCacheDirectory = properties.getPomCacheDirectory();
Class<RuntimeInformation> aClass = RuntimeInformation.class;
RuntimeInformation runtimeInformation = lookup(mavenSession.getContainer(), aClass);
boolean skipMavenParsing = properties.isSkipMavenParsing();
Collection<String> exclusions = properties.getIgnoredPathPatterns();
Collection<String> plainTextMasks = properties.getPlainTextMasks();
int sizeThresholdMb = properties.getSizeThresholdMb();
SettingsDecrypter settingsDecrypter = lookup(mavenSession.getContainer(), SettingsDecrypter.class);
boolean runPerSubmodule = properties.isRunPerSubmodule();
boolean parseAdditionalResources = properties.isParseAdditionalResources();

MavenMojoProjectParser mojoProjectParser = new MavenMojoProjectParser(logger, givenBaseDir, pomCacheEnabled,
pomCacheDirectory, runtimeInformation, skipMavenParsing, exclusions, plainTextMasks,
sizeThresholdMb, mavenSession, settingsDecrypter, runPerSubmodule, parseAdditionalResources);
FakedRewriteRunMojo fakedRewriteRunMojo = FakedRewriteRunMojo.from(mavenSession);
Environment env = Environment.builder().build();
try {
// LargeSoruceSet hides access to source files
// LargeSourceSet largeSourceSet =
// fakedRewriteRunMojo.loadSourceSet(givenBaseDir, env, executionContext);
List<SourceFile> sourceFiles = fakedRewriteRunMojo.loadSources(givenBaseDir, env, executionContext);
mavenSessionRef.set(sourceFiles);
}
catch (DependencyResolutionRequiredException e) {
throw new RuntimeException(e);
}
catch (MojoExecutionException e) {
throw new RuntimeException(e);
}
}).execute(List.of("clean", "package", "--fail-at-end"), givenBaseDir);

RewriteProjectParsingResult parsingResult = new RewriteProjectParsingResult(mavenSessionRef.get(),
executionContext);

return parsingResult;
}

private static <T> T lookup(PlexusContainer plexusContainer, Class<T> aClass) {
try {
return plexusContainer.lookup(aClass);
}
catch (ComponentLookupException e) {
throw new RuntimeException(e);
}
}

private static class FakedRewriteRunMojo extends AbstractRewriteDryRunMojo {

private final MavenSession mavenSession1;

public FakedRewriteRunMojo(MavenSession mavenSession) {
mavenSession1 = mavenSession;
}

public static FakedRewriteRunMojo from(MavenSession mavenSession) {
FakedRewriteRunMojo fakedRewriteRunMojo = new FakedRewriteRunMojo(mavenSession);
// project
setField(fakedRewriteRunMojo, "project", mavenSession.getCurrentProject());
// runtime
PlexusContainer plexusContainer = mavenSession.getContainer();
RuntimeInformation runtimeInformation = lookup(plexusContainer, RuntimeInformation.class);
setField(fakedRewriteRunMojo, "runtime", runtimeInformation);
setField(fakedRewriteRunMojo, "mavenSession", mavenSession);
setField(fakedRewriteRunMojo, "settingsDecrypter", lookup(plexusContainer, SettingsDecrypter.class));
return fakedRewriteRunMojo;
}

private static void setField(FakedRewriteRunMojo fakedRewriteRunMojo, String fieldName, Object value) {
Field project = ReflectionUtils.findField(FakedRewriteRunMojo.class, fieldName);
ReflectionUtils.makeAccessible(project);
ReflectionUtils.setField(project, fakedRewriteRunMojo, value);
}

@Override
public ResultsContainer listResults(ExecutionContext ctx) {
try {
super.project = mavenSession.getCurrentProject();
return super.listResults(ctx);
}
catch (MojoExecutionException e) {
throw new RuntimeException(e);
}
}

public List<SourceFile> loadSources(Path repositoryRoot, Environment env, ExecutionContext ctx)
throws DependencyResolutionRequiredException, MojoExecutionException {
List<NamedStyles> styles = loadStyles(project, env);

// Parse and collect source files from each project in the maven session.
MavenMojoProjectParser projectParser = new MavenMojoProjectParser(getLog(), repositoryRoot, pomCacheEnabled,
pomCacheDirectory, runtime, skipMavenParsing, getExclusions(), getPlainTextMasks(), sizeThresholdMb,
mavenSession, settingsDecrypter, runPerSubmodule, true);

Stream<SourceFile> sourceFiles = projectParser.listSourceFiles(project, styles, ctx);
Method m = ReflectionUtils.findMethod(AbstractRewriteMojo.class, "sourcesWithAutoDetectedStyles",
Stream.class);
ReflectionUtils.makeAccessible(m);
List<SourceFile> sourceFileList = (List<SourceFile>) ReflectionUtils.invokeMethod(m, this, sourceFiles);
return sourceFileList;
}

}

/**
* Container for gathered Maven runtime information required for parsing.
*/
private record MavenRuntimeInformation(RuntimeInformation runtimeInformation) {

public static MavenRuntimeInformation gathering(MavenSession mavenSession) {

RuntimeInformation runtimeInformation = lookup(mavenSession.getContainer(), RuntimeInformation.class);

MavenRuntimeInformation mavenRuntimeInformation = new MavenRuntimeInformation(runtimeInformation);
return mavenRuntimeInformation;
}

private static <T> T lookup(PlexusContainer plexusContainer, Class<T> aClass) {
try {
return plexusContainer.lookup(aClass);
}
catch (ComponentLookupException e) {
throw new RuntimeException(e);
}
}

}

}
Original file line number Diff line number Diff line change
@@ -15,10 +15,12 @@
*/
package org.springframework.rewrite;

import org.apache.maven.execution.ExecutionEvent;
import org.jetbrains.annotations.NotNull;
import org.openrewrite.ExecutionContext;
import org.openrewrite.SourceFile;
import org.openrewrite.marker.Marker;
import org.openrewrite.maven.utilities.MavenArtifactDownloader;
import org.openrewrite.style.NamedStyles;
import org.openrewrite.tree.ParsingEventListener;
import org.openrewrite.tree.ParsingExecutionContextView;
@@ -27,7 +29,9 @@
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.rewrite.maveninvokerplayground.MavenExecutor;
import org.springframework.rewrite.parser.*;
import org.springframework.rewrite.parser.events.StartedParsingProjectEvent;
import org.springframework.rewrite.parser.events.SuccessfullyParsedProjectEvent;
@@ -38,10 +42,12 @@
import org.springframework.rewrite.scopes.ScanScope;
import org.springframework.util.StringUtils;

import java.io.File;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;

/**
* Project parser parsing resources under a given {@link Path} to OpenRewrite Lossless
@@ -94,6 +100,8 @@ public class RewriteProjectParser {

private final MavenProjectAnalyzer mavenProjectAnalyzer;

private MavenArtifactDownloader artifactDownloader;

public RewriteProjectParser(ProvenanceMarkerFactory provenanceMarkerFactory, MavenBuildFileParser buildFileParser,
SourceFileParser sourceFileParser, StyleDetector styleDetector,
SpringRewriteProperties springRewriteProperties, ParsingEventListener parsingEventListener,
@@ -137,9 +145,25 @@ public RewriteProjectParsingResult parse(Path givenBaseDir, List<Resource> resou
// TODO: See ConfigurableRewriteMojo#getPlainTextMasks()
// TODO: where to retrieve styles from? --> see
// AbstractRewriteMojo#getActiveStyles() & AbstractRewriteMojo#loadStyles()

AtomicReference<List<SourceFile>> sourceFilesRef = new AtomicReference<>();
new MavenExecutor(onSuccess -> {
List<SourceFile> sourceFiles = runInMavenSession(onSuccess, baseDir, resources);
sourceFilesRef.set(sourceFiles);
}).execute(List.of("clean", "package", "--fail-at-end"), baseDir);

return new RewriteProjectParsingResult(sourceFilesRef.get(), executionContext);
}

private List<SourceFile> runInMavenSession(ExecutionEvent onSuccess, Path baseDir, List<Resource> resources) {
List<NamedStyles> styles = List.of();
onSuccess.getSession()
.getProjectDependencyGraph()
.getSortedProjects()
.stream()
.map(p -> this.mavenProjectToMavenProject(p, resources))
.toList();

// Get the ordered otherSourceFiles of projects
List<MavenProject> sortedProjects = mavenProjectAnalyzer.getBuildProjects(baseDir, resources);
ParserContext parserContext = new ParserContext(baseDir, resources, sortedProjects);

@@ -169,8 +193,16 @@ public RewriteProjectParsingResult parse(Path givenBaseDir, List<Resource> resou
List<SourceFile> sourceFiles = styleDetector.sourcesWithAutoDetectedStyles(resultingList.stream());

eventPublisher.publishEvent(new SuccessfullyParsedProjectEvent(sourceFiles));
return sourceFiles;
}

return new RewriteProjectParsingResult(sourceFiles, executionContext);
private MavenProject mavenProjectToMavenProject(org.apache.maven.project.MavenProject mavenProject,
MavenArtifactDownloader artifactDownloader, List<Resource> resources) {
Path baseDir = mavenProject.getBasedir().toPath();
File file = mavenProject.getExecutionProject().getFile();
Resource rootPom = new FileSystemResource(file);
new MavenProject(baseDir, rootPom, artifactDownloader, resources);
return null;
}

@NotNull
Original file line number Diff line number Diff line change
@@ -41,7 +41,8 @@ RewriteRecipeLauncher rewriteRecipeLauncher(RewriteProjectParser parser, Rewrite
}

@Bean
OpenRewriteProjectParser openRewriteProjectParser(SpringRewriteProperties properties, ExecutionContext executionContext) {
OpenRewriteProjectParser openRewriteProjectParser(SpringRewriteProperties properties,
ExecutionContext executionContext) {
return new OpenRewriteProjectParser(properties, executionContext);
}

Original file line number Diff line number Diff line change
@@ -317,7 +317,8 @@ static void verifyEqualSourceFileMarkers(SourceFile curExpectedSourceFile, Sourc

static void compareMavenResolutionResultMarker(SoftAssertions softAssertions, MavenResolutionResult expected,
MavenResolutionResult actual) {
softAssertions.assertThat(actual).usingRecursiveComparison()
softAssertions.assertThat(actual)
.usingRecursiveComparison()
.withEqualsForFieldsMatchingRegexes(customRepositoryEquals("mavenSettings.localRepository"),
"mavenSettings.localRepository", ".*\\.repository", "mavenSettings.mavenLocal.uri")
.ignoringFields("modules", // checked further down