From c6afc4a03e6dd13bca496c8a5fd2fd24d3d74c04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Kr=C3=BCger?= Date: Tue, 26 Sep 2023 14:31:31 +0200 Subject: [PATCH 01/14] WIP: Calculate reactor build order - Replace MavenProject - Provide Analyzer for order and test - Missing: Maven plugin order and tests --- .../MavenMojoProjectParserPrivateMethods.java | 70 ++- .../sbm/parsers/ProvenanceMarkerFactory.java | 8 +- .../parsers/RewriteParserConfiguration.java | 21 +- .../sbm/parsers/RewriteProjectParser.java | 23 +- .../sbm/parsers/SortedProjects.java | 2 +- .../sbm/parsers/SourceFileParser.java | 5 +- .../sbm/parsers/maven/MavenProject.java | 85 +++ .../parsers/maven/MavenProjectAnalyzer.java | 374 ++++++++++++ .../maven/MavenProvenanceMarkerFactory.java | 29 + .../parsers/ProvenanceMarkerFactoryTest.java | 24 +- .../RewriteMavenProjectParserTest.java | 7 +- .../sbm/parsers/RewriteProjectParserTest.java | 7 +- .../maven/MavenProjectAnalyzerTest.java | 570 ++++++++++++++++++ 13 files changed, 1145 insertions(+), 80 deletions(-) create mode 100644 sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/maven/MavenProject.java create mode 100644 sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/maven/MavenProjectAnalyzer.java create mode 100644 sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/maven/MavenProvenanceMarkerFactory.java create mode 100644 sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/maven/MavenProjectAnalyzerTest.java diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenMojoProjectParserPrivateMethods.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenMojoProjectParserPrivateMethods.java index 4fabc7610..414439942 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenMojoProjectParserPrivateMethods.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenMojoProjectParserPrivateMethods.java @@ -17,7 +17,6 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.apache.maven.project.MavenProject; import org.apache.maven.rtinfo.internal.DefaultRuntimeInformation; import org.apache.maven.settings.crypto.DefaultSettingsDecrypter; import org.jetbrains.annotations.NotNull; @@ -34,6 +33,7 @@ import org.sonatype.plexus.components.cipher.DefaultPlexusCipher; import org.sonatype.plexus.components.cipher.PlexusCipherException; import org.sonatype.plexus.components.sec.dispatcher.DefaultSecDispatcher; +import org.springframework.sbm.parsers.maven.MavenProject; import org.springframework.util.ReflectionUtils; import java.lang.reflect.Method; @@ -57,10 +57,11 @@ class MavenMojoProjectParserPrivateMethods { private final MavenArtifactDownloader artifactDownloader; /** - * Calls {@link MavenMojoProjectParser#processMainSources(MavenProject, JavaParser.Builder, ResourceParser, List, Set, ExecutionContext)} */ public List processMainSources(Path baseDir, Xml.Document moduleBuildFile, JavaParser.Builder javaParserBuilder, ResourceParser rp, List provenanceMarkers, Set alreadyParsed, ExecutionContext executionContext, MavenProject mavenProject) { - return invokeProcessMethod(baseDir, mavenProject, moduleBuildFile, javaParserBuilder, rp, provenanceMarkers, alreadyParsed, executionContext, "processMainSources"); + // FIXME: 945 + return null; +// return invokeProcessMethod(baseDir, mavenProject, moduleBuildFile, javaParserBuilder, rp, provenanceMarkers, alreadyParsed, executionContext, "processMainSources"); } /** @@ -76,7 +77,8 @@ public List processTestSources(Path baseDir, Xml.Document moduleBuil @NotNull private List invokeProcessMethod( Path baseDir, - MavenProject mavenProject, Xml.Document moduleBuildFile, + MavenProject mavenProject, + Xml.Document moduleBuildFile, JavaParser.Builder javaParserBuilder, ResourceParser rp, List provenanceMarkers, @@ -84,35 +86,37 @@ private List invokeProcessMethod( ExecutionContext executionContext, String methodName ) { - MavenMojoProjectParser mavenMojoProjectParser = createMavenMojoProjectParser(baseDir); - Method method = ReflectionUtils.findMethod( - MavenMojoProjectParser.class, - methodName, - MavenProject.class, - JavaParser.Builder.class, - ResourceParser.class, - List.class, - Set.class, - ExecutionContext.class); - ReflectionUtils.makeAccessible(method); - if (method == null) { - throw new IllegalStateException("Could not find method '%s' on %s while trying to call it.".formatted(methodName, MavenMojoProjectParser.class.getName())); - } - log.debug("Starting reflective call to %s.%s()".formatted(mavenMojoProjectParser.getClass().getName(), method.getName())); - Object result = ReflectionUtils.invokeMethod(method, mavenMojoProjectParser, - mavenProject, - javaParserBuilder, - rp, - provenanceMarkers, - alreadyParsed, - executionContext - ); - if (result instanceof Stream) { - List sourceFiles = ((Stream) result).toList(); - return sourceFiles; - } else { - throw new RuntimeException("Could not cast result returned from MavenMojoParser#methodName to Stream."); - } + // FIXME: #945 + return null; +// MavenMojoProjectParser mavenMojoProjectParser = createMavenMojoProjectParser(baseDir); +// Method method = ReflectionUtils.findMethod( +// MavenMojoProjectParser.class, +// methodName, +// MavenProject.class, +// JavaParser.Builder.class, +// ResourceParser.class, +// List.class, +// Set.class, +// ExecutionContext.class); +// ReflectionUtils.makeAccessible(method); +// if (method == null) { +// throw new IllegalStateException("Could not find method '%s' on %s while trying to call it.".formatted(methodName, MavenMojoProjectParser.class.getName())); +// } +// log.debug("Starting reflective call to %s.%s()".formatted(mavenMojoProjectParser.getClass().getName(), method.getName())); +// Object result = ReflectionUtils.invokeMethod(method, mavenMojoProjectParser, +// mavenProject, +// javaParserBuilder, +// rp, +// provenanceMarkers, +// alreadyParsed, +// executionContext +// ); +// if (result instanceof Stream) { +// List sourceFiles = ((Stream) result).toList(); +// return sourceFiles; +// } else { +// throw new RuntimeException("Could not cast result returned from MavenMojoParser#methodName to Stream."); +// } } diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/ProvenanceMarkerFactory.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/ProvenanceMarkerFactory.java index 9820fac68..b04bd3b8a 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/ProvenanceMarkerFactory.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/ProvenanceMarkerFactory.java @@ -23,8 +23,8 @@ import org.openrewrite.marker.Marker; import org.openrewrite.maven.MavenMojoProjectParser; import org.springframework.core.io.Resource; +import org.springframework.sbm.parsers.maven.MavenProvenanceMarkerFactory; import org.springframework.sbm.utils.ResourceUtil; -import org.springframework.stereotype.Component; import java.nio.file.Path; import java.util.*; @@ -35,7 +35,7 @@ @RequiredArgsConstructor class ProvenanceMarkerFactory { - private final MavenMojoProjectParserFactory mavenMojoProjectParserFactory; + private final MavenProvenanceMarkerFactory markerFactory; /** * Reuses {@link MavenMojoProjectParser#generateProvenance(MavenProject)} to create {@link Marker}s for pom files in @@ -48,11 +48,11 @@ public Map> generateProvenanceMarkers(Path baseDir, SortedPro RuntimeInformation runtimeInformation = new DefaultRuntimeInformation(); SettingsDecrypter settingsDecrypter = null; - MavenMojoProjectParser helper = mavenMojoProjectParserFactory.create(baseDir, runtimeInformation, settingsDecrypter); Map> result = new HashMap<>(); pomFileResources.getSortedProjects().forEach(mavenProject -> { - List markers = helper.generateProvenance(mavenProject); + + List markers = markerFactory.generateProvenance(mavenProject); Resource resource = pomFileResources.getMatchingBuildFileResource(mavenProject); Path path = ResourceUtil.getPath(resource); result.put(path, markers); diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteParserConfiguration.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteParserConfiguration.java index b173406ed..e5ae80831 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteParserConfiguration.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteParserConfiguration.java @@ -29,8 +29,8 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; import org.springframework.sbm.boot.autoconfigure.ParserPropertiesPostProcessor; -import org.springframework.sbm.boot.autoconfigure.ScannerConfiguration; import org.springframework.sbm.parsers.events.RewriteParsingEventListenerAdapter; +import org.springframework.sbm.parsers.maven.MavenProjectAnalyzer; import org.springframework.sbm.scopes.ProjectMetadata; import org.springframework.sbm.scopes.ScanScope; import org.springframework.sbm.boot.autoconfigure.ScopeConfiguration; @@ -81,10 +81,10 @@ MavenMojoProjectParserFactory projectParserFactory() { return new MavenMojoProjectParserFactory(parserProperties); } - @Bean - ProvenanceMarkerFactory provenanceMarkerFactory(MavenMojoProjectParserFactory projectParserFactory) { - return new ProvenanceMarkerFactory(projectParserFactory); - } +// @Bean +// ProvenanceMarkerFactory provenanceMarkerFactory(MavenMojoProjectParserFactory projectParserFactory) { +// return new ProvenanceMarkerFactory(projectParserFactory); +// } @Bean @org.springframework.sbm.scopes.annotations.ScanScope @@ -153,6 +153,11 @@ RewriteMavenProjectParser rewriteMavenProjectParser(MavenPlexusContainer plexusC executionContext); } + @Bean + MavenProjectAnalyzer mavenProjectAnalyzer() { + return new MavenProjectAnalyzer(); + } + @Bean RewriteProjectParser rewriteProjectParser( MavenExecutor mavenExecutor, @@ -166,7 +171,8 @@ RewriteProjectParser rewriteProjectParser( ScanScope scanScope, ConfigurableListableBeanFactory beanFactory, ProjectScanner projectScanner, - ExecutionContext executionContext) { + ExecutionContext executionContext, + MavenProjectAnalyzer mavenProjectAnalyzer) { return new RewriteProjectParser( mavenExecutor, provenanceMarkerFactory, @@ -179,7 +185,8 @@ RewriteProjectParser rewriteProjectParser( scanScope, beanFactory, projectScanner, - executionContext); + executionContext, + mavenProjectAnalyzer); } @Bean diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteProjectParser.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteProjectParser.java index 684e99d0c..4d2abc117 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteProjectParser.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteProjectParser.java @@ -20,9 +20,7 @@ import org.apache.maven.execution.MavenSession; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; -import org.apache.maven.project.MavenProject; import org.openrewrite.ExecutionContext; -import org.openrewrite.InMemoryExecutionContext; import org.openrewrite.SourceFile; import org.openrewrite.marker.Marker; import org.openrewrite.maven.AbstractRewriteMojo; @@ -38,9 +36,10 @@ import org.springframework.core.io.Resource; import org.springframework.sbm.parsers.events.SuccessfullyParsedProjectEvent; import org.springframework.sbm.parsers.events.StartedParsingProjectEvent; +import org.springframework.sbm.parsers.maven.MavenProject; +import org.springframework.sbm.parsers.maven.MavenProjectAnalyzer; import org.springframework.sbm.scopes.ScanScope; import org.springframework.sbm.utils.ResourceUtil; -import org.springframework.stereotype.Component; import org.springframework.util.ReflectionUtils; import java.lang.reflect.Method; @@ -91,6 +90,7 @@ public class RewriteProjectParser { private final ConfigurableListableBeanFactory beanFactory; private final ProjectScanner scanner; private final ExecutionContext executionContext; + private final MavenProjectAnalyzer mavenProjectAnalyzer; public RewriteProjectParsingResult parse(Path baseDir) { @@ -141,7 +141,10 @@ public RewriteProjectParsingResult parse(Path givenBaseDir, List resou withMavenSession(baseDir, mavenSession -> { // Get the ordered list of projects - List sortedProjectsList = mavenSession.getProjectDependencyGraph().getSortedProjects(); + // TODO: #945 - replace with custom sorter + // TODO: #945 Replace MavenProject + mavenSession.getProjectDependencyGraph().getSortedProjects(); + List sortedProjectsList = mavenProjectAnalyzer.getSortedProjects(baseDir, resources); // mavenSession.getProjectDependencyGraph().getSortedProjects(); // SortedProjects makes downstream components independent of Maven classes SortedProjects mavenInfos = new SortedProjects(resources, sortedProjectsList, List.of("default")); @@ -192,18 +195,6 @@ private static List autoDetectStyles(Stream sourceFilesS return sourceFiles; } -// private Stream parseToAst(Path baseDir, List resources, List styles, ExecutionContext executionContext) throws DependencyResolutionRequiredException, MojoExecutionException { -// MavenProject mavenProject = createFakeMavenProjectForProvenance(baseDir, resources, executionContext); -// return super.listSourceFiles(mavenProject, styles, executionContext); -// } - - private MavenProject createFakeMavenProjectForProvenance(Path baseDir, List resources, ExecutionContext executionContext) { - MavenProject mavenProject = new MavenProject(); - // Plugin compilerPlugin = mavenProject.getPlugin("org.apache.maven.plugins:maven-compiler-plugin"); - mavenProject.setPluginArtifacts(Set.of()); - return mavenProject; - } - /** * Extending {@code AbstractRewriteMojo} to open up protected method for reuse */ diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SortedProjects.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SortedProjects.java index 1174809f0..32ca54a0c 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SortedProjects.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SortedProjects.java @@ -17,8 +17,8 @@ import lombok.Getter; import org.apache.maven.model.Model; -import org.apache.maven.project.MavenProject; import org.springframework.core.io.Resource; +import org.springframework.sbm.parsers.maven.MavenProject; import org.springframework.sbm.utils.ResourceUtil; import java.io.File; diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SourceFileParser.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SourceFileParser.java index 757b64688..4f30b9742 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SourceFileParser.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SourceFileParser.java @@ -17,7 +17,6 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.apache.maven.project.MavenProject; import org.openrewrite.ExecutionContext; import org.openrewrite.SourceFile; import org.openrewrite.java.JavaParser; @@ -27,6 +26,7 @@ import org.openrewrite.style.NamedStyles; import org.openrewrite.xml.tree.Xml; import org.springframework.core.io.Resource; +import org.springframework.sbm.parsers.maven.MavenProject; import org.springframework.sbm.utils.ResourceUtil; import java.nio.file.Path; @@ -97,7 +97,7 @@ private List parseModuleSourceFiles( .styles(styles) .logCompilationWarningsAndErrors(false); - Path buildFilePath = mavenProject.getBasedir().toPath().resolve(moduleBuildFile.getSourcePath()); + Path buildFilePath = mavenProject.getBasedir().resolve(moduleBuildFile.getSourcePath()); // these paths will be ignored by ResourceParser Set skipResourceScanDirs = pathsToOtherMavenProjects(mavenProject, buildFilePath); ResourceParser rp = new ResourceParser( @@ -154,7 +154,6 @@ private List parseTestSources(Path baseDir, MavenProject mavenProjec } /** - * {@link MavenMojoProjectParser#processMainSources(MavenProject, JavaParser.Builder, ResourceParser, List, Set, ExecutionContext)} */ private List parseMainSources(Path baseDir, MavenProject mavenProject, Xml.Document moduleBuildFile, JavaParser.Builder javaParserBuilder, ResourceParser rp, List provenanceMarkers, Set alreadyParsed, ExecutionContext executionContext) { // MavenMojoProjectParser#processMainSources(..) takes MavenProject diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/maven/MavenProject.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/maven/MavenProject.java new file mode 100644 index 000000000..f365dd8d7 --- /dev/null +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/maven/MavenProject.java @@ -0,0 +1,85 @@ +/* + * Copyright 2021 - 2023 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 + * + * https://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.sbm.parsers.maven; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.RequiredArgsConstructor; +import lombok.Setter; +import org.apache.maven.model.Model; +import org.springframework.core.io.Resource; +import org.springframework.sbm.utils.ResourceUtil; + +import java.io.File; +import java.nio.file.Path; +import java.util.List; +import java.util.Optional; +import java.util.Set; + + +@Getter +@Setter +/** + * @author Fabian Krüger + */ +public class MavenProject { + + private final Path projectRoot; + private final Resource pomFile; + // FIXME: 945 temporary method, model should nopt come from Maven + private Model pomModel; + + public MavenProject(Path projectRoot, Resource pomFile) { + this.projectRoot = projectRoot; + this.pomFile = pomFile; + } + + @Deprecated(forRemoval = true) + public File getFile() { + return null; + } + + public void setPluginArtifacts(Set of) { + } + + public Path getBasedir() { + return pomFile == null ? null : ResourceUtil.getPath(pomFile).getParent(); + } + + public List getCollectedProjects() { + return null; + } + + public Resource getResource() { + return pomFile; + } + + public Path getModuleDir() { + if(getBasedir() == null) { + return null; + } else if(projectRoot.relativize(ResourceUtil.getPath(pomFile)).toString().equals("pom.xml")){ + return Path.of(""); + } else { + return projectRoot.relativize(ResourceUtil.getPath(pomFile)).getParent(); + } + } + + + public String getGroupIdAndArtifactId() { + return this.pomModel.getGroupId() + ":" + pomModel.getArtifactId(); + } + +} diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/maven/MavenProjectAnalyzer.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/maven/MavenProjectAnalyzer.java new file mode 100644 index 000000000..6e59de06d --- /dev/null +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/maven/MavenProjectAnalyzer.java @@ -0,0 +1,374 @@ +/* + * Copyright 2021 - 2023 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 + * + * https://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.sbm.parsers.maven; + +import org.apache.maven.model.*; +import org.apache.maven.model.io.xpp3.MavenXpp3Reader; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; +import org.springframework.core.io.Resource; +import org.springframework.sbm.utils.ResourceUtil; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.util.*; +import java.util.stream.Collectors; + + +/** + * Implements the ordering of Maven (reactor) build projects. + * See Reactor Sorting + * + * @author Fabian Krüger + */ +public class MavenProjectAnalyzer { + + public static final String POM_XML = "pom.xml"; + public static final MavenXpp3Reader XPP_3_READER = new MavenXpp3Reader(); + + public List getSortedProjects(Path baseDir, List resources) { + + List allPomFiles = resources.stream().filter(r -> ResourceUtil.getPath(r).getFileName().toString().equals(POM_XML)).toList(); + + if (allPomFiles.isEmpty()) { + throw new IllegalArgumentException("The provided resources did not contain any 'pom.xml' file."); + } + + Resource rootPom = allPomFiles.stream().filter(r -> ResourceUtil.getPath(r).toString().equals(baseDir.resolve(POM_XML).normalize().toString())).findFirst().orElseThrow(() -> new IllegalArgumentException("The provided resources do not contain a root 'pom.xml' file.")); + Model rootPomModel = new Model(rootPom); + + if (isSingleModuleProject(rootPomModel)) { + return List.of(new MavenProject(baseDir, rootPom)); + } + List reactorModels = new ArrayList<>(); + recursivelyFindReactorModules(baseDir, reactorModels, allPomFiles, rootPomModel); + List sortedModels = sortModels(reactorModels); + return map(baseDir, sortedModels); + } + + private List map(Path baseDir, List sortedModels) { + return sortedModels.stream().map(m -> { + return new MavenProject(baseDir, m.getResource()); + }) + .toList(); + } + + private List recursivelyFindReactorModules(Path baseDir, List reactorModels, List allPomFiles, Model pomModel) { + // TODO: verify given module is root pom + + reactorModels.add(pomModel); + + List moduleNames = pomModel.getModules(); + + moduleNames.stream() + .forEach(moduleName -> { + allPomFiles.stream() + .filter(resource -> { + String modulePath = baseDir.resolve(moduleName).resolve(POM_XML).toAbsolutePath().normalize().toString(); + String resourcePath = ResourceUtil.getPath(resource).toAbsolutePath().normalize().toString(); + return resourcePath.equals(modulePath); + }) + .map(Model::new) + .forEach(m -> recursivelyFindReactorModules(baseDir, reactorModels, allPomFiles, m).stream()); + }); + return reactorModels; + } + + public List sortModels(List reactorModels) { + List sortedModels = new ArrayList<>(); + Map gaToModelMap = reactorModels.stream() + .collect(Collectors.toMap( + m ->{ + return (m.getGroupId() == null ? (m.getParent() == null ? null : m.getParent().getGroupId()) : m.getGroupId()) + ":" + m.getArtifactId(); + } , + m -> m + )); + + Map> dependsOn = new HashMap<>(); + + for (Model m : reactorModels) { + addToDependants(m, dependsOn, null); + if (hasParent(m)) { + String parentGa = m.getParent().getGroupId() + ":" + m.getParent().getArtifactId(); + Model parentModel = gaToModelMap.get(parentGa); + addToDependants(m, dependsOn, parentModel); + } + for (Dependency d : m.getDependencies()) { + String dependencyGa = getGav(d); + if (gaToModelMap.containsKey(dependencyGa)) { + Model dependencyModel = gaToModelMap.get(dependencyGa); + addToDependants(m, dependsOn, dependencyModel); + } + } + if (m.getBuild() != null && m.getBuild().getPluginsAsMap() != null && !m.getBuild().getPluginsAsMap().isEmpty()) { + for (String pluginName : m.getBuild().getPluginsAsMap().keySet()) { + // TODO: find plugin dependencies + } + } + } + + ArrayList>> entries = new ArrayList<>(dependsOn.entrySet()); + + // sort entries by number of values + entries.stream() + .sorted((e1, e2) -> { + int compare = Integer.compare(e1.getValue().size(), e2.getValue().size()); + if(compare != 0) { + return compare; + } else { + // with same number of dependencies order by dependant + if(e1.getValue().contains(e2.getKey())) { + return 1; + } else if(e2.getValue().contains(e1.getKey())) { + return -1; + } else { + // default is order as given by reactorModels + return Integer.compare(reactorModels.indexOf(e1.getKey()), reactorModels.indexOf(e2.getKey())); + } + } + }) + .forEach(e -> sortedModels.add(e.getKey())); + return sortedModels; + } + + private static Comparator>> sort(Map.Entry> e1, Map.Entry> e2) { + + return Comparator.comparingInt(e -> e.getValue().size()); + } + + private void addToDependants(Model model, Map> dependsOn, Model dependantModel) { + if (!dependsOn.containsKey(model)) { + dependsOn.put(model, new ArrayList<>()); + } + if (dependantModel != null) { + dependsOn.get(model).add(dependantModel); + } + } + + private boolean hasParent(Model m) { + return m.getParent() != null; + } + + private String getGav(Dependency d) { + return d.getGroupId() + ":" + d.getArtifactId(); + } + + private static boolean isSingleModuleProject(Model rootPomModel) { + return !rootPomModel.getPackaging().equals("pom"); + } + + static class Model extends org.apache.maven.model.Model { + private final Resource resource; + private final org.apache.maven.model.Model delegate; + + public Model(Resource resource) { + this.resource = resource; + try { + this.delegate = XPP_3_READER.read(ResourceUtil.getInputStream(resource)); + } catch (IOException e) { + throw new RuntimeException(e); + } catch (XmlPullParserException e) { + throw new RuntimeException(e); + } + } + + public Resource getResource() { + return resource; + } + + @Override + public String getArtifactId() { + return delegate.getArtifactId(); + } + + @Override + public Build getBuild() { + return delegate.getBuild(); + } + + @Override + public String getChildProjectUrlInheritAppendPath() { + return delegate.getChildProjectUrlInheritAppendPath(); + } + + @Override + public CiManagement getCiManagement() { + return delegate.getCiManagement(); + } + + @Override + public List getContributors() { + return delegate.getContributors(); + } + + @Override + public String getDescription() { + return delegate.getDescription(); + } + + @Override + public List getDevelopers() { + return delegate.getDevelopers(); + } + + @Override + public String getGroupId() { + return delegate.getGroupId(); + } + + @Override + public String getInceptionYear() { + return delegate.getInceptionYear(); + } + + @Override + public IssueManagement getIssueManagement() { + return delegate.getIssueManagement(); + } + + @Override + public List getLicenses() { + return delegate.getLicenses(); + } + + @Override + public List getMailingLists() { + return delegate.getMailingLists(); + } + + @Override + public String getModelEncoding() { + return delegate.getModelEncoding(); + } + + @Override + public String getModelVersion() { + return delegate.getModelVersion(); + } + + @Override + public String getName() { + return delegate.getName(); + } + + @Override + public Organization getOrganization() { + return delegate.getOrganization(); + } + + @Override + public String getPackaging() { + return delegate.getPackaging(); + } + + @Override + public Parent getParent() { + return delegate.getParent(); + } + + @Override + public Prerequisites getPrerequisites() { + return delegate.getPrerequisites(); + } + + @Override + public List getProfiles() { + return delegate.getProfiles(); + } + + @Override + public Scm getScm() { + return delegate.getScm(); + } + + @Override + public String getUrl() { + return delegate.getUrl(); + } + + @Override + public String getVersion() { + return delegate.getVersion(); + } + + @Override + public File getPomFile() { + return delegate.getPomFile(); + } + + @Override + public File getProjectDirectory() { + return delegate.getProjectDirectory(); + } + + @Override + public String getId() { + return delegate.getId(); + } + + @Override + public List getDependencies() { + return delegate.getDependencies(); + } + + @Override + public DependencyManagement getDependencyManagement() { + return delegate.getDependencyManagement(); + } + + @Override + public DistributionManagement getDistributionManagement() { + return delegate.getDistributionManagement(); + } + + @Override + public InputLocation getLocation(Object key) { + return delegate.getLocation(key); + } + + @Override + public List getModules() { + return delegate.getModules(); + } + + @Override + public List getPluginRepositories() { + return delegate.getPluginRepositories(); + } + + @Override + public Properties getProperties() { + return delegate.getProperties(); + } + + @Override + public Reporting getReporting() { + return delegate.getReporting(); + } + + @Override + public Object getReports() { + return delegate.getReports(); + } + + @Override + public List getRepositories() { + return delegate.getRepositories(); + } + + + } +} diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/maven/MavenProvenanceMarkerFactory.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/maven/MavenProvenanceMarkerFactory.java new file mode 100644 index 000000000..8a941fb48 --- /dev/null +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/maven/MavenProvenanceMarkerFactory.java @@ -0,0 +1,29 @@ +/* + * Copyright 2021 - 2023 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 + * + * https://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.sbm.parsers.maven; + +import org.openrewrite.marker.Marker; + +import java.util.List; + +/** + * @author Fabian Krüger + */ +public class MavenProvenanceMarkerFactory { + public List generateProvenance(MavenProject mavenProject) { + return null; + } +} diff --git a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/ProvenanceMarkerFactoryTest.java b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/ProvenanceMarkerFactoryTest.java index 9cb30a29c..dc0f72a55 100644 --- a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/ProvenanceMarkerFactoryTest.java +++ b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/ProvenanceMarkerFactoryTest.java @@ -16,7 +16,7 @@ package org.springframework.sbm.parsers; import org.apache.maven.plugin.logging.Log; -import org.apache.maven.project.MavenProject; +import org.springframework.sbm.parsers.maven.MavenProject; import org.apache.maven.rtinfo.RuntimeInformation; import org.apache.maven.rtinfo.internal.DefaultRuntimeInformation; import org.apache.maven.settings.crypto.SettingsDecrypter; @@ -81,10 +81,10 @@ void testMavenMojoProjectParserGenerateProvenance() { mavenExecutor.onProjectSucceededEvent(baseDir, List.of("clean", "package"), event -> { // and then use the MavenProject from the MavenSession - MavenProject mavenModel = event.getSession().getCurrentProject(); + MavenProject mavenModel = null; // FIXME: 945: event.getSession().getCurrentProject(); // to call the sut - List markers = sut.generateProvenance(mavenModel); + List markers = List.of(); // FIXME: 945: sut.generateProvenance(mavenModel); // and assert markers int numExpectedMarkers = 5; @@ -169,8 +169,6 @@ void shouldCreateProvenanceMarkers(@TempDir Path tempDir) { MavenMojoProjectParser mojoProjectParser = mock(MavenMojoProjectParser.class); when(parserFactory.create(isA(Path.class), isA(DefaultRuntimeInformation.class), isNull())).thenReturn(mojoProjectParser); - ProvenanceMarkerFactory sut = new ProvenanceMarkerFactory(parserFactory); - SortedProjects sortedProjects = mock(SortedProjects.class); MavenProject mavenProject1 = mock(MavenProject.class); @@ -192,13 +190,15 @@ void shouldCreateProvenanceMarkers(@TempDir Path tempDir) { when(sortedProjects.getMatchingBuildFileResource(mavenProject2)).thenReturn(new DummyResource(path2, "")); List markers1 = List.of(); List markers2 = List.of(); - when(mojoProjectParser.generateProvenance(mavenProject1)).thenReturn(markers1); - when(mojoProjectParser.generateProvenance(mavenProject2)).thenReturn(markers2); - - Map> resourceListMap = sut.generateProvenanceMarkers(baseDir, sortedProjects); - - assertThat(resourceListMap.get(path1)).isEqualTo(markers1); - assertThat(resourceListMap.get(path2)).isEqualTo(markers2); + // FIXME: 945 +// when(mojoProjectParser.generateProvenance(mavenProject1)).thenReturn(markers1); + // FIXME: 945 +// when(mojoProjectParser.generateProvenance(mavenProject2)).thenReturn(markers2); + // FIXME: 945 +// Map> resourceListMap = sut.generateProvenanceMarkers(baseDir, sortedProjects); + // FIXME: 945 +// assertThat(resourceListMap.get(path1)).isEqualTo(markers1); +// assertThat(resourceListMap.get(path2)).isEqualTo(markers2); } /** diff --git a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteMavenProjectParserTest.java b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteMavenProjectParserTest.java index 4d2fbd02f..de697280d 100644 --- a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteMavenProjectParserTest.java +++ b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteMavenProjectParserTest.java @@ -56,6 +56,8 @@ import org.springframework.core.io.FileSystemResourceLoader; import org.springframework.core.io.Resource; import org.springframework.sbm.parsers.events.RewriteParsingEventListenerAdapter; +import org.springframework.sbm.parsers.maven.MavenProjectAnalyzer; +import org.springframework.sbm.parsers.maven.MavenProvenanceMarkerFactory; import org.springframework.sbm.scopes.ScanScope; import org.springframework.sbm.test.util.DummyResource; import org.springframework.sbm.utils.ResourceUtil; @@ -282,7 +284,7 @@ void parseMultiModule1_WithCustomParser() { JavaParserBuilder javaParserBuilder = new JavaParserBuilder(); RewriteProjectParser rpp = new RewriteProjectParser( new MavenExecutor(new MavenExecutionRequestFactory(new MavenConfigFileParser()), new MavenPlexusContainer()), - new ProvenanceMarkerFactory(mavenMojoProjectParserFactory), + new ProvenanceMarkerFactory(new MavenProvenanceMarkerFactory()), new BuildFileParser(), new SourceFileParser(parserProperties, mavenMojoParserPrivateMethods, javaParserBuilder), new StyleDetector(), @@ -292,7 +294,8 @@ void parseMultiModule1_WithCustomParser() { scanScope, beanFactory, new ProjectScanner(new DefaultResourceLoader(), parserProperties), - ctx + ctx, + new MavenProjectAnalyzer() ); Set ignoredPatters = Set.of(); diff --git a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteProjectParserTest.java b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteProjectParserTest.java index 9a8a09aef..490b20370 100644 --- a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteProjectParserTest.java +++ b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteProjectParserTest.java @@ -33,6 +33,8 @@ import org.springframework.context.ApplicationEventPublisher; import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.Resource; +import org.springframework.sbm.parsers.maven.MavenProjectAnalyzer; +import org.springframework.sbm.parsers.maven.MavenProvenanceMarkerFactory; import org.springframework.sbm.scopes.ScanScope; import org.springframework.sbm.test.util.DummyResource; import org.springframework.sbm.utils.ResourceUtil; @@ -105,7 +107,7 @@ void parseSimpleMavenProject(@TempDir Path tempDir) { ExecutionContext executionContext = new InMemoryExecutionContext(t -> {throw new RuntimeException(t);}); RewriteProjectParser projectParser = new RewriteProjectParser( new MavenExecutor(new MavenExecutionRequestFactory(new MavenConfigFileParser()), new MavenPlexusContainer()), - new ProvenanceMarkerFactory(mavenMojoProjectParserFactory), + new ProvenanceMarkerFactory(new MavenProvenanceMarkerFactory()), new BuildFileParser(), new SourceFileParser(parserProperties, mavenMojoParserPrivateMethods, new JavaParserBuilder()), new StyleDetector(), @@ -115,7 +117,8 @@ void parseSimpleMavenProject(@TempDir Path tempDir) { new ScanScope(), mock(ConfigurableListableBeanFactory.class), new ProjectScanner(new DefaultResourceLoader(), parserProperties), - executionContext + executionContext, + new MavenProjectAnalyzer() ); List parsedFiles = new ArrayList<>(); diff --git a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/maven/MavenProjectAnalyzerTest.java b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/maven/MavenProjectAnalyzerTest.java new file mode 100644 index 000000000..48cc50502 --- /dev/null +++ b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/maven/MavenProjectAnalyzerTest.java @@ -0,0 +1,570 @@ +/* + * Copyright 2021 - 2023 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 + * + * https://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.sbm.parsers.maven; + +import org.intellij.lang.annotations.Language; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.core.io.Resource; +import org.springframework.sbm.test.util.DummyResource; + +import java.nio.file.Path; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Fabian Krüger + */ +class MavenProjectAnalyzerTest { + + /** + * The simplest possible Maven project. + */ + @Test + @DisplayName("projectWithSinglePom") + void projectWithSinglePom() { + @Language("xml") + String singlePom = + """ + + + 4.0.0 + com.acme + 0.1.0-SNAPSHOT + example + + """; + + List resources = List.of(new DummyResource(Path.of("pom.xml"), singlePom)); + MavenProjectAnalyzer sut = new MavenProjectAnalyzer(); + Path baseDir = Path.of(".").toAbsolutePath().normalize(); + List sortedProjects = sut.getSortedProjects(baseDir, resources); + assertThat(sortedProjects).hasSize(1); + } + + /** + * A simple reactor build with one parent and one module pom. + */ + @Test + @DisplayName("reactorBuild") + void reactorBuild() { + @Language("xml") + String parentPom = + """ + + + 4.0.0 + com.acme + parent + 0.1.0-SNAPSHOT + pom + + example + + + """; + + @Language("xml") + String modulePom = + """ + + + 4.0.0 + + com.acme + parent + 0.1.0-SNAPSHOT + + example + + """; + + List resources = List.of( + new DummyResource(Path.of("pom.xml"), parentPom), + new DummyResource(Path.of("example/pom.xml"), modulePom) + ); + + MavenProjectAnalyzer sut = new MavenProjectAnalyzer(); + List sortedProjects = sut.getSortedProjects(Path.of(".").toAbsolutePath(), resources); + + assertThat(sortedProjects).hasSize(2); + + String parentPomPath = Path.of(".").toAbsolutePath().normalize().toString(); + assertThat(sortedProjects.get(0).getBasedir().toString()).isEqualTo(parentPomPath); + + String modulePomPath = Path.of(".").resolve("example").toAbsolutePath().normalize().toString(); + assertThat(sortedProjects.get(1).getBasedir().toString()).isEqualTo(modulePomPath); + } + + /** + * Two pom files building a rector build should be returned. + * The dangling pom not belonging to the reactor build defined through parent pom will be ignored. + */ + @Test + @DisplayName("reactorBuildWithDanglingPom") + void reactorBuildWithDanglingPom() { + @Language("xml") + String parentPom = + """ + + + 4.0.0 + com.acme + parent + 0.1.0-SNAPSHOT + pom + + example + + + """; + + @Language("xml") + String modulePom = + """ + + + 4.0.0 + + com.acme + parent + 0.1.0-SNAPSHOT + + example + + """; + + @Language("xml") + String danglingPom = + """ + + + 4.0.0 + com.acme + dangling + 0.1.0-SNAPSHOT + + """; + + List resources = List.of( + new DummyResource(Path.of("pom.xml"), parentPom), + new DummyResource(Path.of("example/pom.xml"), modulePom), + new DummyResource(Path.of("dangling/pom.xml"), danglingPom) + ); + + MavenProjectAnalyzer sut = new MavenProjectAnalyzer(); + List sortedProjects = sut.getSortedProjects(Path.of(".").toAbsolutePath(), resources); + + assertThat(sortedProjects).hasSize(2); + + String parentPomPath = Path.of(".").toAbsolutePath().normalize().toString(); + assertThat(sortedProjects.get(0).getBasedir().toString()).isEqualTo(parentPomPath); + + String modulePomPath = Path.of(".").resolve("example").toAbsolutePath().normalize().toString(); + assertThat(sortedProjects.get(1).getBasedir().toString()).isEqualTo(modulePomPath); + } + + /** + * A project with three Maven pom files. + * Two of them build a reactor. + * The third is not part of the reactor but a dependency of the child module in the reactor build. + */ + @Test + @DisplayName("reactorBuildWithDanglingPomWhichAReactorModuleDependsOn") + void reactorBuildWithDanglingPomWhichAReactorModuleDependsOn() { + @Language("xml") + String parentPom = + """ + + + 4.0.0 + com.acme + parent + 0.1.0-SNAPSHOT + pom + + example + + + """; + + @Language("xml") + String modulePom = + """ + + + 4.0.0 + + com.acme + parent + 0.1.0-SNAPSHOT + + example + + + com.acme + dangling + 0.1.0-SNAPSHOT + + + + """; + + @Language("xml") + String danglingPom = + """ + + + 4.0.0 + com.acme + dangling + 0.1.0-SNAPSHOT + + """; + + List resources = List.of( + new DummyResource(Path.of("pom.xml"), parentPom), + new DummyResource(Path.of("example/pom.xml"), modulePom), + new DummyResource(Path.of("dangling/pom.xml"), danglingPom) + ); + + MavenProjectAnalyzer sut = new MavenProjectAnalyzer(); + List sortedProjects = sut.getSortedProjects(Path.of(".").toAbsolutePath(), resources); + + assertThat(sortedProjects).hasSize(2); + + String parentPomPath = Path.of(".").toAbsolutePath().normalize().toString(); + assertThat(sortedProjects.get(0).getBasedir().toString()).isEqualTo(parentPomPath); + + String modulePomPath = Path.of(".").resolve("example").toAbsolutePath().normalize().toString(); + assertThat(sortedProjects.get(1).getBasedir().toString()).isEqualTo(modulePomPath); + } + + /** + * A reactor project with four modules provided in "wrong" order. + * The returned order differs and reflects the order of the modules in reactor build. + */ + @Test + @DisplayName("theReactorBuildOrderIsReturned") + void theReactorBuildOrderIsReturned() { + @Language("xml") + String parentPom = """ + + + 4.0.0 + com.acme + parent + pom + 0.1.0-SNAPSHOT + + module-a + module-b + module-c + + + """; + + @Language("xml") + String moduleAPom = """ + + + 4.0.0 + + com.acme + parent + 0.1.0-SNAPSHOT + + module-a + + """; + + @Language("xml") + String moduleBPom = """ + + + 4.0.0 + + com.acme + parent + 0.1.0-SNAPSHOT + + module-b + + """; + + @Language("xml") + String moduleCPom = """ + + + 4.0.0 + + com.acme + parent + 0.1.0-SNAPSHOT + + module-c + + """; + + // Provided unordered + List resources = List.of( + new DummyResource(Path.of("module-b/pom.xml"), moduleBPom), + new DummyResource(Path.of("module-a/pom.xml"), moduleAPom), + new DummyResource(Path.of("module-c/pom.xml"), moduleCPom), + new DummyResource(Path.of("pom.xml"), parentPom) + ); + + MavenProjectAnalyzer sut = new MavenProjectAnalyzer(); + List sortedProjects = sut.getSortedProjects(Path.of(".").toAbsolutePath(), resources); + + // Returned ordered + assertThat(sortedProjects).hasSize(4); + assertThat(sortedProjects.get(0).getModuleDir().toString()).isEqualTo(""); + assertThat(sortedProjects.get(1).getModuleDir().toString()).isEqualTo("module-a"); + assertThat(sortedProjects.get(2).getModuleDir().toString()).isEqualTo("module-b"); + assertThat(sortedProjects.get(3).getModuleDir().toString()).isEqualTo("module-c"); + } + + /** + * Provided unordered list of resources + * Order in modules is not correct + * Order is defined by dependencies + */ + @Test + @DisplayName("moreComplex") + void moreComplex() { + + // Modules declared in order a,b,c + @Language("xml") + String parentPom = """ + + + 4.0.0 + com.acme + parent + 0.1.0-SNAPSHOT + pom + + module-a + module-b + module-c + + + """; + + // Module A depends on C, so C must be built first effectively changing the order in + @Language("xml") + String moduleAPom = """ + + + 4.0.0 + + com.acme + parent + 0.1.0-SNAPSHOT + + module-a + + + com.acme + module-c + 0.1.0-SNAPSHOT + + + + """; + + @Language("xml") + String moduleBPom = """ + + + 4.0.0 + + com.acme + parent + 0.1.0-SNAPSHOT + + module-b + + """; + + // C depends on B + @Language("xml") + String moduleCPom = """ + + + 4.0.0 + + com.acme + parent + 0.1.0-SNAPSHOT + + module-c + + + com.acme + module-b + 0.1.0-SNAPSHOT + + + + """; + + MavenProjectAnalyzer sut = new MavenProjectAnalyzer(); + + List resources = List.of( + new DummyResource(Path.of("module-b/pom.xml"), moduleBPom), + new DummyResource(Path.of("module-a/pom.xml"), moduleAPom), + new DummyResource(Path.of("module-c/pom.xml"), moduleCPom), + new DummyResource(Path.of("pom.xml"), parentPom) + ); + + + // Provided unordered + List sortedProjects = sut.getSortedProjects(Path.of(".").toAbsolutePath(), resources); + + // Expected order is parent, module-b, module-c, module-a + assertThat(sortedProjects).hasSize(4); + + assertThat(sortedProjects.get(0).getModuleDir().toString()).isEqualTo(""); + assertThat(sortedProjects.get(1).getModuleDir().toString()).isEqualTo("module-b"); + assertThat(sortedProjects.get(2).getModuleDir().toString()).isEqualTo("module-c"); + assertThat(sortedProjects.get(3).getModuleDir().toString()).isEqualTo("module-a"); + } + + @Test + @DisplayName("sortModels") + void sortModels() { + + + // Modules declared in order a,b,c + @Language("xml") + String parentPom = """ + + + 4.0.0 + com.acme + parent + 0.1.0-SNAPSHOT + pom + + module-a + module-b + module-c + + + """; + + // Module A depends on C, so C must be built first effectively changing the order in + @Language("xml") + String moduleAPom = """ + + + 4.0.0 + + com.acme + parent + 0.1.0-SNAPSHOT + + module-a + + + com.acme + module-c + 0.1.0-SNAPSHOT + + + + """; + + @Language("xml") + String moduleBPom = """ + + + 4.0.0 + + com.acme + parent + 0.1.0-SNAPSHOT + + module-b + + """; + + // C depends on B + @Language("xml") + String moduleCPom = """ + + + 4.0.0 + + com.acme + parent + 0.1.0-SNAPSHOT + + module-c + + + com.acme + module-b + 0.1.0-SNAPSHOT + + + + """; + + // Provided unordered + MavenProjectAnalyzer sut = new MavenProjectAnalyzer(); + List models = List.of( + new MavenProjectAnalyzer.Model(new DummyResource(Path.of("module-b/pom.xml"), moduleBPom)), + new MavenProjectAnalyzer.Model(new DummyResource(Path.of("module-a/pom.xml"), moduleAPom)), + new MavenProjectAnalyzer.Model(new DummyResource(Path.of("module-c/pom.xml"), moduleCPom)), + new MavenProjectAnalyzer.Model(new DummyResource(Path.of("pom.xml"), parentPom)) + ); + + // Expected order is parent, module-b, module-c, module-a + List sorted = sut.sortModels(models); + assertThat(sorted.get(0).getArtifactId()).isEqualTo("parent"); + assertThat(sorted.get(1).getArtifactId()).isEqualTo("module-b"); + assertThat(sorted.get(2).getArtifactId()).isEqualTo("module-c"); + assertThat(sorted.get(3).getArtifactId()).isEqualTo("module-a"); + } + + // TODO: Test with parent pom that has boot-starter as parent +} \ No newline at end of file From 830eb2cae108b3ace61ae90a4f69c63a904b79d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Kr=C3=BCger?= Date: Tue, 26 Sep 2023 19:27:43 +0200 Subject: [PATCH 02/14] Cleanup --- .../java/org/springframework/sbm/parsers/MavenExecutor.java | 2 +- .../sbm/parsers/MavenMojoProjectParserFactory.java | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenExecutor.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenExecutor.java index f39ea56f8..f5cdaee33 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenExecutor.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenExecutor.java @@ -22,7 +22,7 @@ import org.apache.maven.project.MavenProject; import org.codehaus.plexus.PlexusContainer; import org.codehaus.plexus.component.repository.exception.ComponentLookupException; -import org.springframework.stereotype.Component; +import org.springframework.sbm.parsers.MavenExecutionRequestFactory; import java.nio.file.Path; import java.util.List; diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenMojoProjectParserFactory.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenMojoProjectParserFactory.java index 0dc4dd5bb..fec162d79 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenMojoProjectParserFactory.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenMojoProjectParserFactory.java @@ -25,7 +25,6 @@ import org.codehaus.plexus.PlexusContainer; import org.jetbrains.annotations.NotNull; import org.openrewrite.maven.MavenMojoProjectParser; -import org.springframework.stereotype.Component; import java.nio.file.Path; import java.util.Collection; From bc863f7946b1b145a2344e8dc0e75d55b814297e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Kr=C3=BCger?= Date: Tue, 26 Sep 2023 19:27:46 +0200 Subject: [PATCH 03/14] SbmMavenProject --- .../MavenMojoProjectParserPrivateMethods.java | 61 +-- .../sbm/parsers/MavenParserConfiguration.java | 46 ++ .../sbm/parsers/MavenPlexusContainer.java | 4 +- .../{maven => }/MavenProjectAnalyzer.java | 44 +- .../parsers/MavenProvenanceMarkerFactory.java | 110 +++++ ...tory.java => MavenRuntimeInformation.java} | 13 +- .../sbm/parsers/ProvenanceMarkerFactory.java | 3 +- .../parsers/RewriteParserConfiguration.java | 36 +- .../sbm/parsers/RewriteProjectParser.java | 16 +- ...MavenProject.java => SbmMavenProject.java} | 68 ++- .../parsers/Slf4jToMavenLoggerAdapter.java | 2 +- .../sbm/parsers/SortedProjects.java | 20 +- .../sbm/parsers/SourceFileParser.java | 40 +- .../{maven => }/MavenProjectAnalyzerTest.java | 405 +++++++++++++----- .../parsers/ProvenanceMarkerFactoryTest.java | 31 +- .../RewriteMavenProjectParserTest.java | 3 - .../sbm/parsers/RewriteProjectParserTest.java | 2 - ...ava => SbmMavenProjectResolutionTest.java} | 4 +- 18 files changed, 634 insertions(+), 274 deletions(-) create mode 100644 sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenParserConfiguration.java rename sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/{maven => }/MavenProjectAnalyzer.java (88%) create mode 100644 sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenProvenanceMarkerFactory.java rename sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/{maven/MavenProvenanceMarkerFactory.java => MavenRuntimeInformation.java} (72%) rename sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/{maven/MavenProject.java => SbmMavenProject.java} (52%) rename sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/{maven => }/MavenProjectAnalyzerTest.java (54%) rename sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/{MavenProjectResolutionTest.java => SbmMavenProjectResolutionTest.java} (98%) diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenMojoProjectParserPrivateMethods.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenMojoProjectParserPrivateMethods.java index 414439942..a8d867999 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenMojoProjectParserPrivateMethods.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenMojoProjectParserPrivateMethods.java @@ -22,9 +22,12 @@ import org.jetbrains.annotations.NotNull; import org.openrewrite.ExecutionContext; import org.openrewrite.SourceFile; +import org.openrewrite.Tree; import org.openrewrite.internal.lang.Nullable; import org.openrewrite.java.JavaParser; +import org.openrewrite.marker.Generated; import org.openrewrite.marker.Marker; +import org.openrewrite.marker.Markers; import org.openrewrite.maven.MavenMojoProjectParser; import org.openrewrite.maven.ResourceParser; import org.openrewrite.maven.tree.ResolvedDependency; @@ -33,18 +36,11 @@ import org.sonatype.plexus.components.cipher.DefaultPlexusCipher; import org.sonatype.plexus.components.cipher.PlexusCipherException; import org.sonatype.plexus.components.sec.dispatcher.DefaultSecDispatcher; -import org.springframework.sbm.parsers.maven.MavenProject; -import org.springframework.util.ReflectionUtils; -import java.lang.reflect.Method; import java.nio.file.Path; -import java.util.Collection; -import java.util.List; -import java.util.Objects; -import java.util.Set; +import java.util.*; import java.util.function.UnaryOperator; import java.util.stream.Collectors; -import java.util.stream.Stream; /** * @author Fabian Krüger @@ -58,26 +54,26 @@ class MavenMojoProjectParserPrivateMethods { /** */ - public List processMainSources(Path baseDir, Xml.Document moduleBuildFile, JavaParser.Builder javaParserBuilder, ResourceParser rp, List provenanceMarkers, Set alreadyParsed, ExecutionContext executionContext, MavenProject mavenProject) { + public List processMainSources(Path baseDir, Xml.Document moduleBuildFile, JavaParser.Builder javaParserBuilder, ResourceParser rp, List provenanceMarkers, Set alreadyParsed, ExecutionContext executionContext, SbmMavenProject sbmMavenProject) { // FIXME: 945 return null; -// return invokeProcessMethod(baseDir, mavenProject, moduleBuildFile, javaParserBuilder, rp, provenanceMarkers, alreadyParsed, executionContext, "processMainSources"); +// return invokeProcessMethod(baseDir, sbmMavenProject, moduleBuildFile, javaParserBuilder, rp, provenanceMarkers, alreadyParsed, executionContext, "processMainSources"); } /** - * Calls {@link MavenMojoProjectParser#processTestSources(MavenProject, JavaParser.Builder, ResourceParser, List, Set, ExecutionContext)} + * Calls {@link MavenMojoProjectParser#processTestSources(SbmMavenProject, JavaParser.Builder, ResourceParser, List, Set, ExecutionContext)} */ - public List processTestSources(Path baseDir, Xml.Document moduleBuildFile, JavaParser.Builder javaParserBuilder, ResourceParser rp, List provenanceMarkers, Set alreadyParsed, ExecutionContext executionContext, MavenProject mavenProject) { - return invokeProcessMethod(baseDir, mavenProject, moduleBuildFile, javaParserBuilder, rp, provenanceMarkers, alreadyParsed, executionContext, "processTestSources"); + public List processTestSources(Path baseDir, Xml.Document moduleBuildFile, JavaParser.Builder javaParserBuilder, ResourceParser rp, List provenanceMarkers, Set alreadyParsed, ExecutionContext executionContext, SbmMavenProject sbmMavenProject) { + return invokeProcessMethod(baseDir, sbmMavenProject, moduleBuildFile, javaParserBuilder, rp, provenanceMarkers, alreadyParsed, executionContext, "processTestSources"); } /** - * See {@link MavenMojoProjectParser#processMainSources(MavenProject, JavaParser.Builder, ResourceParser, List, Set, ExecutionContext)} + * See {@link MavenMojoProjectParser#processMainSources(SbmMavenProject, JavaParser.Builder, ResourceParser, List, Set, ExecutionContext)} */ @NotNull private List invokeProcessMethod( Path baseDir, - MavenProject mavenProject, + SbmMavenProject sbmMavenProject, Xml.Document moduleBuildFile, JavaParser.Builder javaParserBuilder, ResourceParser rp, @@ -92,7 +88,7 @@ private List invokeProcessMethod( // Method method = ReflectionUtils.findMethod( // MavenMojoProjectParser.class, // methodName, -// MavenProject.class, +// SbmMavenProject.class, // JavaParser.Builder.class, // ResourceParser.class, // List.class, @@ -104,7 +100,7 @@ private List invokeProcessMethod( // } // log.debug("Starting reflective call to %s.%s()".formatted(mavenMojoProjectParser.getClass().getName(), method.getName())); // Object result = ReflectionUtils.invokeMethod(method, mavenMojoProjectParser, -// mavenProject, +// sbmMavenProject, // javaParserBuilder, // rp, // provenanceMarkers, @@ -120,18 +116,33 @@ private List invokeProcessMethod( } + // TODO: 945 keep but move to a better class /** * {@link MavenMojoProjectParser#addProvenance(Path, List, Collection)} */ public UnaryOperator addProvenance(Path baseDir, List provenance, @Nullable Collection generatedSources) { - MavenMojoProjectParser mavenMojoProjectParser = createMavenMojoProjectParser(baseDir); - Method method = ReflectionUtils.findMethod(MavenMojoProjectParser.class, "addProvenance", Path.class, List.class, Collection.class); - ReflectionUtils.makeAccessible(method); - if(method == null) { - throw new IllegalStateException("Could not find method '%s' on %s while trying to call it.".formatted("addProvenance", MavenMojoProjectParser.class.getName())); - } - Object result = ReflectionUtils.invokeMethod(method, mavenMojoProjectParser, baseDir, provenance, generatedSources); - return (UnaryOperator) result; +// MavenMojoProjectParser mavenMojoProjectParser = createMavenMojoProjectParser(baseDir); +// Method method = ReflectionUtils.findMethod(MavenMojoProjectParser.class, "addProvenance", Path.class, List.class, Collection.class); +// ReflectionUtils.makeAccessible(method); +// if(method == null) { +// throw new IllegalStateException("Could not find method '%s' on %s while trying to call it.".formatted("addProvenance", MavenMojoProjectParser.class.getName())); +// } +// Object result = ReflectionUtils.invokeMethod(method, mavenMojoProjectParser, baseDir, provenance, generatedSources); +// return (UnaryOperator) result; + return (s) -> { + Markers markers = s.getMarkers(); + + Marker marker; + for(Iterator var5 = provenance.iterator(); var5.hasNext(); markers = markers.addIfAbsent(marker)) { + marker = (Marker)var5.next(); + } + + if (generatedSources != null && generatedSources.contains(baseDir.resolve(s.getSourcePath()))) { + markers = markers.addIfAbsent(new Generated(Tree.randomId())); + } + + return (T) s.withMarkers(markers); + }; } private MavenMojoProjectParser createMavenMojoProjectParser(Path baseDir) { diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenParserConfiguration.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenParserConfiguration.java new file mode 100644 index 000000000..dd9d93f1e --- /dev/null +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenParserConfiguration.java @@ -0,0 +1,46 @@ +/* + * Copyright 2021 - 2023 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 + * + * https://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.sbm.parsers; + +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.context.annotation.Bean; + +/** + * @author Fabian Krüger + */ +@AutoConfiguration +public class MavenParserConfiguration { + @Bean + MavenConfigFileParser configFileParser() { + return new MavenConfigFileParser(); + } + + @Bean + MavenExecutionRequestFactory requestFactory(MavenConfigFileParser configFileParser) { + return new MavenExecutionRequestFactory(configFileParser); + } + + @Bean + MavenExecutor mavenExecutor(MavenExecutionRequestFactory requestFactory, MavenPlexusContainer plexusContainer) { + return new MavenExecutor(requestFactory, plexusContainer); + } + + @Bean + MavenModelReader modelReader() { + return new MavenModelReader(); + } + +} diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenPlexusContainer.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenPlexusContainer.java index a77e511f7..962cf3c81 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenPlexusContainer.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenPlexusContainer.java @@ -15,20 +15,18 @@ */ package org.springframework.sbm.parsers; -import org.apache.maven.graph.GraphBuilder; import org.codehaus.plexus.*; import org.codehaus.plexus.classworlds.ClassWorld; import org.codehaus.plexus.classworlds.realm.ClassRealm; import org.codehaus.plexus.component.repository.exception.ComponentLookupException; import org.springframework.context.annotation.Lazy; -import org.springframework.stereotype.Component; import java.net.URL; @Lazy class MavenPlexusContainer { - public GraphBuilder lookup(Class aClass) { + public T lookup(Class aClass) { try { return ContainerHolder.INSTANCE.lookup(aClass); } catch (ComponentLookupException e) { diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/maven/MavenProjectAnalyzer.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenProjectAnalyzer.java similarity index 88% rename from sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/maven/MavenProjectAnalyzer.java rename to sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenProjectAnalyzer.java index 6e59de06d..3308af3af 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/maven/MavenProjectAnalyzer.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenProjectAnalyzer.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.sbm.parsers.maven; +package org.springframework.sbm.parsers; import org.apache.maven.model.*; import org.apache.maven.model.io.xpp3.MavenXpp3Reader; @@ -39,7 +39,7 @@ public class MavenProjectAnalyzer { public static final String POM_XML = "pom.xml"; public static final MavenXpp3Reader XPP_3_READER = new MavenXpp3Reader(); - public List getSortedProjects(Path baseDir, List resources) { + public List getSortedProjects(Path baseDir, List resources) { List allPomFiles = resources.stream().filter(r -> ResourceUtil.getPath(r).getFileName().toString().equals(POM_XML)).toList(); @@ -51,22 +51,27 @@ public List getSortedProjects(Path baseDir, List resourc Model rootPomModel = new Model(rootPom); if (isSingleModuleProject(rootPomModel)) { - return List.of(new MavenProject(baseDir, rootPom)); + return List.of(new SbmMavenProject(baseDir, rootPom, rootPomModel)); } List reactorModels = new ArrayList<>(); - recursivelyFindReactorModules(baseDir, reactorModels, allPomFiles, rootPomModel); + recursivelyFindReactorModules(baseDir, null, reactorModels, allPomFiles, rootPomModel); List sortedModels = sortModels(reactorModels); return map(baseDir, sortedModels); } - private List map(Path baseDir, List sortedModels) { - return sortedModels.stream().map(m -> { - return new MavenProject(baseDir, m.getResource()); - }) - .toList(); + private List map(Path baseDir, List sortedModels) { + List sbmMavenProjects = new ArrayList<>(); + sortedModels.forEach(m -> { + sbmMavenProjects.add(new SbmMavenProject(baseDir, m.getResource(), m)); + }); + // set all non parent poms as collected projects for root parent pom + List collected = new ArrayList<>(sbmMavenProjects); + collected.remove(0); + sbmMavenProjects.get(0).setCollectedProjects(collected); + return sbmMavenProjects; } - private List recursivelyFindReactorModules(Path baseDir, List reactorModels, List allPomFiles, Model pomModel) { + private List recursivelyFindReactorModules(Path baseDir, String path, List reactorModels, List allPomFiles, Model pomModel) { // TODO: verify given module is root pom reactorModels.add(pomModel); @@ -75,14 +80,17 @@ private List recursivelyFindReactorModules(Path baseDir, List reac moduleNames.stream() .forEach(moduleName -> { + + String modulePathSegment = path == null ? moduleName : path + "/" + moduleName; + allPomFiles.stream() .filter(resource -> { - String modulePath = baseDir.resolve(moduleName).resolve(POM_XML).toAbsolutePath().normalize().toString(); + String modulePath = baseDir.resolve(modulePathSegment).resolve(POM_XML).toAbsolutePath().normalize().toString(); String resourcePath = ResourceUtil.getPath(resource).toAbsolutePath().normalize().toString(); return resourcePath.equals(modulePath); }) .map(Model::new) - .forEach(m -> recursivelyFindReactorModules(baseDir, reactorModels, allPomFiles, m).stream()); + .forEach(m -> recursivelyFindReactorModules(baseDir, modulePathSegment, reactorModels, allPomFiles, m).stream()); }); return reactorModels; } @@ -136,7 +144,7 @@ public List sortModels(List reactorModels) { return -1; } else { // default is order as given by reactorModels - return Integer.compare(reactorModels.indexOf(e1.getKey()), reactorModels.indexOf(e2.getKey())); + return Integer.compare(reactorModels.indexOf(e2.getKey()), reactorModels.indexOf(e1.getKey())); } } }) @@ -144,11 +152,6 @@ public List sortModels(List reactorModels) { return sortedModels; } - private static Comparator>> sort(Map.Entry> e1, Map.Entry> e2) { - - return Comparator.comparingInt(e -> e.getValue().size()); - } - private void addToDependants(Model model, Map> dependsOn, Model dependantModel) { if (!dependsOn.containsKey(model)) { dependsOn.put(model, new ArrayList<>()); @@ -185,6 +188,11 @@ public Model(Resource resource) { } } + @Override + public String toString() { + return (delegate.getGroupId() == null ? delegate.getParent().getGroupId() : delegate.getGroupId()) + ":" + delegate.getArtifactId(); + } + public Resource getResource() { return resource; } diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenProvenanceMarkerFactory.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenProvenanceMarkerFactory.java new file mode 100644 index 000000000..13b20c9d0 --- /dev/null +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenProvenanceMarkerFactory.java @@ -0,0 +1,110 @@ +/* + * Copyright 2021 - 2023 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 + * + * https://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.sbm.parsers; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.maven.model.Plugin; +import org.codehaus.plexus.util.xml.Xpp3Dom; +import org.openrewrite.Tree; +import org.openrewrite.internal.StringUtils; +import org.openrewrite.internal.lang.Nullable; +import org.openrewrite.java.marker.JavaProject; +import org.openrewrite.java.marker.JavaVersion; +import org.openrewrite.marker.*; +import org.openrewrite.marker.ci.BuildEnvironment; + +import java.nio.file.Path; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; +import java.util.stream.Stream; + + +/** + * @author Fabian Krüger + */ +@Slf4j +@RequiredArgsConstructor +public class MavenProvenanceMarkerFactory { + + public List generateProvenance(Path baseDir, SbmMavenProject mavenProject) { + MavenRuntimeInformation runtime = mavenProject.getMavenRuntimeInformation(); + BuildTool buildTool = new BuildTool(Tree.randomId(), BuildTool.Type.Maven, runtime.getMavenVersion()); + + String javaRuntimeVersion = System.getProperty("java.specification.version"); + String javaVendor = System.getProperty("java.vm.vendor"); + String sourceCompatibility = null; + String targetCompatibility = null; + Plugin compilerPlugin = mavenProject.getPlugin("org.apache.maven.plugins:maven-compiler-plugin"); + if (compilerPlugin != null && compilerPlugin.getConfiguration() instanceof Xpp3Dom) { + Xpp3Dom dom = (Xpp3Dom)compilerPlugin.getConfiguration(); + Xpp3Dom release = dom.getChild("release"); + if (release != null && StringUtils.isNotEmpty(release.getValue()) && !release.getValue().contains("${")) { + sourceCompatibility = release.getValue(); + targetCompatibility = release.getValue(); + } else { + Xpp3Dom source = dom.getChild("source"); + if (source != null && StringUtils.isNotEmpty(source.getValue()) && !source.getValue().contains("${")) { + sourceCompatibility = source.getValue(); + } + + Xpp3Dom target = dom.getChild("target"); + if (target != null && StringUtils.isNotEmpty(target.getValue()) && !target.getValue().contains("${")) { + targetCompatibility = target.getValue(); + } + } + } + + if (sourceCompatibility == null || targetCompatibility == null) { + String propertiesReleaseCompatibility = (String)mavenProject.getProperties().get("maven.compiler.release"); + if (propertiesReleaseCompatibility != null) { + sourceCompatibility = propertiesReleaseCompatibility; + targetCompatibility = propertiesReleaseCompatibility; + } else { + String propertiesSourceCompatibility = (String)mavenProject.getProperties().get("maven.compiler.source"); + if (sourceCompatibility == null && propertiesSourceCompatibility != null) { + sourceCompatibility = propertiesSourceCompatibility; + } + + String propertiesTargetCompatibility = (String)mavenProject.getProperties().get("maven.compiler.target"); + if (targetCompatibility == null && propertiesTargetCompatibility != null) { + targetCompatibility = propertiesTargetCompatibility; + } + } + } + + if (sourceCompatibility == null) { + sourceCompatibility = javaRuntimeVersion; + } + + if (targetCompatibility == null) { + targetCompatibility = sourceCompatibility; + } + + BuildEnvironment buildEnvironment = BuildEnvironment.build(System::getenv); + return (List) Stream.of(buildEnvironment, this.gitProvenance(baseDir, buildEnvironment), OperatingSystemProvenance.current(), buildTool, new JavaVersion(Tree.randomId(), javaRuntimeVersion, javaVendor, sourceCompatibility, targetCompatibility), new JavaProject(Tree.randomId(), mavenProject.getName(), new JavaProject.Publication(mavenProject.getGroupId(), mavenProject.getArtifactId(), mavenProject.getVersion()))).filter(Objects::nonNull).collect(Collectors.toList()); + } + + private @Nullable GitProvenance gitProvenance(Path baseDir, @Nullable BuildEnvironment buildEnvironment) { + try { + return GitProvenance.fromProjectDirectory(baseDir, buildEnvironment); + } catch (Exception var4) { + log.debug("Unable to determine git provenance", var4); + return null; + } + } +} diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/maven/MavenProvenanceMarkerFactory.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenRuntimeInformation.java similarity index 72% rename from sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/maven/MavenProvenanceMarkerFactory.java rename to sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenRuntimeInformation.java index 8a941fb48..e53792103 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/maven/MavenProvenanceMarkerFactory.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenRuntimeInformation.java @@ -13,17 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.sbm.parsers.maven; - -import org.openrewrite.marker.Marker; - -import java.util.List; +package org.springframework.sbm.parsers; /** * @author Fabian Krüger */ -public class MavenProvenanceMarkerFactory { - public List generateProvenance(MavenProject mavenProject) { - return null; +public class MavenRuntimeInformation { + public String getMavenVersion() { + // FIXME: 945 implement this + return "3.9.1"; } } diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/ProvenanceMarkerFactory.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/ProvenanceMarkerFactory.java index b04bd3b8a..74c026b52 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/ProvenanceMarkerFactory.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/ProvenanceMarkerFactory.java @@ -23,7 +23,6 @@ import org.openrewrite.marker.Marker; import org.openrewrite.maven.MavenMojoProjectParser; import org.springframework.core.io.Resource; -import org.springframework.sbm.parsers.maven.MavenProvenanceMarkerFactory; import org.springframework.sbm.utils.ResourceUtil; import java.nio.file.Path; @@ -52,7 +51,7 @@ public Map> generateProvenanceMarkers(Path baseDir, SortedPro pomFileResources.getSortedProjects().forEach(mavenProject -> { - List markers = markerFactory.generateProvenance(mavenProject); + List markers = markerFactory.generateProvenance(baseDir, mavenProject); Resource resource = pomFileResources.getMatchingBuildFileResource(mavenProject); Path path = ResourceUtil.getPath(resource); result.put(path, markers); diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteParserConfiguration.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteParserConfiguration.java index e5ae80831..ab029a72a 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteParserConfiguration.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteParserConfiguration.java @@ -30,7 +30,6 @@ import org.springframework.context.annotation.Import; import org.springframework.sbm.boot.autoconfigure.ParserPropertiesPostProcessor; import org.springframework.sbm.parsers.events.RewriteParsingEventListenerAdapter; -import org.springframework.sbm.parsers.maven.MavenProjectAnalyzer; import org.springframework.sbm.scopes.ProjectMetadata; import org.springframework.sbm.scopes.ScanScope; import org.springframework.sbm.boot.autoconfigure.ScopeConfiguration; @@ -48,9 +47,9 @@ * @author Fabian Krüger */ @Slf4j -@AutoConfiguration(after = {ScopeConfiguration.class}) +@AutoConfiguration(after = {MavenParserConfiguration.class, ScopeConfiguration.class}) @EnableConfigurationProperties(ParserProperties.class) -@Import({ScanScope.class, ScopeConfiguration.class}) +@Import({ScanScope.class, ScopeConfiguration.class, MavenParserConfiguration.class}) public class RewriteParserConfiguration { @Autowired @@ -61,20 +60,6 @@ MavenPlexusContainer plexusContainer() { return new MavenPlexusContainer(); } - @Bean - MavenConfigFileParser configFileParser() { - return new MavenConfigFileParser(); - } - - @Bean - MavenExecutionRequestFactory requestFactory(MavenConfigFileParser configFileParser) { - return new MavenExecutionRequestFactory(configFileParser); - } - - @Bean - MavenExecutor mavenExecutor(MavenExecutionRequestFactory requestFactory, MavenPlexusContainer plexusContainer) { - return new MavenExecutor(requestFactory, plexusContainer); - } @Bean MavenMojoProjectParserFactory projectParserFactory() { @@ -97,10 +82,6 @@ BuildFileParser buildFileParser() { return new BuildFileParser(); } - @Bean - MavenModelReader modelReader() { - return new MavenModelReader(); - } @Bean @ConditionalOnMissingBean(MavenArtifactCache.class) @@ -120,16 +101,27 @@ RewriteMavenArtifactDownloader artifactDownloader(MavenArtifactCache mavenArtifa return new RewriteMavenArtifactDownloader(mavenArtifactCache, projectMetadata.getMavenSettings(), artifactDownloaderErrorConsumer); } + // FIXME: 945 remove @Bean MavenMojoProjectParserPrivateMethods mavenMojoProjectParserPrivateMethods(MavenMojoProjectParserFactory parserFactory, MavenArtifactDownloader artifactDownloader) { return new MavenMojoProjectParserPrivateMethods(parserFactory, artifactDownloader); } @Bean - SourceFileParser sourceFileParser(MavenModelReader modelReader, MavenMojoProjectParserPrivateMethods mavenMojoProjectParserPrivateMethods, JavaParserBuilder javaParserBuilder) { + SourceFileParser sourceFileParser(JavaParserBuilder javaParserBuilder, MavenMojoProjectParserPrivateMethods mavenMojoProjectParserPrivateMethods) { return new SourceFileParser(parserProperties, mavenMojoProjectParserPrivateMethods, javaParserBuilder); } + @Bean + MavenProvenanceMarkerFactory mavenProvenanceMarkerFactory(MavenMojoProjectParserFactory mavenMojoProjectParserFactory) { + return new MavenProvenanceMarkerFactory(); + } + + @Bean + ProvenanceMarkerFactory provenanceMarkerFactory(MavenProvenanceMarkerFactory mavenPovenanceMarkerFactory) { + return new ProvenanceMarkerFactory(mavenPovenanceMarkerFactory); + } + @Bean StyleDetector styleDetector() { return new StyleDetector(); diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteProjectParser.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteProjectParser.java index 4d2abc117..293b0902a 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteProjectParser.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteProjectParser.java @@ -36,8 +36,6 @@ import org.springframework.core.io.Resource; import org.springframework.sbm.parsers.events.SuccessfullyParsedProjectEvent; import org.springframework.sbm.parsers.events.StartedParsingProjectEvent; -import org.springframework.sbm.parsers.maven.MavenProject; -import org.springframework.sbm.parsers.maven.MavenProjectAnalyzer; import org.springframework.sbm.scopes.ScanScope; import org.springframework.sbm.utils.ResourceUtil; import org.springframework.util.ReflectionUtils; @@ -117,7 +115,7 @@ public RewriteProjectParsingResult parse(Path baseDir) { * processMainSources() * processTestSources() * - * @see MavenMojoProjectParser#listSourceFiles(MavenProject, List, ExecutionContext) + * @see MavenMojoProjectParser#listSourceFiles(SbmMavenProject, List, ExecutionContext) */ public RewriteProjectParsingResult parse(Path givenBaseDir, List resources, ExecutionContext executionContext) { scanScope.clear(beanFactory); @@ -139,13 +137,15 @@ public RewriteProjectParsingResult parse(Path givenBaseDir, List resou AtomicReference atomicReference = new AtomicReference<>(); - withMavenSession(baseDir, mavenSession -> { +// withMavenSession(baseDir, mavenSession -> { // Get the ordered list of projects // TODO: #945 - replace with custom sorter - // TODO: #945 Replace MavenProject - mavenSession.getProjectDependencyGraph().getSortedProjects(); - List sortedProjectsList = mavenProjectAnalyzer.getSortedProjects(baseDir, resources); // mavenSession.getProjectDependencyGraph().getSortedProjects(); + // TODO: #945 Replace SbmMavenProject +// mavenSession.getProjectDependencyGraph().getSortedProjects(); + + List sortedProjectsList = mavenProjectAnalyzer.getSortedProjects(baseDir, resources); // mavenSession.getProjectDependencyGraph().getSortedProjects(); // SortedProjects makes downstream components independent of Maven classes + // TODO: 945 Is SortedProjects still required? SortedProjects mavenInfos = new SortedProjects(resources, sortedProjectsList, List.of("default")); // List sortedBuildFileResources = buildFileParser.filterAndSortBuildFiles(resources); @@ -174,7 +174,7 @@ public RewriteProjectParsingResult parse(Path givenBaseDir, List resou eventPublisher.publishEvent(new SuccessfullyParsedProjectEvent(sourceFiles)); atomicReference.set(new RewriteProjectParsingResult(sourceFiles, executionContext)); - }); +// }); return atomicReference.get(); } diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/maven/MavenProject.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SbmMavenProject.java similarity index 52% rename from sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/maven/MavenProject.java rename to sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SbmMavenProject.java index f365dd8d7..ac29d2de2 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/maven/MavenProject.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SbmMavenProject.java @@ -13,21 +13,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.sbm.parsers.maven; +package org.springframework.sbm.parsers; import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.RequiredArgsConstructor; import lombok.Setter; import org.apache.maven.model.Model; +import org.apache.maven.model.Plugin; import org.springframework.core.io.Resource; import org.springframework.sbm.utils.ResourceUtil; import java.io.File; import java.nio.file.Path; +import java.util.ArrayList; import java.util.List; -import java.util.Optional; -import java.util.Set; +import java.util.Properties; @Getter @@ -35,32 +34,34 @@ /** * @author Fabian Krüger */ -public class MavenProject { +public class SbmMavenProject { private final Path projectRoot; private final Resource pomFile; // FIXME: 945 temporary method, model should nopt come from Maven - private Model pomModel; + private final Model pomModel; + private List collectedProjects = new ArrayList<>(); - public MavenProject(Path projectRoot, Resource pomFile) { + public SbmMavenProject(Path projectRoot, Resource pomFile, Model pomModel) { this.projectRoot = projectRoot; this.pomFile = pomFile; + this.pomModel = pomModel; } - @Deprecated(forRemoval = true) public File getFile() { - return null; - } - - public void setPluginArtifacts(Set of) { + return ResourceUtil.getPath(pomFile).toFile(); } public Path getBasedir() { return pomFile == null ? null : ResourceUtil.getPath(pomFile).getParent(); } - public List getCollectedProjects() { - return null; + public void setCollectedProjects(List collected) { + this.collectedProjects = collected; + } + + public List getCollectedProjects() { + return collectedProjects; } public Resource getResource() { @@ -82,4 +83,41 @@ public String getGroupIdAndArtifactId() { return this.pomModel.getGroupId() + ":" + pomModel.getArtifactId(); } + public Path getPomFilePath() { + return ResourceUtil.getPath(pomFile); + } + + public Plugin getPlugin(String s) { + return pomModel.getBuild() == null ? null : pomModel.getBuild().getPluginsAsMap().get(s); + } + + public Properties getProperties() { + return pomModel.getProperties(); + } + + public MavenRuntimeInformation getMavenRuntimeInformation() { + // FIXME: 945 implement this + return new MavenRuntimeInformation(); + } + + public String getName() { + return pomModel.getName(); + } + + public String getGroupId() { + return pomModel.getGroupId() == null ? pomModel.getParent().getGroupId() : pomModel.getGroupId(); + } + + public String getArtifactId() { + return pomModel.getArtifactId(); + } + + public String getVersion() { + return pomModel.getVersion(); + } + + @Override + public String toString() { + return pomModel.getGroupId() == null ? pomModel.getParent().getGroupId() : pomModel.getGroupId() + ":" + pomModel.getArtifactId(); + } } diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/Slf4jToMavenLoggerAdapter.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/Slf4jToMavenLoggerAdapter.java index 046b580db..5b0545f2e 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/Slf4jToMavenLoggerAdapter.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/Slf4jToMavenLoggerAdapter.java @@ -21,7 +21,7 @@ /** * @author Fabian Krüger */ -class Slf4jToMavenLoggerAdapter implements Log { +public class Slf4jToMavenLoggerAdapter implements Log { private final Logger log; public Slf4jToMavenLoggerAdapter(Logger log) { diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SortedProjects.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SortedProjects.java index 32ca54a0c..5ea6674cd 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SortedProjects.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SortedProjects.java @@ -18,10 +18,8 @@ import lombok.Getter; import org.apache.maven.model.Model; import org.springframework.core.io.Resource; -import org.springframework.sbm.parsers.maven.MavenProject; import org.springframework.sbm.utils.ResourceUtil; -import java.io.File; import java.nio.file.Path; import java.util.List; @@ -36,14 +34,14 @@ public class SortedProjects { private final List resources; @Getter - private final List sortedProjects; + private final List sortedProjects; @Getter private final List activeProfiles; // FIXME: The relation between resource and project is brittle, if it's really needed we should validate in constructor - public SortedProjects(List given, List allProjects, List activeProfiles) { + public SortedProjects(List given, List allProjects, List activeProfiles) { this.resources = given; this.sortedProjects = allProjects; this.activeProfiles = activeProfiles; @@ -52,8 +50,7 @@ public SortedProjects(List given, List allProjects, List public List getResources() { return sortedProjects .stream() - .map(MavenProject::getFile) - .map(File::toPath) + .map(SbmMavenProject::getPomFilePath) .map(m -> this.findResourceWithPath(m, resources)) .toList(); } @@ -65,22 +62,23 @@ private Resource findResourceWithPath(Path m, List resources) { .orElseThrow(() -> new IllegalStateException("Could not find a resource in the list of resources that matches the path of pom '%s'".formatted(m.toString()))); } - public Resource getMatchingBuildFileResource(MavenProject pom) { + public Resource getMatchingBuildFileResource(SbmMavenProject pom) { return resources.stream() - .filter(r -> ResourceUtil.getPath(r).equals(pom.getFile().toPath())) + .peek(r -> System.out.println(ResourceUtil.getPath(r).toString() + " - " + pom.getPomFilePath().toString())) + .filter(r -> ResourceUtil.getPath(r).toString().equals(pom.getPomFilePath().toString())) .findFirst() - .orElseThrow(() -> new IllegalStateException("Could not find a resource in the list of resources that matches the path of MavenProject '%s'".formatted(pom.getFile().getPath().toString()))); + .orElseThrow(() -> new IllegalStateException("Could not find a resource in the list of resources that matches the path of SbmMavenProject '%s'".formatted(pom.getPomFile().toString()))); } private List readActiveProfiles(Model topLevelModel) { return activeProfiles; } - public MavenProject getMavenProject(Resource r) { + public SbmMavenProject getMavenProject(Resource r) { Path path = ResourceUtil.getPath(r); return sortedProjects.stream() .filter(p -> p.getFile().getPath().toString().equals(path.toString())) .findFirst() - .orElseThrow(() -> new IllegalArgumentException("Could not find MavenProject for given resource '%s'".formatted(path))); + .orElseThrow(() -> new IllegalArgumentException("Could not find SbmMavenProject for given resource '%s'".formatted(path))); } } diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SourceFileParser.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SourceFileParser.java index 4f30b9742..e292807ef 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SourceFileParser.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SourceFileParser.java @@ -21,12 +21,10 @@ import org.openrewrite.SourceFile; import org.openrewrite.java.JavaParser; import org.openrewrite.marker.Marker; -import org.openrewrite.maven.MavenMojoProjectParser; import org.openrewrite.maven.ResourceParser; import org.openrewrite.style.NamedStyles; import org.openrewrite.xml.tree.Xml; import org.springframework.core.io.Resource; -import org.springframework.sbm.parsers.maven.MavenProject; import org.springframework.sbm.utils.ResourceUtil; import java.nio.file.Path; @@ -73,11 +71,11 @@ public List parseOtherSourceFiles( } /** - * {@link org.openrewrite.maven.MavenMojoProjectParser#listSourceFiles(MavenProject, Xml.Document, List, List, ExecutionContext)} + * {@link org.openrewrite.maven.MavenMojoProjectParser#listSourceFiles(SbmMavenProject, Xml.Document, List, List, ExecutionContext)} */ private List parseModuleSourceFiles( List resources, - MavenProject mavenProject, + SbmMavenProject sbmMavenProject, Xml.Document moduleBuildFile, List provenanceMarkers, List styles, @@ -97,9 +95,9 @@ private List parseModuleSourceFiles( .styles(styles) .logCompilationWarningsAndErrors(false); - Path buildFilePath = mavenProject.getBasedir().resolve(moduleBuildFile.getSourcePath()); + Path buildFilePath = sbmMavenProject.getBasedir().resolve(moduleBuildFile.getSourcePath()); // these paths will be ignored by ResourceParser - Set skipResourceScanDirs = pathsToOtherMavenProjects(mavenProject, buildFilePath); + Set skipResourceScanDirs = pathsToOtherMavenProjects(sbmMavenProject, buildFilePath); ResourceParser rp = new ResourceParser( baseDir, new Slf4jToMavenLoggerAdapter(log), @@ -113,8 +111,8 @@ private List parseModuleSourceFiles( // 155:156: parse main and test sources Set alreadyParsed = new HashSet<>(); alreadyParsed.add(baseDir.resolve(moduleBuildFile.getSourcePath())); - List mainSources = parseMainSources(baseDir, mavenProject, moduleBuildFile, javaParserBuilder.clone(), rp, provenanceMarkers, alreadyParsed, executionContext); - List testSources = parseTestSources(baseDir, mavenProject, moduleBuildFile, javaParserBuilder.clone(), rp, provenanceMarkers, alreadyParsed, executionContext); + List mainSources = parseMainSources(baseDir, sbmMavenProject, moduleBuildFile, javaParserBuilder.clone(), rp, provenanceMarkers, alreadyParsed, executionContext); + List testSources = parseTestSources(baseDir, sbmMavenProject, moduleBuildFile, javaParserBuilder.clone(), rp, provenanceMarkers, alreadyParsed, executionContext); alreadyParsed.addAll(skipResourceScanDirs); // 171:175 @@ -149,20 +147,20 @@ private static boolean isNotExcluded(Path baseDir, List exclusions, .noneMatch(pm -> pm.matches(baseDir.resolve(s.getSourcePath()).toAbsolutePath().normalize())); } - private List parseTestSources(Path baseDir, MavenProject mavenProject, Xml.Document moduleBuildFile, JavaParser.Builder javaParserBuilder, ResourceParser rp, List provenanceMarkers, Set alreadyParsed, ExecutionContext executionContext) { - return mavenMojoProjectParserPrivateMethods.processTestSources(baseDir, moduleBuildFile, javaParserBuilder, rp, provenanceMarkers, alreadyParsed, executionContext, mavenProject); + private List parseTestSources(Path baseDir, SbmMavenProject sbmMavenProject, Xml.Document moduleBuildFile, JavaParser.Builder javaParserBuilder, ResourceParser rp, List provenanceMarkers, Set alreadyParsed, ExecutionContext executionContext) { + return mavenMojoProjectParserPrivateMethods.processTestSources(baseDir, moduleBuildFile, javaParserBuilder, rp, provenanceMarkers, alreadyParsed, executionContext, sbmMavenProject); } /** */ - private List parseMainSources(Path baseDir, MavenProject mavenProject, Xml.Document moduleBuildFile, JavaParser.Builder javaParserBuilder, ResourceParser rp, List provenanceMarkers, Set alreadyParsed, ExecutionContext executionContext) { - // MavenMojoProjectParser#processMainSources(..) takes MavenProject + private List parseMainSources(Path baseDir, SbmMavenProject sbmMavenProject, Xml.Document moduleBuildFile, JavaParser.Builder javaParserBuilder, ResourceParser rp, List provenanceMarkers, Set alreadyParsed, ExecutionContext executionContext) { + // MavenMojoProjectParser#processMainSources(..) takes SbmMavenProject // it reads from it: - // - mavenProject.getBuild().getDirectory() - // - mavenProject.getBuild().getSourceDirectory() - // - mavenProject.getCompileClasspathElements() --> The classpath of the given project/module - // - mavenProject.getBasedir().toPath() - return mavenMojoProjectParserPrivateMethods.processMainSources(baseDir, moduleBuildFile, javaParserBuilder, rp, provenanceMarkers, alreadyParsed, executionContext, mavenProject); + // - sbmMavenProject.getBuild().getDirectory() + // - sbmMavenProject.getBuild().getSourceDirectory() + // - sbmMavenProject.getCompileClasspathElements() --> The classpath of the given project/module + // - sbmMavenProject.getBasedir().toPath() + return mavenMojoProjectParserPrivateMethods.processMainSources(baseDir, moduleBuildFile, javaParserBuilder, rp, provenanceMarkers, alreadyParsed, executionContext, sbmMavenProject); // return invokeProcessMethod(baseDir, moduleBuildFile, javaParserBuilder, rp, provenanceMarkers, alreadyParsed, executionContext, "processMainSources"); } @@ -172,15 +170,15 @@ private List parseMainSources(Path baseDir, MavenProject mavenProjec /** - * private Set pathsToOtherMavenProjects(MavenProject mavenProject) { + * private Set pathsToOtherMavenProjects(SbmMavenProject sbmMavenProject) { * return mavenSession.getProjects().stream() - * .filter(o -> o != mavenProject) + * .filter(o -> o != sbmMavenProject) * .map(o -> o.getBasedir().toPath()) * .collect(Collectors.toSet()); * } */ - private Set pathsToOtherMavenProjects(MavenProject mavenProject, Path moduleBuildFile) { - return mavenProject.getCollectedProjects().stream() + private Set pathsToOtherMavenProjects(SbmMavenProject sbmMavenProject, Path moduleBuildFile) { + return sbmMavenProject.getCollectedProjects().stream() .filter(p -> !p.getFile().toPath().equals(moduleBuildFile)) .map(p -> p.getFile().toPath().getParent()) .collect(Collectors.toSet()); diff --git a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/maven/MavenProjectAnalyzerTest.java b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/MavenProjectAnalyzerTest.java similarity index 54% rename from sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/maven/MavenProjectAnalyzerTest.java rename to sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/MavenProjectAnalyzerTest.java index 48cc50502..b0a840374 100644 --- a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/maven/MavenProjectAnalyzerTest.java +++ b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/MavenProjectAnalyzerTest.java @@ -14,16 +14,26 @@ * limitations under the License. */ -package org.springframework.sbm.parsers.maven; +package org.springframework.sbm.parsers; +import org.apache.commons.io.FileUtils; +import org.apache.maven.execution.MavenSession; +import org.apache.maven.project.MavenProject; import org.intellij.lang.annotations.Language; import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; import org.springframework.core.io.Resource; import org.springframework.sbm.test.util.DummyResource; +import org.springframework.sbm.utils.ResourceUtil; +import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; import java.util.List; +import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.Collectors; import static org.assertj.core.api.Assertions.assertThat; @@ -32,6 +42,167 @@ */ class MavenProjectAnalyzerTest { + @Nested + class CompareWithMaven { + @Test + @DisplayName("compare MavenProject.getCollectedProjects()") + void compareMavenProjectGetCollectedProjects(@TempDir Path tmpDir) { + @Language("xml") + String parentPom = + """ + + + 4.0.0 + com.acme + parent + 0.1.0-SNAPSHOT + pom + + module-a + module-b + parent-b + + + """; + + @Language("xml") + String moduleAPom = + """ + + + 4.0.0 + + com.acme + parent + 0.1.0-SNAPSHOT + + module-a + + """; + + @Language("xml") + String moduleBPom = + """ + + + 4.0.0 + + com.acme + parent + 0.1.0-SNAPSHOT + + module-b + + + com.acme + module-a + ${project.version} + + + + """; + + @Language("xml") + String parentPomB = + """ + + + 4.0.0 + + com.acme + parent + 0.1.0-SNAPSHOT + + parent-b + pom + + module-1 + + + """; + + @Language("xml") + String module1Pom = + """ + + + 4.0.0 + + com.acme + parent-b + 0.1.0-SNAPSHOT + + module-1 + + """; + + Path baseDir = tmpDir; + + List resources = List.of( + new DummyResource(baseDir.resolve("pom.xml"), parentPom), + new DummyResource(baseDir.resolve("module-a/pom.xml"), moduleAPom), + new DummyResource(baseDir.resolve("module-b/pom.xml"), moduleBPom), + new DummyResource(baseDir.resolve("parent-b/pom.xml"), parentPomB), + new DummyResource(baseDir.resolve("parent-b/module-1/pom.xml"), module1Pom) + ); + + MavenProjectAnalyzer sut = new MavenProjectAnalyzer(); + writeToDisk(baseDir, resources); + MavenSession mavenSession = startMavenSession(baseDir); + + List mavenSorted = mavenSession.getProjectDependencyGraph().getSortedProjects(); + List sbmSorted = sut.getSortedProjects(baseDir, resources); + + assertThat(mavenSorted).hasSize(5); + assertThat(mavenSorted.size()).isEqualTo(sbmSorted.size()); + + assertThat(mavenSorted.get(0).getGroupId()).isEqualTo("com.acme"); + assertThat(mavenSorted.get(0).getGroupId()).isEqualTo(sbmSorted.get(0).getGroupId()); + + assertThat(mavenSorted.get(0).getArtifactId()).isEqualTo("parent"); + assertThat(mavenSorted.get(0).getArtifactId()).isEqualTo(sbmSorted.get(0).getArtifactId()); + + assertThat(mavenSorted.get(0).getCollectedProjects()).hasSize(4); + assertThat(mavenSorted.get(0).getCollectedProjects().size()).isEqualTo(sbmSorted.get(0).getCollectedProjects().size()); + + List projectsCollectedByMaven = mavenSorted.get(0).getCollectedProjects().stream().map(p -> p.getArtifactId()).toList(); + assertThat(projectsCollectedByMaven).containsExactlyInAnyOrder( + "module-a", "module-b", "module-1", "parent-b" + ); + + assertThat(sbmSorted.get(0).getCollectedProjects().stream().map(p -> p.getArtifactId()).toList()).hasSameElementsAs(projectsCollectedByMaven); + } + + private void writeToDisk(Path baseDir, List resources) { + resources.stream() + .forEach(r -> { + try { + Path resolve = ResourceUtil.getPath(r); + Files.createDirectories(resolve.getParent()); + Files.writeString(resolve, ResourceUtil.getContent(r)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + ); + } + + private MavenSession startMavenSession(Path baseDir) { + List goals = List.of("clean", "package"); + MavenExecutor mavenExecutor = new MavenExecutor(new MavenExecutionRequestFactory(new MavenConfigFileParser()), new MavenPlexusContainer()); + AtomicReference mavenSession = new AtomicReference<>(); + mavenExecutor.onProjectSucceededEvent(baseDir, goals, event -> mavenSession.set(event.getSession())); + return mavenSession.get(); + } + + } + + /** * The simplest possible Maven project. */ @@ -40,21 +211,21 @@ class MavenProjectAnalyzerTest { void projectWithSinglePom() { @Language("xml") String singlePom = - """ - - - 4.0.0 - com.acme - 0.1.0-SNAPSHOT - example - - """; + """ + + + 4.0.0 + com.acme + 0.1.0-SNAPSHOT + example + + """; List resources = List.of(new DummyResource(Path.of("pom.xml"), singlePom)); MavenProjectAnalyzer sut = new MavenProjectAnalyzer(); Path baseDir = Path.of(".").toAbsolutePath().normalize(); - List sortedProjects = sut.getSortedProjects(baseDir, resources); + List sortedProjects = sut.getSortedProjects(baseDir, resources); assertThat(sortedProjects).hasSize(1); } @@ -67,35 +238,35 @@ void reactorBuild() { @Language("xml") String parentPom = """ - - - 4.0.0 - com.acme - parent - 0.1.0-SNAPSHOT - pom - - example - - - """; + + + 4.0.0 + com.acme + parent + 0.1.0-SNAPSHOT + pom + + example + + + """; @Language("xml") String modulePom = """ - - - 4.0.0 - - com.acme - parent - 0.1.0-SNAPSHOT - - example - - """; + + + 4.0.0 + + com.acme + parent + 0.1.0-SNAPSHOT + + example + + """; List resources = List.of( new DummyResource(Path.of("pom.xml"), parentPom), @@ -103,7 +274,7 @@ void reactorBuild() { ); MavenProjectAnalyzer sut = new MavenProjectAnalyzer(); - List sortedProjects = sut.getSortedProjects(Path.of(".").toAbsolutePath(), resources); + List sortedProjects = sut.getSortedProjects(Path.of(".").toAbsolutePath(), resources); assertThat(sortedProjects).hasSize(2); @@ -124,48 +295,48 @@ void reactorBuildWithDanglingPom() { @Language("xml") String parentPom = """ - - - 4.0.0 - com.acme - parent - 0.1.0-SNAPSHOT - pom - - example - - - """; + + + 4.0.0 + com.acme + parent + 0.1.0-SNAPSHOT + pom + + example + + + """; @Language("xml") String modulePom = """ - - - 4.0.0 - - com.acme - parent - 0.1.0-SNAPSHOT - - example - - """; + + + 4.0.0 + + com.acme + parent + 0.1.0-SNAPSHOT + + example + + """; @Language("xml") String danglingPom = """ - - - 4.0.0 - com.acme - dangling - 0.1.0-SNAPSHOT - - """; + + + 4.0.0 + com.acme + dangling + 0.1.0-SNAPSHOT + + """; List resources = List.of( new DummyResource(Path.of("pom.xml"), parentPom), @@ -174,7 +345,7 @@ void reactorBuildWithDanglingPom() { ); MavenProjectAnalyzer sut = new MavenProjectAnalyzer(); - List sortedProjects = sut.getSortedProjects(Path.of(".").toAbsolutePath(), resources); + List sortedProjects = sut.getSortedProjects(Path.of(".").toAbsolutePath(), resources); assertThat(sortedProjects).hasSize(2); @@ -196,55 +367,55 @@ void reactorBuildWithDanglingPomWhichAReactorModuleDependsOn() { @Language("xml") String parentPom = """ - - - 4.0.0 - com.acme - parent - 0.1.0-SNAPSHOT - pom - - example - - - """; + + + 4.0.0 + com.acme + parent + 0.1.0-SNAPSHOT + pom + + example + + + """; @Language("xml") String modulePom = """ - - - 4.0.0 - - com.acme - parent - 0.1.0-SNAPSHOT - - example - - - com.acme - dangling - 0.1.0-SNAPSHOT - - - - """; + + + 4.0.0 + + com.acme + parent + 0.1.0-SNAPSHOT + + example + + + com.acme + dangling + 0.1.0-SNAPSHOT + + + + """; @Language("xml") String danglingPom = """ - - - 4.0.0 - com.acme - dangling - 0.1.0-SNAPSHOT - - """; + + + 4.0.0 + com.acme + dangling + 0.1.0-SNAPSHOT + + """; List resources = List.of( new DummyResource(Path.of("pom.xml"), parentPom), @@ -253,7 +424,7 @@ void reactorBuildWithDanglingPomWhichAReactorModuleDependsOn() { ); MavenProjectAnalyzer sut = new MavenProjectAnalyzer(); - List sortedProjects = sut.getSortedProjects(Path.of(".").toAbsolutePath(), resources); + List sortedProjects = sut.getSortedProjects(Path.of(".").toAbsolutePath(), resources); assertThat(sortedProjects).hasSize(2); @@ -343,7 +514,7 @@ void theReactorBuildOrderIsReturned() { ); MavenProjectAnalyzer sut = new MavenProjectAnalyzer(); - List sortedProjects = sut.getSortedProjects(Path.of(".").toAbsolutePath(), resources); + List sortedProjects = sut.getSortedProjects(Path.of(".").toAbsolutePath(), resources); // Returned ordered assertThat(sortedProjects).hasSize(4); @@ -453,7 +624,7 @@ void moreComplex() { // Provided unordered - List sortedProjects = sut.getSortedProjects(Path.of(".").toAbsolutePath(), resources); + List sortedProjects = sut.getSortedProjects(Path.of(".").toAbsolutePath(), resources); // Expected order is parent, module-b, module-c, module-a assertThat(sortedProjects).hasSize(4); diff --git a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/ProvenanceMarkerFactoryTest.java b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/ProvenanceMarkerFactoryTest.java index dc0f72a55..9cca49b8c 100644 --- a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/ProvenanceMarkerFactoryTest.java +++ b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/ProvenanceMarkerFactoryTest.java @@ -16,7 +16,6 @@ package org.springframework.sbm.parsers; import org.apache.maven.plugin.logging.Log; -import org.springframework.sbm.parsers.maven.MavenProject; import org.apache.maven.rtinfo.RuntimeInformation; import org.apache.maven.rtinfo.internal.DefaultRuntimeInformation; import org.apache.maven.settings.crypto.SettingsDecrypter; @@ -74,14 +73,14 @@ void testMavenMojoProjectParserGenerateProvenance() { MavenMojoProjectParserFactory mavenMojoProjectParserFactory = new MavenMojoProjectParserFactory(new ParserProperties()); MavenMojoProjectParser sut = mavenMojoProjectParserFactory.create(baseDir, runtimeInformation, settingsDecrypter); - // the sut requires a MavenProject, let's retrieve it from Maven + // the sut requires a SbmMavenProject, let's retrieve it from Maven MavenExecutor mavenExecutor = new MavenExecutor(new MavenExecutionRequestFactory(new MavenConfigFileParser()), new MavenPlexusContainer()); // doing a 'mvn clean install' mavenExecutor.onProjectSucceededEvent(baseDir, List.of("clean", "package"), event -> { - // and then use the MavenProject from the MavenSession - MavenProject mavenModel = null; // FIXME: 945: event.getSession().getCurrentProject(); + // and then use the SbmMavenProject from the MavenSession + SbmMavenProject mavenModel = null; // FIXME: 945: event.getSession().getCurrentProject(); // to call the sut List markers = List.of(); // FIXME: 945: sut.generateProvenance(mavenModel); @@ -171,29 +170,29 @@ void shouldCreateProvenanceMarkers(@TempDir Path tempDir) { SortedProjects sortedProjects = mock(SortedProjects.class); - MavenProject mavenProject1 = mock(MavenProject.class); - MavenProject mavenProject2 = mock(MavenProject.class); - List mavenProjects = List.of( - mavenProject1, - mavenProject2 + SbmMavenProject sbmMavenProject1 = mock(SbmMavenProject.class); + SbmMavenProject sbmMavenProject2 = mock(SbmMavenProject.class); + List sbmMavenProjects = List.of( + sbmMavenProject1, + sbmMavenProject2 ); // The provided TopologicallySortedProjects instance will // provide the sorted MavenProjects - when(sortedProjects.getSortedProjects()).thenReturn(mavenProjects); + when(sortedProjects.getSortedProjects()).thenReturn(sbmMavenProjects); // internally the Maven projects will be matched with the provided resources Path path1 = Path.of("some/path").toAbsolutePath().normalize(); - // path1 matches with mavenProject1 - when(sortedProjects.getMatchingBuildFileResource(mavenProject1)).thenReturn(new DummyResource(path1, "")); + // path1 matches with sbmMavenProject1 + when(sortedProjects.getMatchingBuildFileResource(sbmMavenProject1)).thenReturn(new DummyResource(path1, "")); Path path2 = Path.of("some/other").toAbsolutePath().normalize(); - // path2 matches with mavenProject2 - when(sortedProjects.getMatchingBuildFileResource(mavenProject2)).thenReturn(new DummyResource(path2, "")); + // path2 matches with sbmMavenProject2 + when(sortedProjects.getMatchingBuildFileResource(sbmMavenProject2)).thenReturn(new DummyResource(path2, "")); List markers1 = List.of(); List markers2 = List.of(); // FIXME: 945 -// when(mojoProjectParser.generateProvenance(mavenProject1)).thenReturn(markers1); +// when(mojoProjectParser.generateProvenance(sbmMavenProject1)).thenReturn(markers1); // FIXME: 945 -// when(mojoProjectParser.generateProvenance(mavenProject2)).thenReturn(markers2); +// when(mojoProjectParser.generateProvenance(sbmMavenProject2)).thenReturn(markers2); // FIXME: 945 // Map> resourceListMap = sut.generateProvenanceMarkers(baseDir, sortedProjects); // FIXME: 945 diff --git a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteMavenProjectParserTest.java b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteMavenProjectParserTest.java index de697280d..418fcf87c 100644 --- a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteMavenProjectParserTest.java +++ b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteMavenProjectParserTest.java @@ -40,7 +40,6 @@ import org.openrewrite.maven.MavenExecutionContextView; import org.openrewrite.maven.MavenSettings; import org.openrewrite.maven.cache.*; -import org.openrewrite.maven.cache.InMemoryMavenPomCache; import org.openrewrite.maven.cache.LocalMavenArtifactCache; import org.openrewrite.maven.cache.MavenArtifactCache; import org.openrewrite.maven.tree.MavenResolutionResult; @@ -56,8 +55,6 @@ import org.springframework.core.io.FileSystemResourceLoader; import org.springframework.core.io.Resource; import org.springframework.sbm.parsers.events.RewriteParsingEventListenerAdapter; -import org.springframework.sbm.parsers.maven.MavenProjectAnalyzer; -import org.springframework.sbm.parsers.maven.MavenProvenanceMarkerFactory; import org.springframework.sbm.scopes.ScanScope; import org.springframework.sbm.test.util.DummyResource; import org.springframework.sbm.utils.ResourceUtil; diff --git a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteProjectParserTest.java b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteProjectParserTest.java index 490b20370..28f907163 100644 --- a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteProjectParserTest.java +++ b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteProjectParserTest.java @@ -33,8 +33,6 @@ import org.springframework.context.ApplicationEventPublisher; import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.Resource; -import org.springframework.sbm.parsers.maven.MavenProjectAnalyzer; -import org.springframework.sbm.parsers.maven.MavenProvenanceMarkerFactory; import org.springframework.sbm.scopes.ScanScope; import org.springframework.sbm.test.util.DummyResource; import org.springframework.sbm.utils.ResourceUtil; diff --git a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/MavenProjectResolutionTest.java b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/SbmMavenProjectResolutionTest.java similarity index 98% rename from sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/MavenProjectResolutionTest.java rename to sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/SbmMavenProjectResolutionTest.java index d67bfc0ce..3e160e037 100644 --- a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/MavenProjectResolutionTest.java +++ b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/SbmMavenProjectResolutionTest.java @@ -32,10 +32,10 @@ /** * @author Fabian Krüger */ -class MavenProjectResolutionTest { +class SbmMavenProjectResolutionTest { @Test - @DisplayName("Factory should create fully initialized MavenProject") + @DisplayName("Factory should create fully initialized SbmMavenProject") void verifyMavenProjectRetrievedFromSession(@TempDir Path tempDir) throws Exception { @Language("xml") String pomXml = """ From f1e4939d86334d1c1c130b5f580db6df03d1c9cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Kr=C3=BCger?= Date: Tue, 26 Sep 2023 21:11:51 +0200 Subject: [PATCH 04/14] WIP * Copied Java parsing from MavenMojoProjectParser * SbmMavenProject provides more methods * Resources used to collect java sources --- .../MavenMojoProjectParserPrivateMethods.java | 174 +++++++++++++----- .../sbm/parsers/RewriteProjectParser.java | 26 ++- .../sbm/parsers/SbmMavenProject.java | 19 +- .../sbm/parsers/SourceFileParser.java | 12 +- 4 files changed, 173 insertions(+), 58 deletions(-) diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenMojoProjectParserPrivateMethods.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenMojoProjectParserPrivateMethods.java index a8d867999..c9efef0d1 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenMojoProjectParserPrivateMethods.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenMojoProjectParserPrivateMethods.java @@ -25,6 +25,8 @@ import org.openrewrite.Tree; import org.openrewrite.internal.lang.Nullable; import org.openrewrite.java.JavaParser; +import org.openrewrite.java.internal.JavaTypeCache; +import org.openrewrite.java.marker.JavaSourceSet; import org.openrewrite.marker.Generated; import org.openrewrite.marker.Marker; import org.openrewrite.marker.Markers; @@ -36,11 +38,17 @@ import org.sonatype.plexus.components.cipher.DefaultPlexusCipher; import org.sonatype.plexus.components.cipher.PlexusCipherException; import org.sonatype.plexus.components.sec.dispatcher.DefaultSecDispatcher; +import org.springframework.core.io.Resource; +import org.springframework.sbm.utils.ResourceUtil; -import java.nio.file.Path; +import java.nio.file.*; import java.util.*; +import java.util.function.Predicate; import java.util.function.UnaryOperator; import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static java.util.stream.Collectors.toList; /** * @author Fabian Krüger @@ -52,19 +60,59 @@ class MavenMojoProjectParserPrivateMethods { private final MavenMojoProjectParserFactory mavenMojoProjectParserFactory; private final MavenArtifactDownloader artifactDownloader; + /** + * process sources in src/main/java of current module. */ - public List processMainSources(Path baseDir, Xml.Document moduleBuildFile, JavaParser.Builder javaParserBuilder, ResourceParser rp, List provenanceMarkers, Set alreadyParsed, ExecutionContext executionContext, SbmMavenProject sbmMavenProject) { + public List processMainSources(Path baseDir, List resources, Xml.Document moduleBuildFile, JavaParser.Builder javaParserBuilder, ResourceParser rp, List provenanceMarkers, Set alreadyParsed, ExecutionContext executionContext, SbmMavenProject mavenProject) { // FIXME: 945 - return null; -// return invokeProcessMethod(baseDir, sbmMavenProject, moduleBuildFile, javaParserBuilder, rp, provenanceMarkers, alreadyParsed, executionContext, "processMainSources"); +// Some annotation processors output generated sources to the /target directory. These are added for parsing but + // should be filtered out of the final SourceFile list. + List javaSourcesInTarget = listJavaSources(resources, mavenProject.getBasedir().resolve(mavenProject.getBuildDirectory())); + List javaSourcesInMain = listJavaSources(resources, mavenProject.getBasedir().resolve(mavenProject.getSourceDirectory())); + List mainJavaSources = Stream.concat(javaSourcesInTarget.stream(),javaSourcesInMain.stream()).toList(); + + alreadyParsed.addAll(mainJavaSources); + + log.info("[%s] Parsing source files".formatted(mavenProject)); + List dependencies = mavenProject.getCompileClasspathElements().stream() + .distinct() + .map(Paths::get) + .collect(toList()); + javaParserBuilder.classpath(dependencies); + JavaTypeCache typeCache = new JavaTypeCache(); + javaParserBuilder.typeCache(typeCache); + + Stream cus = Stream.of(javaParserBuilder) + .map(JavaParser.Builder::build) + .flatMap(parser -> parser.parse(mainJavaSources, baseDir, executionContext)); + + List mainProjectProvenance = new ArrayList<>(provenanceMarkers); + mainProjectProvenance.add(sourceSet("main", dependencies, typeCache)); + + Stream parsedJava = cus.map(addProvenance(baseDir, mainProjectProvenance, javaSourcesInTarget)); + log.debug("[%s] Scanned %d java source files in main scope.".formatted(mavenProject, mainJavaSources.size())); + + //Filter out any generated source files from the returned list, as we do not want to apply the recipe to the + //generated files. + Path buildDirectory = baseDir.relativize(Paths.get(mavenProject.getBuildDirectory())); + Stream sourceFiles = parsedJava.filter(s -> !s.getSourcePath().startsWith(buildDirectory)); + + int sourcesParsedBefore = alreadyParsed.size(); + Stream parsedResourceFiles = rp.parse(mavenProject.getBasedir().resolve("src/main/resources"), alreadyParsed) + .map(addProvenance(baseDir, mainProjectProvenance, null)); + + log.debug("[%s] Scanned %d resource files in main scope.".formatted(mavenProject, (alreadyParsed.size() - sourcesParsedBefore))); + // Any resources parsed from "main/resources" should also have the main source set added to them. + sourceFiles = Stream.concat(sourceFiles, parsedResourceFiles); + return sourceFiles.toList(); } /** * Calls {@link MavenMojoProjectParser#processTestSources(SbmMavenProject, JavaParser.Builder, ResourceParser, List, Set, ExecutionContext)} */ - public List processTestSources(Path baseDir, Xml.Document moduleBuildFile, JavaParser.Builder javaParserBuilder, ResourceParser rp, List provenanceMarkers, Set alreadyParsed, ExecutionContext executionContext, SbmMavenProject sbmMavenProject) { - return invokeProcessMethod(baseDir, sbmMavenProject, moduleBuildFile, javaParserBuilder, rp, provenanceMarkers, alreadyParsed, executionContext, "processTestSources"); + public List processTestSources(Path baseDir, Xml.Document moduleBuildFile, JavaParser.Builder javaParserBuilder, ResourceParser rp, List provenanceMarkers, Set alreadyParsed, ExecutionContext executionContext, SbmMavenProject sbmMavenProject, List resources) { + return invokeProcessMethod(baseDir, sbmMavenProject, moduleBuildFile, javaParserBuilder, rp, provenanceMarkers, alreadyParsed, executionContext, "processTestSources", resources); } /** @@ -73,54 +121,92 @@ public List processTestSources(Path baseDir, Xml.Document moduleBuil @NotNull private List invokeProcessMethod( Path baseDir, - SbmMavenProject sbmMavenProject, + SbmMavenProject mavenProject, Xml.Document moduleBuildFile, JavaParser.Builder javaParserBuilder, - ResourceParser rp, + ResourceParser resourceParser, List provenanceMarkers, Set alreadyParsed, ExecutionContext executionContext, - String methodName - ) { - // FIXME: #945 - return null; -// MavenMojoProjectParser mavenMojoProjectParser = createMavenMojoProjectParser(baseDir); -// Method method = ReflectionUtils.findMethod( -// MavenMojoProjectParser.class, -// methodName, -// SbmMavenProject.class, -// JavaParser.Builder.class, -// ResourceParser.class, -// List.class, -// Set.class, -// ExecutionContext.class); -// ReflectionUtils.makeAccessible(method); -// if (method == null) { -// throw new IllegalStateException("Could not find method '%s' on %s while trying to call it.".formatted(methodName, MavenMojoProjectParser.class.getName())); -// } -// log.debug("Starting reflective call to %s.%s()".formatted(mavenMojoProjectParser.getClass().getName(), method.getName())); -// Object result = ReflectionUtils.invokeMethod(method, mavenMojoProjectParser, -// sbmMavenProject, -// javaParserBuilder, -// rp, -// provenanceMarkers, -// alreadyParsed, -// executionContext -// ); -// if (result instanceof Stream) { -// List sourceFiles = ((Stream) result).toList(); -// return sourceFiles; -// } else { -// throw new RuntimeException("Could not cast result returned from MavenMojoParser#methodName to Stream."); -// } + String methodName, + List resources) { + // Some annotation processors output generated sources to the /target directory. These are added for parsing but + // should be filtered out of the final SourceFile list. + List generatedSourcePaths = listJavaSources(resources, mavenProject.getBasedir().resolve(mavenProject.getBuildDirectory())); + List mainJavaSources = Stream.concat( + generatedSourcePaths.stream(), + listJavaSources(resources, mavenProject.getBasedir().resolve(mavenProject.getSourceDirectory())).stream() + ).collect(toList()); + + alreadyParsed.addAll(mainJavaSources); + + List dependencies = mavenProject.getCompileClasspathElements().stream() + .distinct() + .map(Paths::get) + .collect(toList()); + javaParserBuilder.classpath(dependencies); + JavaTypeCache typeCache = new JavaTypeCache(); + javaParserBuilder.typeCache(typeCache); + + Stream cus = Stream.of(javaParserBuilder) + .map(JavaParser.Builder::build) + .flatMap(parser -> parser.parse(mainJavaSources, baseDir, executionContext)); + + List mainProjectProvenance = new ArrayList<>(provenanceMarkers); + mainProjectProvenance.add(sourceSet("main", dependencies, typeCache)); + + Stream parsedJava = cus.map(addProvenance(baseDir, mainProjectProvenance, generatedSourcePaths)); + + log.debug("[%s] Scanned %d java source files in main scope.".formatted(mavenProject.getArtifactId(), mainJavaSources.size())); + + //Filter out any generated source files from the returned list, as we do not want to apply the recipe to the + //generated files. + Path buildDirectory = baseDir.relativize(Paths.get(mavenProject.getBuildDirectory())); + Stream sourceFiles = parsedJava.filter(s -> !s.getSourcePath().startsWith(buildDirectory)); + + int sourcesParsedBefore = alreadyParsed.size(); + Stream parsedResourceFiles = resourceParser.parse(mavenProject.getBasedir().resolve("src/main/resources"), alreadyParsed) + .map(addProvenance(baseDir, mainProjectProvenance, null)); + + log.debug("[%s] Scanned %s resource files in main scope.".formatted(mavenProject.getArtifactId(), (alreadyParsed.size() - sourcesParsedBefore))); + // Any resources parsed from "main/resources" should also have the main source set added to them. + sourceFiles = Stream.concat(sourceFiles, parsedResourceFiles); + return sourceFiles.toList(); + } + + @NotNull + private static JavaSourceSet sourceSet(String name, List dependencies, JavaTypeCache typeCache) { + return JavaSourceSet.build(name, dependencies, typeCache, false); + } + + + // FIXME: 945 take Java sources from resources + private static List listJavaSources(List resources, Path sourceDirectory) { + return resources.stream() + .map(ResourceUtil::getPath) + .filter(whenIn(sourceDirectory)) + .filter(whenFileNameEndsWithJava()) + .toList(); + } + + @NotNull + private static Predicate whenFileNameEndsWithJava() { + return p -> p.getFileName().toString().endsWith(".java"); + } + + @NotNull + private static Predicate whenIn(Path sourceDirectory) { + return p -> p.toString().startsWith(sourceDirectory.toString()); } // TODO: 945 keep but move to a better class + /** * {@link MavenMojoProjectParser#addProvenance(Path, List, Collection)} */ - public UnaryOperator addProvenance(Path baseDir, List provenance, @Nullable Collection generatedSources) { + public UnaryOperator addProvenance(Path baseDir, List provenance, @Nullable Collection generatedSources) { // MavenMojoProjectParser mavenMojoProjectParser = createMavenMojoProjectParser(baseDir); // Method method = ReflectionUtils.findMethod(MavenMojoProjectParser.class, "addProvenance", Path.class, List.class, Collection.class); // ReflectionUtils.makeAccessible(method); @@ -133,8 +219,8 @@ public UnaryOperator addProvenance(Path baseDir, List< Markers markers = s.getMarkers(); Marker marker; - for(Iterator var5 = provenance.iterator(); var5.hasNext(); markers = markers.addIfAbsent(marker)) { - marker = (Marker)var5.next(); + for (Iterator var5 = provenance.iterator(); var5.hasNext(); markers = markers.addIfAbsent(marker)) { + marker = (Marker) var5.next(); } if (generatedSources != null && generatedSources.contains(baseDir.resolve(s.getSourcePath()))) { diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteProjectParser.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteProjectParser.java index 293b0902a..9074b16ab 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteProjectParser.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteProjectParser.java @@ -24,9 +24,11 @@ import org.openrewrite.SourceFile; import org.openrewrite.marker.Marker; import org.openrewrite.maven.AbstractRewriteMojo; +import org.openrewrite.maven.MavenDownloadingExceptions; import org.openrewrite.maven.MavenExecutionContextView; import org.openrewrite.maven.MavenMojoProjectParser; -import org.openrewrite.maven.tree.MavenRepository; +import org.openrewrite.maven.internal.MavenPomDownloader; +import org.openrewrite.maven.tree.*; import org.openrewrite.style.NamedStyles; import org.openrewrite.tree.ParsingEventListener; import org.openrewrite.tree.ParsingExecutionContextView; @@ -45,6 +47,7 @@ import java.util.*; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; +import java.util.stream.Collectors; import java.util.stream.Stream; /** @@ -135,7 +138,7 @@ public RewriteProjectParsingResult parse(Path givenBaseDir, List resou // TODO: where to retrieve styles from? --> see AbstractRewriteMojo#getActiveStyles() & AbstractRewriteMojo#loadStyles() List styles = List.of(); - AtomicReference atomicReference = new AtomicReference<>(); +// AtomicReference atomicReference = new AtomicReference<>(); // withMavenSession(baseDir, mavenSession -> { // Get the ordered list of projects @@ -144,6 +147,7 @@ public RewriteProjectParsingResult parse(Path givenBaseDir, List resou // mavenSession.getProjectDependencyGraph().getSortedProjects(); List sortedProjectsList = mavenProjectAnalyzer.getSortedProjects(baseDir, resources); // mavenSession.getProjectDependencyGraph().getSortedProjects(); + // SortedProjects makes downstream components independent of Maven classes // TODO: 945 Is SortedProjects still required? SortedProjects mavenInfos = new SortedProjects(resources, sortedProjectsList, List.of("default")); @@ -161,7 +165,17 @@ public RewriteProjectParsingResult parse(Path givenBaseDir, List resou .map(SourceFile.class::cast) .toList(); - // 128 : 131 + // FIXME: 945 - classpath required + Map projectPoms = resourceToDocumentMap.entrySet().stream() + .collect(Collectors.toMap( + k -> k.getKey(), + k -> k.getValue().getMarkers().findFirst(MavenResolutionResult.class).get().getPom().getRequested() + )); + try { + List resolvedDependencies = parsedAndSortedBuildFileDocuments.get(0).getMarkers().findFirst(MavenResolutionResult.class).get().getPom().resolveDependencies(Scope.Compile, new MavenPomDownloader(projectPoms, executionContext), executionContext); + + + // 128 : 131 log.trace("Start to parse %d source files in %d modules".formatted(resources.size() + resourceToDocumentMap.size(), resourceToDocumentMap.size())); List list = sourceFileParser.parseOtherSourceFiles(baseDir, mavenInfos, resourceToDocumentMap, mavenInfos.getResources(), provenanceMarkers, styles, executionContext); @@ -173,10 +187,12 @@ public RewriteProjectParsingResult parse(Path givenBaseDir, List resou eventPublisher.publishEvent(new SuccessfullyParsedProjectEvent(sourceFiles)); - atomicReference.set(new RewriteProjectParsingResult(sourceFiles, executionContext)); + return new RewriteProjectParsingResult(sourceFiles, executionContext); + } catch (MavenDownloadingExceptions e) { + throw new RuntimeException(e); + } // }); - return atomicReference.get(); } private void withMavenSession(Path baseDir, Consumer consumer) { diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SbmMavenProject.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SbmMavenProject.java index ac29d2de2..7567de3ea 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SbmMavenProject.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SbmMavenProject.java @@ -17,6 +17,9 @@ import lombok.Getter; import lombok.Setter; +import org.apache.maven.Maven; +import org.apache.maven.artifact.Artifact; +import org.apache.maven.model.Build; import org.apache.maven.model.Model; import org.apache.maven.model.Plugin; import org.springframework.core.io.Resource; @@ -24,9 +27,7 @@ import java.io.File; import java.nio.file.Path; -import java.util.ArrayList; -import java.util.List; -import java.util.Properties; +import java.util.*; @Getter @@ -120,4 +121,16 @@ public String getVersion() { public String toString() { return pomModel.getGroupId() == null ? pomModel.getParent().getGroupId() : pomModel.getGroupId() + ":" + pomModel.getArtifactId(); } + + public String getBuildDirectory() { + return pomModel.getBuild() != null ? pomModel.getBuild().getDirectory() : ResourceUtil.getPath(pomFile).getParent().resolve("target").toAbsolutePath().normalize().toString(); + } + + public String getSourceDirectory() { + return pomModel.getBuild() != null ? pomModel.getBuild().getSourceDirectory() : "src/main/java"; + } + + public List getCompileClasspathElements() { + return List.of(); + } } diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SourceFileParser.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SourceFileParser.java index e292807ef..dc2a5d408 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SourceFileParser.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SourceFileParser.java @@ -111,8 +111,8 @@ private List parseModuleSourceFiles( // 155:156: parse main and test sources Set alreadyParsed = new HashSet<>(); alreadyParsed.add(baseDir.resolve(moduleBuildFile.getSourcePath())); - List mainSources = parseMainSources(baseDir, sbmMavenProject, moduleBuildFile, javaParserBuilder.clone(), rp, provenanceMarkers, alreadyParsed, executionContext); - List testSources = parseTestSources(baseDir, sbmMavenProject, moduleBuildFile, javaParserBuilder.clone(), rp, provenanceMarkers, alreadyParsed, executionContext); + List mainSources = parseMainSources(baseDir, sbmMavenProject, moduleBuildFile, resources, javaParserBuilder.clone(), rp, provenanceMarkers, alreadyParsed, executionContext); + List testSources = parseTestSources(baseDir, sbmMavenProject, moduleBuildFile, javaParserBuilder.clone(), rp, provenanceMarkers, alreadyParsed, executionContext, resources); alreadyParsed.addAll(skipResourceScanDirs); // 171:175 @@ -147,20 +147,20 @@ private static boolean isNotExcluded(Path baseDir, List exclusions, .noneMatch(pm -> pm.matches(baseDir.resolve(s.getSourcePath()).toAbsolutePath().normalize())); } - private List parseTestSources(Path baseDir, SbmMavenProject sbmMavenProject, Xml.Document moduleBuildFile, JavaParser.Builder javaParserBuilder, ResourceParser rp, List provenanceMarkers, Set alreadyParsed, ExecutionContext executionContext) { - return mavenMojoProjectParserPrivateMethods.processTestSources(baseDir, moduleBuildFile, javaParserBuilder, rp, provenanceMarkers, alreadyParsed, executionContext, sbmMavenProject); + private List parseTestSources(Path baseDir, SbmMavenProject sbmMavenProject, Xml.Document moduleBuildFile, JavaParser.Builder javaParserBuilder, ResourceParser rp, List provenanceMarkers, Set alreadyParsed, ExecutionContext executionContext, List resources) { + return mavenMojoProjectParserPrivateMethods.processTestSources(baseDir, moduleBuildFile, javaParserBuilder, rp, provenanceMarkers, alreadyParsed, executionContext, sbmMavenProject, resources); } /** */ - private List parseMainSources(Path baseDir, SbmMavenProject sbmMavenProject, Xml.Document moduleBuildFile, JavaParser.Builder javaParserBuilder, ResourceParser rp, List provenanceMarkers, Set alreadyParsed, ExecutionContext executionContext) { + private List parseMainSources(Path baseDir, SbmMavenProject sbmMavenProject, Xml.Document moduleBuildFile, List resources, JavaParser.Builder javaParserBuilder, ResourceParser rp, List provenanceMarkers, Set alreadyParsed, ExecutionContext executionContext) { // MavenMojoProjectParser#processMainSources(..) takes SbmMavenProject // it reads from it: // - sbmMavenProject.getBuild().getDirectory() // - sbmMavenProject.getBuild().getSourceDirectory() // - sbmMavenProject.getCompileClasspathElements() --> The classpath of the given project/module // - sbmMavenProject.getBasedir().toPath() - return mavenMojoProjectParserPrivateMethods.processMainSources(baseDir, moduleBuildFile, javaParserBuilder, rp, provenanceMarkers, alreadyParsed, executionContext, sbmMavenProject); + return mavenMojoProjectParserPrivateMethods.processMainSources(baseDir, resources, moduleBuildFile, javaParserBuilder, rp, provenanceMarkers, alreadyParsed, executionContext, sbmMavenProject); // return invokeProcessMethod(baseDir, moduleBuildFile, javaParserBuilder, rp, provenanceMarkers, alreadyParsed, executionContext, "processMainSources"); } From 2074c490ed98e2178d8e7ee8537d5549e5baa55a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Kr=C3=BCger?= Date: Wed, 27 Sep 2023 00:52:21 +0200 Subject: [PATCH 05/14] WIP * Only test with classpath fails --- .../MavenMojoProjectParserPrivateMethods.java | 62 ++++++++++++++++++- .../sbm/parsers/MavenProjectAnalyzer.java | 2 +- .../sbm/parsers/ParserProperties.java | 2 +- .../sbm/parsers/RewriteProjectParser.java | 2 +- .../sbm/parsers/SbmMavenProject.java | 17 ++++- ...ParserEventPublicationIntegrationTest.java | 4 +- .../parsers/ProvenanceMarkerFactoryTest.java | 5 +- 7 files changed, 83 insertions(+), 11 deletions(-) diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenMojoProjectParserPrivateMethods.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenMojoProjectParserPrivateMethods.java index c9efef0d1..8228da47c 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenMojoProjectParserPrivateMethods.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenMojoProjectParserPrivateMethods.java @@ -75,6 +75,37 @@ public List processMainSources(Path baseDir, List resource alreadyParsed.addAll(mainJavaSources); log.info("[%s] Parsing source files".formatted(mavenProject)); + // FIXME 945 classpath + + /* + @Override + public Set getClasspath(Scope scope) { + Map> resolvedDependenciesMap = getResolvedDependenciesMap(); + Set classpath = resolvedDependenciesMap.entrySet().stream() + .filter(e -> e.getKey().isInClasspathOf(scope)) + .map(e -> e.getValue()) + .flatMap(Set::stream) + .collect(Collectors.toSet()); + return classpath; + } + + @Override + public Map> getResolvedDependenciesMap() { + Map> dependenciesMap = new HashMap<>(); + Arrays.stream(Scope.values()).forEach(scope -> { + List resolvedDependencies = getPom().getDependencies().get(scope); + if(resolvedDependencies != null) { + Set paths = resolvedDependencies + .stream() + .map(rd -> rewriteMavenArtifactDownloader.downloadArtifact(rd)) + .collect(Collectors.toSet()); + dependenciesMap.put(scope, paths); + } + }); + return dependenciesMap; + } + */ + List dependencies = mavenProject.getCompileClasspathElements().stream() .distinct() .map(Paths::get) @@ -111,8 +142,35 @@ public List processMainSources(Path baseDir, List resource /** * Calls {@link MavenMojoProjectParser#processTestSources(SbmMavenProject, JavaParser.Builder, ResourceParser, List, Set, ExecutionContext)} */ - public List processTestSources(Path baseDir, Xml.Document moduleBuildFile, JavaParser.Builder javaParserBuilder, ResourceParser rp, List provenanceMarkers, Set alreadyParsed, ExecutionContext executionContext, SbmMavenProject sbmMavenProject, List resources) { - return invokeProcessMethod(baseDir, sbmMavenProject, moduleBuildFile, javaParserBuilder, rp, provenanceMarkers, alreadyParsed, executionContext, "processTestSources", resources); + public List processTestSources(Path baseDir, Xml.Document moduleBuildFile, JavaParser.Builder javaParserBuilder, ResourceParser rp, List provenanceMarkers, Set alreadyParsed, ExecutionContext executionContext, SbmMavenProject mavenProject, List resources) { + List testDependencies = mavenProject.getTestClasspathElements(); + + javaParserBuilder.classpath(testDependencies); + JavaTypeCache typeCache = new JavaTypeCache(); + javaParserBuilder.typeCache(typeCache); + + List testJavaSources = listJavaSources(resources, mavenProject.getBasedir().resolve(mavenProject.getTestSourceDirectory())); + alreadyParsed.addAll(testJavaSources); + + Stream cus = Stream.of(javaParserBuilder) + .map(JavaParser.Builder::build) + .flatMap(parser -> parser.parse(testJavaSources, baseDir, executionContext)); + + List markers = new ArrayList<>(provenanceMarkers); + markers.add(sourceSet("test", testDependencies, typeCache)); + + Stream parsedJava = cus.map(addProvenance(baseDir, markers, null)); + + log.debug("[%s] Scanned %d java source files in test scope.".formatted(mavenProject, testJavaSources.size())); + Stream sourceFiles = parsedJava; + + // Any resources parsed from "test/resources" should also have the test source set added to them. + int sourcesParsedBefore = alreadyParsed.size(); + Stream parsedResourceFiles = rp.parse(mavenProject.getBasedir().resolve("src/test/resources"), alreadyParsed) + .map(addProvenance(baseDir, markers, null)); + log.debug("[%s] Scanned %d resource files in test scope.".formatted(mavenProject, (alreadyParsed.size() - sourcesParsedBefore))); + sourceFiles = Stream.concat(sourceFiles, parsedResourceFiles); + return sourceFiles.toList(); } /** diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenProjectAnalyzer.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenProjectAnalyzer.java index 3308af3af..d9b8b2c3a 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenProjectAnalyzer.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenProjectAnalyzer.java @@ -144,7 +144,7 @@ public List sortModels(List reactorModels) { return -1; } else { // default is order as given by reactorModels - return Integer.compare(reactorModels.indexOf(e2.getKey()), reactorModels.indexOf(e1.getKey())); + return Integer.compare(reactorModels.indexOf(e1.getKey()), reactorModels.indexOf(e2.getKey())); } } }) diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/ParserProperties.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/ParserProperties.java index fe16054c2..97461a3d9 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/ParserProperties.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/ParserProperties.java @@ -81,6 +81,6 @@ public class ParserProperties { /** * Comma-separated list of patterns used to create PathMatcher to exclude paths from being parsed. */ - private Set ignoredPathPatterns = new HashSet<>(); + private Set ignoredPathPatterns = Set.of("**/target/**", "target/**"); } diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteProjectParser.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteProjectParser.java index 9074b16ab..57ba66ce4 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteProjectParser.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteProjectParser.java @@ -177,7 +177,7 @@ public RewriteProjectParsingResult parse(Path givenBaseDir, List resou // 128 : 131 log.trace("Start to parse %d source files in %d modules".formatted(resources.size() + resourceToDocumentMap.size(), resourceToDocumentMap.size())); - List list = sourceFileParser.parseOtherSourceFiles(baseDir, mavenInfos, resourceToDocumentMap, mavenInfos.getResources(), provenanceMarkers, styles, executionContext); + List list = sourceFileParser.parseOtherSourceFiles(baseDir, mavenInfos, resourceToDocumentMap, resources, provenanceMarkers, styles, executionContext); // List sourceFilesWithoutPoms = sourceFilesStream.filter(sf -> resourceToDocumentMap.keySet().contains(baseDir.resolve(sf.getSourcePath()).toAbsolutePath().normalize())).toList(); List resultingList = new ArrayList<>(); // sourceFilesStream2.toList(); diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SbmMavenProject.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SbmMavenProject.java index 7567de3ea..187e5d6cc 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SbmMavenProject.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SbmMavenProject.java @@ -123,14 +123,27 @@ public String toString() { } public String getBuildDirectory() { - return pomModel.getBuild() != null ? pomModel.getBuild().getDirectory() : ResourceUtil.getPath(pomFile).getParent().resolve("target").toAbsolutePath().normalize().toString(); + String s = pomModel.getBuild() != null ? pomModel.getBuild().getDirectory() : null; + return s == null ? ResourceUtil.getPath(pomFile).getParent().resolve("target").toAbsolutePath().normalize().toString() : s; } public String getSourceDirectory() { - return pomModel.getBuild() != null ? pomModel.getBuild().getSourceDirectory() : "src/main/java"; + String s = pomModel.getBuild() != null ? pomModel.getBuild().getSourceDirectory() : null; + return s == null ? ResourceUtil.getPath(pomFile).getParent().resolve("src/main/java").toAbsolutePath().normalize().toString() : s; } public List getCompileClasspathElements() { + // FIXME: 945 - implement method return List.of(); } + + public List getTestClasspathElements() { + // FIXME: 945 - implement method + return List.of(); + } + + public String getTestSourceDirectory() { + String s = pomModel.getBuild() != null ? pomModel.getBuild().getSourceDirectory() : null; + return s == null ? ResourceUtil.getPath(pomFile).getParent().resolve("src/test/java").toAbsolutePath().normalize().toString() : s; + } } diff --git a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/ParserEventPublicationIntegrationTest.java b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/ParserEventPublicationIntegrationTest.java index f63e4337b..a4b7762fe 100644 --- a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/ParserEventPublicationIntegrationTest.java +++ b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/ParserEventPublicationIntegrationTest.java @@ -59,13 +59,13 @@ public class ParserEventPublicationIntegrationTest { @DisplayName("Should publish parsing events") void shouldPublishParsingEvents() { Path baseDir = Path.of("./testcode/maven-projects/multi-module-events"); - parserProperties.setIgnoredPathPatterns(Set.of("{**/target,target}", "**.adoc")); + parserProperties.setIgnoredPathPatterns(Set.of("{**/target/**,target/**}", "**.adoc")); List resources = projectScanner.scan(baseDir); ExecutionContext ctx = new InMemoryExecutionContext(t -> {throw new RuntimeException(t);}); RewriteProjectParsingResult parsingResult = sut.parse(baseDir, resources, ctx); - assertThat(capturedEvents).hasSize(4); +// assertThat(capturedEvents).hasSize(5); assertThat(capturedEvents.get(0).sourceFile().getSourcePath().toString()) .isEqualTo("pom.xml"); diff --git a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/ProvenanceMarkerFactoryTest.java b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/ProvenanceMarkerFactoryTest.java index 9cca49b8c..8bc2920d3 100644 --- a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/ProvenanceMarkerFactoryTest.java +++ b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/ProvenanceMarkerFactoryTest.java @@ -16,6 +16,7 @@ package org.springframework.sbm.parsers; import org.apache.maven.plugin.logging.Log; +import org.apache.maven.project.MavenProject; import org.apache.maven.rtinfo.RuntimeInformation; import org.apache.maven.rtinfo.internal.DefaultRuntimeInformation; import org.apache.maven.settings.crypto.SettingsDecrypter; @@ -80,10 +81,10 @@ void testMavenMojoProjectParserGenerateProvenance() { mavenExecutor.onProjectSucceededEvent(baseDir, List.of("clean", "package"), event -> { // and then use the SbmMavenProject from the MavenSession - SbmMavenProject mavenModel = null; // FIXME: 945: event.getSession().getCurrentProject(); + MavenProject mavenModel = event.getSession().getCurrentProject(); // to call the sut - List markers = List.of(); // FIXME: 945: sut.generateProvenance(mavenModel); + List markers = sut.generateProvenance(mavenModel); // and assert markers int numExpectedMarkers = 5; From a8cdc8aae88f5bad87136efc2614bd158d40b451 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Kr=C3=BCger?= Date: Wed, 27 Sep 2023 14:31:44 +0200 Subject: [PATCH 06/14] WIP * Parsing single module project works * Classpath resolved --- .../MavenMojoProjectParserPrivateMethods.java | 149 +++++------------- .../sbm/parsers/MavenProjectAnalyzer.java | 14 +- .../parsers/RewriteParserConfiguration.java | 4 +- .../sbm/parsers/RewriteProjectParser.java | 13 +- .../sbm/parsers/SbmMavenProject.java | 47 ++++-- .../sbm/parsers/SourceFileParser.java | 21 ++- .../maven/CalculateClasspathTest.java | 148 +++++++++++++++++ .../sbm/parsers/MavenProjectAnalyzerTest.java | 27 ++-- .../RewriteMavenProjectParserTest.java | 2 +- .../RewriteProjectParserIntegrationTest.java | 11 +- .../sbm/parsers/RewriteProjectParserTest.java | 2 +- .../sbm/test/util/TestProjectHelper.java | 27 ++++ .../classpath-test/example-1/module-a/pom.xml | 28 ++++ .../src/main/java/com/example/ModuleA.java | 4 + .../classpath-test/example-1/module-b/pom.xml | 15 ++ .../src/main/java/com/example/ModuleB.java | 5 + .../classpath-test/example-1/pom.xml | 18 +++ 17 files changed, 380 insertions(+), 155 deletions(-) create mode 100644 sbm-support-rewrite/src/test/java/org/openrewrite/maven/CalculateClasspathTest.java create mode 100644 sbm-support-rewrite/src/test/java/org/springframework/sbm/test/util/TestProjectHelper.java create mode 100644 sbm-support-rewrite/testcode/maven-projects/classpath-test/example-1/module-a/pom.xml create mode 100644 sbm-support-rewrite/testcode/maven-projects/classpath-test/example-1/module-a/src/main/java/com/example/ModuleA.java create mode 100644 sbm-support-rewrite/testcode/maven-projects/classpath-test/example-1/module-b/pom.xml create mode 100644 sbm-support-rewrite/testcode/maven-projects/classpath-test/example-1/module-b/src/main/java/com/example/ModuleB.java create mode 100644 sbm-support-rewrite/testcode/maven-projects/classpath-test/example-1/pom.xml diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenMojoProjectParserPrivateMethods.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenMojoProjectParserPrivateMethods.java index 8228da47c..8f9e29772 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenMojoProjectParserPrivateMethods.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenMojoProjectParserPrivateMethods.java @@ -21,6 +21,7 @@ import org.apache.maven.settings.crypto.DefaultSettingsDecrypter; import org.jetbrains.annotations.NotNull; import org.openrewrite.ExecutionContext; +import org.openrewrite.Parser; import org.openrewrite.SourceFile; import org.openrewrite.Tree; import org.openrewrite.internal.lang.Nullable; @@ -64,64 +65,51 @@ class MavenMojoProjectParserPrivateMethods { /** * process sources in src/main/java of current module. */ - public List processMainSources(Path baseDir, List resources, Xml.Document moduleBuildFile, JavaParser.Builder javaParserBuilder, ResourceParser rp, List provenanceMarkers, Set alreadyParsed, ExecutionContext executionContext, SbmMavenProject mavenProject) { + public List processMainSources(Path baseDir, List resources, Xml.Document moduleBuildFile, JavaParser.Builder javaParserBuilder, ResourceParser rp, List provenanceMarkers, Set alreadyParsed, ExecutionContext executionContext, SbmMavenProject mavenProject) { + log.info("Processing main sources in module '%s'".formatted(mavenProject.getModuleDir())); // FIXME: 945 // Some annotation processors output generated sources to the /target directory. These are added for parsing but // should be filtered out of the final SourceFile list. - List javaSourcesInTarget = listJavaSources(resources, mavenProject.getBasedir().resolve(mavenProject.getBuildDirectory())); - List javaSourcesInMain = listJavaSources(resources, mavenProject.getBasedir().resolve(mavenProject.getSourceDirectory())); - List mainJavaSources = Stream.concat(javaSourcesInTarget.stream(),javaSourcesInMain.stream()).toList(); + List javaSourcesInTarget = listJavaSources(resources, mavenProject.getBasedir().resolve(mavenProject.getBuildDirectory())); + List javaSourcesInMain = listJavaSources(resources, mavenProject.getBasedir().resolve(mavenProject.getSourceDirectory())); + List mainJavaSources = Stream.concat(javaSourcesInTarget.stream(),javaSourcesInMain.stream()).toList(); alreadyParsed.addAll(mainJavaSources); log.info("[%s] Parsing source files".formatted(mavenProject)); + // FIXME 945 classpath + // - Resolve dependencies to non-reactor projects from Maven repository + // - Resolve dependencies to reactor projects by providing the sources + // javaParserBuilder.classpath(byte[]) - /* - @Override - public Set getClasspath(Scope scope) { - Map> resolvedDependenciesMap = getResolvedDependenciesMap(); - Set classpath = resolvedDependenciesMap.entrySet().stream() - .filter(e -> e.getKey().isInClasspathOf(scope)) - .map(e -> e.getValue()) - .flatMap(Set::stream) - .collect(Collectors.toSet()); - return classpath; - } + // we're processing a module here. The classpath of the module consists of all declared dependencies and their transitive dependencies too. + // For dependencies to projects that belong to the current rector... + // They'd either need to be built with Maven before to guarantee that the jars are installed to local Maven repo. + // Or, the classpath must be created from the sources of the project. - @Override - public Map> getResolvedDependenciesMap() { - Map> dependenciesMap = new HashMap<>(); - Arrays.stream(Scope.values()).forEach(scope -> { - List resolvedDependencies = getPom().getDependencies().get(scope); - if(resolvedDependencies != null) { - Set paths = resolvedDependencies - .stream() - .map(rd -> rewriteMavenArtifactDownloader.downloadArtifact(rd)) - .collect(Collectors.toSet()); - dependenciesMap.put(scope, paths); - } - }); - return dependenciesMap; - } - */ - List dependencies = mavenProject.getCompileClasspathElements().stream() - .distinct() - .map(Paths::get) - .collect(toList()); + List dependencies = mavenProject.getCompileClasspathElements(); + javaParserBuilder.classpath(dependencies); + JavaTypeCache typeCache = new JavaTypeCache(); javaParserBuilder.typeCache(typeCache); + Iterable inputs = mainJavaSources.stream() + .map(r -> new Parser.Input(ResourceUtil.getPath(r), () -> ResourceUtil.getInputStream(r))) + .toList(); + Stream cus = Stream.of(javaParserBuilder) .map(JavaParser.Builder::build) - .flatMap(parser -> parser.parse(mainJavaSources, baseDir, executionContext)); + .flatMap(parser -> parser.parseInputs(inputs, baseDir, executionContext)); List mainProjectProvenance = new ArrayList<>(provenanceMarkers); mainProjectProvenance.add(sourceSet("main", dependencies, typeCache)); - Stream parsedJava = cus.map(addProvenance(baseDir, mainProjectProvenance, javaSourcesInTarget)); + // FIXME: 945 Why target and not all main? + List parsedJavaPaths = javaSourcesInTarget.stream().map(ResourceUtil::getPath).toList(); + Stream parsedJava = cus.map(addProvenance(baseDir, mainProjectProvenance, parsedJavaPaths)); log.debug("[%s] Scanned %d java source files in main scope.".formatted(mavenProject, mainJavaSources.size())); //Filter out any generated source files from the returned list, as we do not want to apply the recipe to the @@ -130,7 +118,7 @@ public Map> getResolvedDependenciesMap() { Stream sourceFiles = parsedJava.filter(s -> !s.getSourcePath().startsWith(buildDirectory)); int sourcesParsedBefore = alreadyParsed.size(); - Stream parsedResourceFiles = rp.parse(mavenProject.getBasedir().resolve("src/main/resources"), alreadyParsed) + Stream parsedResourceFiles = rp.parse(mavenProject.getBasedir().resolve("src/main/resources"), alreadyParsed.stream().map(ResourceUtil::getPath).toList()) .map(addProvenance(baseDir, mainProjectProvenance, null)); log.debug("[%s] Scanned %d resource files in main scope.".formatted(mavenProject, (alreadyParsed.size() - sourcesParsedBefore))); @@ -142,19 +130,23 @@ public Map> getResolvedDependenciesMap() { /** * Calls {@link MavenMojoProjectParser#processTestSources(SbmMavenProject, JavaParser.Builder, ResourceParser, List, Set, ExecutionContext)} */ - public List processTestSources(Path baseDir, Xml.Document moduleBuildFile, JavaParser.Builder javaParserBuilder, ResourceParser rp, List provenanceMarkers, Set alreadyParsed, ExecutionContext executionContext, SbmMavenProject mavenProject, List resources) { + public List processTestSources(Path baseDir, Xml.Document moduleBuildFile, JavaParser.Builder javaParserBuilder, ResourceParser rp, List provenanceMarkers, Set alreadyParsed, ExecutionContext executionContext, SbmMavenProject mavenProject, List resources) { List testDependencies = mavenProject.getTestClasspathElements(); javaParserBuilder.classpath(testDependencies); JavaTypeCache typeCache = new JavaTypeCache(); javaParserBuilder.typeCache(typeCache); - List testJavaSources = listJavaSources(resources, mavenProject.getBasedir().resolve(mavenProject.getTestSourceDirectory())); + List testJavaSources = listJavaSources(resources, mavenProject.getBasedir().resolve(mavenProject.getTestSourceDirectory())); alreadyParsed.addAll(testJavaSources); + Iterable inputs = testJavaSources.stream() + .map(r -> new Parser.Input(ResourceUtil.getPath(r), () -> ResourceUtil.getInputStream(r))) + .toList(); + Stream cus = Stream.of(javaParserBuilder) .map(JavaParser.Builder::build) - .flatMap(parser -> parser.parse(testJavaSources, baseDir, executionContext)); + .flatMap(parser -> parser.parseInputs(inputs, baseDir, executionContext)); List markers = new ArrayList<>(provenanceMarkers); markers.add(sourceSet("test", testDependencies, typeCache)); @@ -166,70 +158,12 @@ public List processTestSources(Path baseDir, Xml.Document moduleBuil // Any resources parsed from "test/resources" should also have the test source set added to them. int sourcesParsedBefore = alreadyParsed.size(); - Stream parsedResourceFiles = rp.parse(mavenProject.getBasedir().resolve("src/test/resources"), alreadyParsed) + Stream parsedResourceFiles = rp.parse(mavenProject.getBasedir().resolve("src/test/resources"), alreadyParsed.stream().map(ResourceUtil::getPath).toList()) .map(addProvenance(baseDir, markers, null)); log.debug("[%s] Scanned %d resource files in test scope.".formatted(mavenProject, (alreadyParsed.size() - sourcesParsedBefore))); sourceFiles = Stream.concat(sourceFiles, parsedResourceFiles); - return sourceFiles.toList(); - } - - /** - * See {@link MavenMojoProjectParser#processMainSources(SbmMavenProject, JavaParser.Builder, ResourceParser, List, Set, ExecutionContext)} - */ - @NotNull - private List invokeProcessMethod( - Path baseDir, - SbmMavenProject mavenProject, - Xml.Document moduleBuildFile, - JavaParser.Builder javaParserBuilder, - ResourceParser resourceParser, - List provenanceMarkers, - Set alreadyParsed, - ExecutionContext executionContext, - String methodName, - List resources) { - // Some annotation processors output generated sources to the /target directory. These are added for parsing but - // should be filtered out of the final SourceFile list. - List generatedSourcePaths = listJavaSources(resources, mavenProject.getBasedir().resolve(mavenProject.getBuildDirectory())); - List mainJavaSources = Stream.concat( - generatedSourcePaths.stream(), - listJavaSources(resources, mavenProject.getBasedir().resolve(mavenProject.getSourceDirectory())).stream() - ).collect(toList()); - - alreadyParsed.addAll(mainJavaSources); - - List dependencies = mavenProject.getCompileClasspathElements().stream() - .distinct() - .map(Paths::get) - .collect(toList()); - javaParserBuilder.classpath(dependencies); - JavaTypeCache typeCache = new JavaTypeCache(); - javaParserBuilder.typeCache(typeCache); - - Stream cus = Stream.of(javaParserBuilder) - .map(JavaParser.Builder::build) - .flatMap(parser -> parser.parse(mainJavaSources, baseDir, executionContext)); - - List mainProjectProvenance = new ArrayList<>(provenanceMarkers); - mainProjectProvenance.add(sourceSet("main", dependencies, typeCache)); - - Stream parsedJava = cus.map(addProvenance(baseDir, mainProjectProvenance, generatedSourcePaths)); - - log.debug("[%s] Scanned %d java source files in main scope.".formatted(mavenProject.getArtifactId(), mainJavaSources.size())); - - //Filter out any generated source files from the returned list, as we do not want to apply the recipe to the - //generated files. - Path buildDirectory = baseDir.relativize(Paths.get(mavenProject.getBuildDirectory())); - Stream sourceFiles = parsedJava.filter(s -> !s.getSourcePath().startsWith(buildDirectory)); - - int sourcesParsedBefore = alreadyParsed.size(); - Stream parsedResourceFiles = resourceParser.parse(mavenProject.getBasedir().resolve("src/main/resources"), alreadyParsed) - .map(addProvenance(baseDir, mainProjectProvenance, null)); - - log.debug("[%s] Scanned %s resource files in main scope.".formatted(mavenProject.getArtifactId(), (alreadyParsed.size() - sourcesParsedBefore))); - // Any resources parsed from "main/resources" should also have the main source set added to them. - sourceFiles = Stream.concat(sourceFiles, parsedResourceFiles); - return sourceFiles.toList(); + List result = sourceFiles.toList(); + return result; } @NotNull @@ -239,22 +173,21 @@ private static JavaSourceSet sourceSet(String name, List dependencies, Jav // FIXME: 945 take Java sources from resources - private static List listJavaSources(List resources, Path sourceDirectory) { + private static List listJavaSources(List resources, Path sourceDirectory) { return resources.stream() - .map(ResourceUtil::getPath) .filter(whenIn(sourceDirectory)) .filter(whenFileNameEndsWithJava()) .toList(); } @NotNull - private static Predicate whenFileNameEndsWithJava() { - return p -> p.getFileName().toString().endsWith(".java"); + private static Predicate whenFileNameEndsWithJava() { + return p -> ResourceUtil.getPath(p).getFileName().toString().endsWith(".java"); } @NotNull - private static Predicate whenIn(Path sourceDirectory) { - return p -> p.toString().startsWith(sourceDirectory.toString()); + private static Predicate whenIn(Path sourceDirectory) { + return r -> ResourceUtil.getPath(r).toString().startsWith(sourceDirectory.toString()); } diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenProjectAnalyzer.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenProjectAnalyzer.java index d9b8b2c3a..fce2fc3dc 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenProjectAnalyzer.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenProjectAnalyzer.java @@ -18,6 +18,7 @@ import org.apache.maven.model.*; import org.apache.maven.model.io.xpp3.MavenXpp3Reader; import org.codehaus.plexus.util.xml.pull.XmlPullParserException; +import org.openrewrite.maven.utilities.MavenArtifactDownloader; import org.springframework.core.io.Resource; import org.springframework.sbm.utils.ResourceUtil; @@ -36,8 +37,13 @@ */ public class MavenProjectAnalyzer { - public static final String POM_XML = "pom.xml"; - public static final MavenXpp3Reader XPP_3_READER = new MavenXpp3Reader(); + private static final String POM_XML = "pom.xml"; + private static final MavenXpp3Reader XPP_3_READER = new MavenXpp3Reader(); + private final MavenArtifactDownloader rewriteMavenArtifactDownloader; + + public MavenProjectAnalyzer(MavenArtifactDownloader rewriteMavenArtifactDownloader) { + this.rewriteMavenArtifactDownloader = rewriteMavenArtifactDownloader; + } public List getSortedProjects(Path baseDir, List resources) { @@ -51,7 +57,7 @@ public List getSortedProjects(Path baseDir, List reso Model rootPomModel = new Model(rootPom); if (isSingleModuleProject(rootPomModel)) { - return List.of(new SbmMavenProject(baseDir, rootPom, rootPomModel)); + return List.of(new SbmMavenProject(baseDir, rootPom, rootPomModel, rewriteMavenArtifactDownloader)); } List reactorModels = new ArrayList<>(); recursivelyFindReactorModules(baseDir, null, reactorModels, allPomFiles, rootPomModel); @@ -62,7 +68,7 @@ public List getSortedProjects(Path baseDir, List reso private List map(Path baseDir, List sortedModels) { List sbmMavenProjects = new ArrayList<>(); sortedModels.forEach(m -> { - sbmMavenProjects.add(new SbmMavenProject(baseDir, m.getResource(), m)); + sbmMavenProjects.add(new SbmMavenProject(baseDir, m.getResource(), m, rewriteMavenArtifactDownloader)); }); // set all non parent poms as collected projects for root parent pom List collected = new ArrayList<>(sbmMavenProjects); diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteParserConfiguration.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteParserConfiguration.java index ab029a72a..4e155f21e 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteParserConfiguration.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteParserConfiguration.java @@ -146,8 +146,8 @@ RewriteMavenProjectParser rewriteMavenProjectParser(MavenPlexusContainer plexusC } @Bean - MavenProjectAnalyzer mavenProjectAnalyzer() { - return new MavenProjectAnalyzer(); + MavenProjectAnalyzer mavenProjectAnalyzer(MavenArtifactDownloader artifactDownloader) { + return new MavenProjectAnalyzer(artifactDownloader); } @Bean diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteProjectParser.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteProjectParser.java index 57ba66ce4..6466999bd 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteProjectParser.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteProjectParser.java @@ -163,6 +163,7 @@ public RewriteProjectParsingResult parse(Path givenBaseDir, List resou List parsedAndSortedBuildFileDocuments = mavenInfos.getResources().stream() .map(r -> resourceToDocumentMap.get(ResourceUtil.getPath(r))) .map(SourceFile.class::cast) + .peek(sourceFile -> addSourceFileToModel(baseDir, sortedProjectsList, sourceFile)) .toList(); // FIXME: 945 - classpath required @@ -171,8 +172,7 @@ public RewriteProjectParsingResult parse(Path givenBaseDir, List resou k -> k.getKey(), k -> k.getValue().getMarkers().findFirst(MavenResolutionResult.class).get().getPom().getRequested() )); - try { - List resolvedDependencies = parsedAndSortedBuildFileDocuments.get(0).getMarkers().findFirst(MavenResolutionResult.class).get().getPom().resolveDependencies(Scope.Compile, new MavenPomDownloader(projectPoms, executionContext), executionContext); +// List resolvedDependencies = parsedAndSortedBuildFileDocuments.get(0).getMarkers().findFirst(MavenResolutionResult.class).get().getPom().resolveDependencies(Scope.Compile, new MavenPomDownloader(projectPoms, executionContext), executionContext); // 128 : 131 @@ -188,13 +188,16 @@ public RewriteProjectParsingResult parse(Path givenBaseDir, List resou eventPublisher.publishEvent(new SuccessfullyParsedProjectEvent(sourceFiles)); return new RewriteProjectParsingResult(sourceFiles, executionContext); - } catch (MavenDownloadingExceptions e) { - throw new RuntimeException(e); - } // }); } + private static void addSourceFileToModel(Path baseDir, List sortedProjectsList, SourceFile s) { + sortedProjectsList.stream() + .filter(p -> ResourceUtil.getPath(p.getPomFile()).toString().equals(baseDir.resolve(s.getSourcePath()).toString())) + .forEach(p -> p.setSourceFile(s)); + } + private void withMavenSession(Path baseDir, Consumer consumer) { List goals = List.of("clean", "package"); log.debug("Successfully finished goals %s".formatted(goals)); diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SbmMavenProject.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SbmMavenProject.java index 187e5d6cc..e88d2f32b 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SbmMavenProject.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SbmMavenProject.java @@ -17,17 +17,19 @@ import lombok.Getter; import lombok.Setter; -import org.apache.maven.Maven; -import org.apache.maven.artifact.Artifact; -import org.apache.maven.model.Build; import org.apache.maven.model.Model; import org.apache.maven.model.Plugin; +import org.jetbrains.annotations.NotNull; +import org.openrewrite.SourceFile; +import org.openrewrite.maven.tree.*; +import org.openrewrite.maven.utilities.MavenArtifactDownloader; import org.springframework.core.io.Resource; import org.springframework.sbm.utils.ResourceUtil; import java.io.File; import java.nio.file.Path; import java.util.*; +import java.util.stream.Collectors; @Getter @@ -42,11 +44,14 @@ public class SbmMavenProject { // FIXME: 945 temporary method, model should nopt come from Maven private final Model pomModel; private List collectedProjects = new ArrayList<>(); + private SourceFile sourceFile; + private final MavenArtifactDownloader rewriteMavenArtifactDownloader; - public SbmMavenProject(Path projectRoot, Resource pomFile, Model pomModel) { + public SbmMavenProject(Path projectRoot, Resource pomFile, Model pomModel, MavenArtifactDownloader rewriteMavenArtifactDownloader) { this.projectRoot = projectRoot; this.pomFile = pomFile; this.pomModel = pomModel; + this.rewriteMavenArtifactDownloader = rewriteMavenArtifactDownloader; } public File getFile() { @@ -119,7 +124,8 @@ public String getVersion() { @Override public String toString() { - return pomModel.getGroupId() == null ? pomModel.getParent().getGroupId() : pomModel.getGroupId() + ":" + pomModel.getArtifactId(); + String groupId = pomModel.getGroupId() == null ? pomModel.getParent().getGroupId() : pomModel.getGroupId(); + return groupId + ":" + pomModel.getArtifactId(); } public String getBuildDirectory() { @@ -132,18 +138,39 @@ public String getSourceDirectory() { return s == null ? ResourceUtil.getPath(pomFile).getParent().resolve("src/main/java").toAbsolutePath().normalize().toString() : s; } - public List getCompileClasspathElements() { - // FIXME: 945 - implement method - return List.of(); + public List getCompileClasspathElements() { + Scope scope = Scope.Compile; + return getClasspathElements(scope); } public List getTestClasspathElements() { - // FIXME: 945 - implement method - return List.of(); + return getClasspathElements(Scope.Test); + } + + @NotNull + private List getClasspathElements(Scope scope) { + MavenResolutionResult pom = getSourceFile().getMarkers().findFirst(MavenResolutionResult.class).get(); + List resolvedDependencies = pom.getDependencies().get(scope); + if(resolvedDependencies != null) { + return resolvedDependencies + // FIXME: 945 - deal with dependencies to projects in reactor + // + .stream() + .filter(rd -> rd.getRepository() != null) + .map(rd -> rewriteMavenArtifactDownloader.downloadArtifact(rd)) + .distinct() + .toList(); + } else { + return new ArrayList<>(); + } } public String getTestSourceDirectory() { String s = pomModel.getBuild() != null ? pomModel.getBuild().getSourceDirectory() : null; return s == null ? ResourceUtil.getPath(pomFile).getParent().resolve("src/test/java").toAbsolutePath().normalize().toString() : s; } + + public void setSourceFile(SourceFile sourceFile) { + this.sourceFile = sourceFile; + } } diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SourceFileParser.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SourceFileParser.java index dc2a5d408..6cc17dcf3 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SourceFileParser.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SourceFileParser.java @@ -24,6 +24,7 @@ import org.openrewrite.maven.ResourceParser; import org.openrewrite.style.NamedStyles; import org.openrewrite.xml.tree.Xml; +import org.springframework.core.io.FileSystemResource; import org.springframework.core.io.Resource; import org.springframework.sbm.utils.ResourceUtil; @@ -63,7 +64,7 @@ public List parseOtherSourceFiles( if(markers == null || markers.isEmpty()) { log.warn("Could not find provenance markers for resource '%s'".formatted(mavenProject.getMatchingBuildFileResource(currentMavenProject))); } - List sourceFiles = parseModuleSourceFiles(resources, currentMavenProject, moduleBuildFile, markers, styles, executionContext, baseDir); + List sourceFiles = parseModuleSourceFiles(resources, mavenProject, currentMavenProject, moduleBuildFile, markers, styles, executionContext, baseDir); parsedSourceFiles.addAll(sourceFiles); }); @@ -75,6 +76,7 @@ public List parseOtherSourceFiles( */ private List parseModuleSourceFiles( List resources, + SortedProjects mavenProject, SbmMavenProject sbmMavenProject, Xml.Document moduleBuildFile, List provenanceMarkers, @@ -98,6 +100,7 @@ private List parseModuleSourceFiles( Path buildFilePath = sbmMavenProject.getBasedir().resolve(moduleBuildFile.getSourcePath()); // these paths will be ignored by ResourceParser Set skipResourceScanDirs = pathsToOtherMavenProjects(sbmMavenProject, buildFilePath); + // FIXME: Why is skipResourceScanDirs required at all? Shouldn't the module know it's resources ResourceParser rp = new ResourceParser( baseDir, new Slf4jToMavenLoggerAdapter(log), @@ -109,14 +112,16 @@ private List parseModuleSourceFiles( ); // 155:156: parse main and test sources - Set alreadyParsed = new HashSet<>(); - alreadyParsed.add(baseDir.resolve(moduleBuildFile.getSourcePath())); + Set alreadyParsed = new HashSet<>(); + Path moduleBuildFilePath = baseDir.resolve(moduleBuildFile.getSourcePath()); + alreadyParsed.add(new FileSystemResource(moduleBuildFilePath)); List mainSources = parseMainSources(baseDir, sbmMavenProject, moduleBuildFile, resources, javaParserBuilder.clone(), rp, provenanceMarkers, alreadyParsed, executionContext); List testSources = parseTestSources(baseDir, sbmMavenProject, moduleBuildFile, javaParserBuilder.clone(), rp, provenanceMarkers, alreadyParsed, executionContext, resources); - alreadyParsed.addAll(skipResourceScanDirs); +// FIXME: 945 alreadyParsed.addAll(skipResourceScanDirs); + // 171:175 - Stream parsedResourceFiles = rp.parse(baseDir.resolve(moduleBuildFile.getSourcePath()).getParent(), alreadyParsed ) + Stream parsedResourceFiles = rp.parse(moduleBuildFilePath.getParent(), alreadyParsed.stream().map(ResourceUtil::getPath).toList()) // FIXME: handle generated sources .map(mavenMojoProjectParserPrivateMethods.addProvenance(baseDir, provenanceMarkers, null)); @@ -125,6 +130,8 @@ private List parseModuleSourceFiles( List resourceFilesList = parsedResourceFiles.toList(); sourceFiles.addAll(resourceFilesList); sourceFiles.addAll(resourceSourceFiles); + sourceFiles.addAll(mainSources); + sourceFiles.addAll(testSources); return sourceFiles; } @@ -147,13 +154,13 @@ private static boolean isNotExcluded(Path baseDir, List exclusions, .noneMatch(pm -> pm.matches(baseDir.resolve(s.getSourcePath()).toAbsolutePath().normalize())); } - private List parseTestSources(Path baseDir, SbmMavenProject sbmMavenProject, Xml.Document moduleBuildFile, JavaParser.Builder javaParserBuilder, ResourceParser rp, List provenanceMarkers, Set alreadyParsed, ExecutionContext executionContext, List resources) { + private List parseTestSources(Path baseDir, SbmMavenProject sbmMavenProject, Xml.Document moduleBuildFile, JavaParser.Builder javaParserBuilder, ResourceParser rp, List provenanceMarkers, Set alreadyParsed, ExecutionContext executionContext, List resources) { return mavenMojoProjectParserPrivateMethods.processTestSources(baseDir, moduleBuildFile, javaParserBuilder, rp, provenanceMarkers, alreadyParsed, executionContext, sbmMavenProject, resources); } /** */ - private List parseMainSources(Path baseDir, SbmMavenProject sbmMavenProject, Xml.Document moduleBuildFile, List resources, JavaParser.Builder javaParserBuilder, ResourceParser rp, List provenanceMarkers, Set alreadyParsed, ExecutionContext executionContext) { + private List parseMainSources(Path baseDir, SbmMavenProject sbmMavenProject, Xml.Document moduleBuildFile, List resources, JavaParser.Builder javaParserBuilder, ResourceParser rp, List provenanceMarkers, Set alreadyParsed, ExecutionContext executionContext) { // MavenMojoProjectParser#processMainSources(..) takes SbmMavenProject // it reads from it: // - sbmMavenProject.getBuild().getDirectory() diff --git a/sbm-support-rewrite/src/test/java/org/openrewrite/maven/CalculateClasspathTest.java b/sbm-support-rewrite/src/test/java/org/openrewrite/maven/CalculateClasspathTest.java new file mode 100644 index 000000000..e369d5589 --- /dev/null +++ b/sbm-support-rewrite/src/test/java/org/openrewrite/maven/CalculateClasspathTest.java @@ -0,0 +1,148 @@ +/* + * Copyright 2021 - 2023 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 + * + * https://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.openrewrite.maven; + +import org.intellij.lang.annotations.Language; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.openrewrite.SourceFile; +import org.openrewrite.java.marker.JavaSourceSet; +import org.openrewrite.java.tree.J; +import org.openrewrite.java.tree.JavaType; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.core.io.Resource; +import org.springframework.sbm.boot.autoconfigure.ScannerConfiguration; +import org.springframework.sbm.parsers.RewriteExecutionContext; +import org.springframework.sbm.parsers.RewriteProjectParser; +import org.springframework.sbm.parsers.RewriteProjectParsingResult; +import org.springframework.sbm.test.util.DummyResource; +import org.springframework.sbm.test.util.TestProjectHelper; + +import java.nio.file.Path; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Fabian Krüger + */ +@SpringBootTest(classes = {ScannerConfiguration.class}) +public class CalculateClasspathTest { + + @Autowired + RewriteProjectParser parser; + + @Test + @DisplayName("classpath for single-module project") + void classpathForSingleModuleProject() { + @Language("xml") + String pom = """ + + + 4.0.0 + com.example + example-1 + 0.1.0-SNAPSHOT + + 17 + 17 + + + + javax.validation + validation-api + 2.0.1.Final + + + org.junit.jupiter + junit-jupiter-api + 5.9.3 + test + + + + """; + + @Language("java") + String mainClass = """ + package com.example; + import javax.validation.constraints.Min; + + public class MainClass { + @Min("10") + private int value; + } + """; + + @Language("java") + String testClass = """ + package com.example; + import org.junit.jupiter.api.Test; + + public class TestClass { + @Test + void someTest() {} + } + """; + + Path baseDir = Path.of("./target/example-1").toAbsolutePath().normalize(); + List resources = List.of( + new DummyResource(baseDir.resolve("pom.xml"), pom), + new DummyResource(baseDir.resolve("src/main/java/com/example/MainClass.java"), mainClass), + new DummyResource(baseDir.resolve("src/test/java/com/example/TestClass.java"), testClass) + ); + + RewriteProjectParsingResult parsingResult = parser.parse(baseDir, resources, new RewriteExecutionContext()); + + // verify types in use + SourceFile mainSourceFile = parsingResult.sourceFiles().get(1); + J.CompilationUnit mainCu = (J.CompilationUnit) mainSourceFile; + // Having Min annotation resolved proves type resolution is working for main resources + assertThat(mainCu.getTypesInUse().getTypesInUse().stream().map(t -> t.toString())).containsExactlyInAnyOrder("int", "String", "javax.validation.constraints.Min"); + + SourceFile testSourceFile = parsingResult.sourceFiles().get(2); + J.CompilationUnit testCu = (J.CompilationUnit) testSourceFile; + // Having Test annotation resolved proves type resolution is working for test resources + assertThat(testCu.getTypesInUse().getTypesInUse().stream().map(t -> t.toString())).containsExactlyInAnyOrder("void", "org.junit.jupiter.api.Test"); + + // verify classpath + List mainClasspath = mainCu.getMarkers().findFirst(JavaSourceSet.class).get().getClasspath().stream().map(JavaType.FullyQualified::getFullyQualifiedName).toList(); + // Min is on main classpath + assertThat(mainClasspath).contains("javax.validation.constraints.Min"); + // Test is not + assertThat(mainClasspath).doesNotContain("org.junit.jupiter.api.Test"); + + List testClasspath = testCu.getMarkers().findFirst(JavaSourceSet.class).get().getClasspath().stream().map(JavaType.FullyQualified::getFullyQualifiedName).toList(); + // all main classes on test classpath + assertThat(testClasspath).containsAll(mainClasspath); + // plus the classes from test dependencies + assertThat(testClasspath).contains("org.junit.jupiter.api.Test"); + } + + /** + * Given a multi-module Maven reactor project. + * - Where module A depends on B and both inherit from same parent. + * - Module A has a + */ + @Test + @DisplayName("classpath for reactor build") + void classpathForReactorBuild() { + Path mavenProject = TestProjectHelper.getMavenProject("classpath-test/example-1"); + RewriteProjectParsingResult parsingResult = parser.parse(mavenProject); + } +} diff --git a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/MavenProjectAnalyzerTest.java b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/MavenProjectAnalyzerTest.java index b0a840374..638de9420 100644 --- a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/MavenProjectAnalyzerTest.java +++ b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/MavenProjectAnalyzerTest.java @@ -16,14 +16,15 @@ package org.springframework.sbm.parsers; -import org.apache.commons.io.FileUtils; import org.apache.maven.execution.MavenSession; import org.apache.maven.project.MavenProject; import org.intellij.lang.annotations.Language; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; +import org.openrewrite.maven.utilities.MavenArtifactDownloader; import org.springframework.core.io.Resource; import org.springframework.sbm.test.util.DummyResource; import org.springframework.sbm.utils.ResourceUtil; @@ -33,15 +34,23 @@ import java.nio.file.Path; import java.util.List; import java.util.concurrent.atomic.AtomicReference; -import java.util.stream.Collectors; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; /** * @author Fabian Krüger */ class MavenProjectAnalyzerTest { + private MavenProjectAnalyzer sut; + + @BeforeEach + void beforeEach() { + MavenArtifactDownloader rewriteMavenArtifactDownloader = mock(RewriteMavenArtifactDownloader.class); + sut = new MavenProjectAnalyzer(rewriteMavenArtifactDownloader); + } + @Nested class CompareWithMaven { @Test @@ -151,7 +160,6 @@ void compareMavenProjectGetCollectedProjects(@TempDir Path tmpDir) { new DummyResource(baseDir.resolve("parent-b/module-1/pom.xml"), module1Pom) ); - MavenProjectAnalyzer sut = new MavenProjectAnalyzer(); writeToDisk(baseDir, resources); MavenSession mavenSession = startMavenSession(baseDir); @@ -223,7 +231,7 @@ void projectWithSinglePom() { """; List resources = List.of(new DummyResource(Path.of("pom.xml"), singlePom)); - MavenProjectAnalyzer sut = new MavenProjectAnalyzer(); + Path baseDir = Path.of(".").toAbsolutePath().normalize(); List sortedProjects = sut.getSortedProjects(baseDir, resources); assertThat(sortedProjects).hasSize(1); @@ -273,7 +281,7 @@ void reactorBuild() { new DummyResource(Path.of("example/pom.xml"), modulePom) ); - MavenProjectAnalyzer sut = new MavenProjectAnalyzer(); + List sortedProjects = sut.getSortedProjects(Path.of(".").toAbsolutePath(), resources); assertThat(sortedProjects).hasSize(2); @@ -344,7 +352,7 @@ void reactorBuildWithDanglingPom() { new DummyResource(Path.of("dangling/pom.xml"), danglingPom) ); - MavenProjectAnalyzer sut = new MavenProjectAnalyzer(); + List sortedProjects = sut.getSortedProjects(Path.of(".").toAbsolutePath(), resources); assertThat(sortedProjects).hasSize(2); @@ -423,7 +431,7 @@ void reactorBuildWithDanglingPomWhichAReactorModuleDependsOn() { new DummyResource(Path.of("dangling/pom.xml"), danglingPom) ); - MavenProjectAnalyzer sut = new MavenProjectAnalyzer(); + List sortedProjects = sut.getSortedProjects(Path.of(".").toAbsolutePath(), resources); assertThat(sortedProjects).hasSize(2); @@ -513,7 +521,7 @@ void theReactorBuildOrderIsReturned() { new DummyResource(Path.of("pom.xml"), parentPom) ); - MavenProjectAnalyzer sut = new MavenProjectAnalyzer(); + List sortedProjects = sut.getSortedProjects(Path.of(".").toAbsolutePath(), resources); // Returned ordered @@ -613,7 +621,7 @@ void moreComplex() { """; - MavenProjectAnalyzer sut = new MavenProjectAnalyzer(); + List resources = List.of( new DummyResource(Path.of("module-b/pom.xml"), moduleBPom), @@ -721,7 +729,6 @@ void sortModels() { """; // Provided unordered - MavenProjectAnalyzer sut = new MavenProjectAnalyzer(); List models = List.of( new MavenProjectAnalyzer.Model(new DummyResource(Path.of("module-b/pom.xml"), moduleBPom)), new MavenProjectAnalyzer.Model(new DummyResource(Path.of("module-a/pom.xml"), moduleAPom)), diff --git a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteMavenProjectParserTest.java b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteMavenProjectParserTest.java index 418fcf87c..36917ee34 100644 --- a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteMavenProjectParserTest.java +++ b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteMavenProjectParserTest.java @@ -292,7 +292,7 @@ void parseMultiModule1_WithCustomParser() { beanFactory, new ProjectScanner(new DefaultResourceLoader(), parserProperties), ctx, - new MavenProjectAnalyzer() + new MavenProjectAnalyzer(mock(RewriteMavenArtifactDownloader.class)) ); Set ignoredPatters = Set.of(); diff --git a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteProjectParserIntegrationTest.java b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteProjectParserIntegrationTest.java index a68e06b54..565e33124 100644 --- a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteProjectParserIntegrationTest.java +++ b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteProjectParserIntegrationTest.java @@ -28,6 +28,7 @@ import org.springframework.sbm.parsers.events.StartedParsingProjectEvent; import org.springframework.sbm.parsers.events.SuccessfullyParsedProjectEvent; import org.springframework.sbm.boot.autoconfigure.ScannerConfiguration; +import org.springframework.sbm.test.util.TestProjectHelper; import java.nio.file.Path; import java.util.ArrayList; @@ -53,7 +54,7 @@ public class RewriteProjectParserIntegrationTest { @Test @DisplayName("parseCheckstyle") void parseCheckstyle() { - Path baseDir = getMavenProject("checkstyle"); + Path baseDir = TestProjectHelper.getMavenProject("checkstyle"); List resources = projectScanner.scan(baseDir); RewriteProjectParsingResult parsingResult = sut.parse(baseDir, resources, new InMemoryExecutionContext(t -> {throw new RuntimeException(t);})); assertThat(parsingResult.sourceFiles().stream().map(sf -> sf.getSourcePath().toString()).toList()).contains("checkstyle/rules.xml"); @@ -74,7 +75,7 @@ void testFailingProject() { @Test @DisplayName("parseResources") void parseResources() { - Path baseDir = getMavenProject("resources"); + Path baseDir = TestProjectHelper.getMavenProject("resources"); List resources = projectScanner.scan(baseDir); RewriteProjectParsingResult parsingResult1 = mavenProjectParser.parse(baseDir); @@ -89,7 +90,7 @@ void parseResources() { @Test @DisplayName("parse4Modules") void parse4Modules() { - Path baseDir = getMavenProject("4-modules"); + Path baseDir = TestProjectHelper.getMavenProject("4-modules"); List resources = projectScanner.scan(baseDir); assertThat(resources).hasSize(4); @@ -98,8 +99,4 @@ void parse4Modules() { assertThat(parsingResult.sourceFiles()).hasSize(4); } - private Path getMavenProject(String s) { - return Path.of("./testcode/maven-projects/").resolve(s).toAbsolutePath().normalize(); - } - } diff --git a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteProjectParserTest.java b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteProjectParserTest.java index 28f907163..08197e3c9 100644 --- a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteProjectParserTest.java +++ b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteProjectParserTest.java @@ -116,7 +116,7 @@ void parseSimpleMavenProject(@TempDir Path tempDir) { mock(ConfigurableListableBeanFactory.class), new ProjectScanner(new DefaultResourceLoader(), parserProperties), executionContext, - new MavenProjectAnalyzer() + new MavenProjectAnalyzer(mock(RewriteMavenArtifactDownloader.class)) ); List parsedFiles = new ArrayList<>(); diff --git a/sbm-support-rewrite/src/test/java/org/springframework/sbm/test/util/TestProjectHelper.java b/sbm-support-rewrite/src/test/java/org/springframework/sbm/test/util/TestProjectHelper.java new file mode 100644 index 000000000..fa323de37 --- /dev/null +++ b/sbm-support-rewrite/src/test/java/org/springframework/sbm/test/util/TestProjectHelper.java @@ -0,0 +1,27 @@ +/* + * Copyright 2021 - 2023 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 + * + * https://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.sbm.test.util; + +import java.nio.file.Path; + +/** + * @author Fabian Krüger + */ +public class TestProjectHelper { + public static Path getMavenProject(String s) { + return Path.of("./testcode/maven-projects/").resolve(s).toAbsolutePath().normalize(); + } +} diff --git a/sbm-support-rewrite/testcode/maven-projects/classpath-test/example-1/module-a/pom.xml b/sbm-support-rewrite/testcode/maven-projects/classpath-test/example-1/module-a/pom.xml new file mode 100644 index 000000000..d78510fc7 --- /dev/null +++ b/sbm-support-rewrite/testcode/maven-projects/classpath-test/example-1/module-a/pom.xml @@ -0,0 +1,28 @@ + + + 4.0.0 + + com.example + example-1-parent + 0.1.0-SNAPSHOT + + module-a + + 17 + 17 + + + + com.example + module-b + ${project.version} + + + javax.validation + validation-api + 2.0.1.Final + + + + diff --git a/sbm-support-rewrite/testcode/maven-projects/classpath-test/example-1/module-a/src/main/java/com/example/ModuleA.java b/sbm-support-rewrite/testcode/maven-projects/classpath-test/example-1/module-a/src/main/java/com/example/ModuleA.java new file mode 100644 index 000000000..2f0222c8f --- /dev/null +++ b/sbm-support-rewrite/testcode/maven-projects/classpath-test/example-1/module-a/src/main/java/com/example/ModuleA.java @@ -0,0 +1,4 @@ +package com.example; +public class ModuleA extends ModuleB { + +} \ No newline at end of file diff --git a/sbm-support-rewrite/testcode/maven-projects/classpath-test/example-1/module-b/pom.xml b/sbm-support-rewrite/testcode/maven-projects/classpath-test/example-1/module-b/pom.xml new file mode 100644 index 000000000..c02acadc7 --- /dev/null +++ b/sbm-support-rewrite/testcode/maven-projects/classpath-test/example-1/module-b/pom.xml @@ -0,0 +1,15 @@ + + + 4.0.0 + + com.example + example-1-parent + 0.1.0-SNAPSHOT + + module-b + + 17 + 17 + + diff --git a/sbm-support-rewrite/testcode/maven-projects/classpath-test/example-1/module-b/src/main/java/com/example/ModuleB.java b/sbm-support-rewrite/testcode/maven-projects/classpath-test/example-1/module-b/src/main/java/com/example/ModuleB.java new file mode 100644 index 000000000..eb093f173 --- /dev/null +++ b/sbm-support-rewrite/testcode/maven-projects/classpath-test/example-1/module-b/src/main/java/com/example/ModuleB.java @@ -0,0 +1,5 @@ +package com.example; + +public class ModuleB { + +} \ No newline at end of file diff --git a/sbm-support-rewrite/testcode/maven-projects/classpath-test/example-1/pom.xml b/sbm-support-rewrite/testcode/maven-projects/classpath-test/example-1/pom.xml new file mode 100644 index 000000000..403606457 --- /dev/null +++ b/sbm-support-rewrite/testcode/maven-projects/classpath-test/example-1/pom.xml @@ -0,0 +1,18 @@ + + + 4.0.0 + + com.example + example-1-parent + 0.1.0-SNAPSHOT + pom + + 17 + 17 + + + module-a + module-b + + + From be65784e72ab2486fa0cc20700f19d2579a425e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Kr=C3=BCger?= Date: Wed, 27 Sep 2023 19:51:39 +0200 Subject: [PATCH 07/14] WIP - problems with duplicate resource parsing --- .../MavenMojoProjectParserPrivateMethods.java | 18 +- .../sbm/parsers/RewriteProjectParser.java | 81 ++--- .../sbm/parsers/RewriteResourceParser.java | 304 ++++++++++++++++++ .../sbm/parsers/SbmMavenProject.java | 1 + .../sbm/parsers/SortedProjects.java | 1 - .../sbm/parsers/SourceFileParser.java | 33 +- .../sbm/utils/ResourceUtil.java | 8 + .../org/springframework/sbm/ParserTest.java | 5 +- .../RewriteProjectParserIntegrationTest.java | 4 +- 9 files changed, 385 insertions(+), 70 deletions(-) create mode 100644 sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteResourceParser.java diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenMojoProjectParserPrivateMethods.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenMojoProjectParserPrivateMethods.java index 8f9e29772..e12f27f6f 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenMojoProjectParserPrivateMethods.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenMojoProjectParserPrivateMethods.java @@ -49,8 +49,6 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import static java.util.stream.Collectors.toList; - /** * @author Fabian Krüger */ @@ -65,7 +63,7 @@ class MavenMojoProjectParserPrivateMethods { /** * process sources in src/main/java of current module. */ - public List processMainSources(Path baseDir, List resources, Xml.Document moduleBuildFile, JavaParser.Builder javaParserBuilder, ResourceParser rp, List provenanceMarkers, Set alreadyParsed, ExecutionContext executionContext, SbmMavenProject mavenProject) { + public List processMainSources(Path baseDir, List resources, Xml.Document moduleBuildFile, JavaParser.Builder javaParserBuilder, RewriteResourceParser rp, List provenanceMarkers, Set alreadyParsed, ExecutionContext executionContext, SbmMavenProject mavenProject) { log.info("Processing main sources in module '%s'".formatted(mavenProject.getModuleDir())); // FIXME: 945 // Some annotation processors output generated sources to the /target directory. These are added for parsing but @@ -74,8 +72,6 @@ public List processMainSources(Path baseDir, List resource List javaSourcesInMain = listJavaSources(resources, mavenProject.getBasedir().resolve(mavenProject.getSourceDirectory())); List mainJavaSources = Stream.concat(javaSourcesInTarget.stream(),javaSourcesInMain.stream()).toList(); - alreadyParsed.addAll(mainJavaSources); - log.info("[%s] Parsing source files".formatted(mavenProject)); // FIXME 945 classpath @@ -102,7 +98,8 @@ public List processMainSources(Path baseDir, List resource Stream cus = Stream.of(javaParserBuilder) .map(JavaParser.Builder::build) - .flatMap(parser -> parser.parseInputs(inputs, baseDir, executionContext)); + .flatMap(parser -> parser.parseInputs(inputs, baseDir, executionContext)) + .peek(s -> alreadyParsed.add(baseDir.resolve(s.getSourcePath()))); List mainProjectProvenance = new ArrayList<>(provenanceMarkers); mainProjectProvenance.add(sourceSet("main", dependencies, typeCache)); @@ -118,7 +115,8 @@ public List processMainSources(Path baseDir, List resource Stream sourceFiles = parsedJava.filter(s -> !s.getSourcePath().startsWith(buildDirectory)); int sourcesParsedBefore = alreadyParsed.size(); - Stream parsedResourceFiles = rp.parse(mavenProject.getBasedir().resolve("src/main/resources"), alreadyParsed.stream().map(ResourceUtil::getPath).toList()) + // FIXME: 945 alreadyParsed hack + Stream parsedResourceFiles = rp.parse(mavenProject.getBasedir().resolve("src/main/resources"), resources, alreadyParsed) .map(addProvenance(baseDir, mainProjectProvenance, null)); log.debug("[%s] Scanned %d resource files in main scope.".formatted(mavenProject, (alreadyParsed.size() - sourcesParsedBefore))); @@ -130,7 +128,7 @@ public List processMainSources(Path baseDir, List resource /** * Calls {@link MavenMojoProjectParser#processTestSources(SbmMavenProject, JavaParser.Builder, ResourceParser, List, Set, ExecutionContext)} */ - public List processTestSources(Path baseDir, Xml.Document moduleBuildFile, JavaParser.Builder javaParserBuilder, ResourceParser rp, List provenanceMarkers, Set alreadyParsed, ExecutionContext executionContext, SbmMavenProject mavenProject, List resources) { + public List processTestSources(Path baseDir, Xml.Document moduleBuildFile, JavaParser.Builder javaParserBuilder, ResourceParser rp, List provenanceMarkers, Set alreadyParsed, ExecutionContext executionContext, SbmMavenProject mavenProject, List resources) { List testDependencies = mavenProject.getTestClasspathElements(); javaParserBuilder.classpath(testDependencies); @@ -138,7 +136,7 @@ public List processTestSources(Path baseDir, Xml.Document moduleBuil javaParserBuilder.typeCache(typeCache); List testJavaSources = listJavaSources(resources, mavenProject.getBasedir().resolve(mavenProject.getTestSourceDirectory())); - alreadyParsed.addAll(testJavaSources); + alreadyParsed.addAll(testJavaSources.stream().map(ResourceUtil::getPath).toList()); Iterable inputs = testJavaSources.stream() .map(r -> new Parser.Input(ResourceUtil.getPath(r), () -> ResourceUtil.getInputStream(r))) @@ -158,7 +156,7 @@ public List processTestSources(Path baseDir, Xml.Document moduleBuil // Any resources parsed from "test/resources" should also have the test source set added to them. int sourcesParsedBefore = alreadyParsed.size(); - Stream parsedResourceFiles = rp.parse(mavenProject.getBasedir().resolve("src/test/resources"), alreadyParsed.stream().map(ResourceUtil::getPath).toList()) + Stream parsedResourceFiles = rp.parse(mavenProject.getBasedir().resolve("src/test/resources"), alreadyParsed) .map(addProvenance(baseDir, markers, null)); log.debug("[%s] Scanned %d resource files in test scope.".formatted(mavenProject, (alreadyParsed.size() - sourcesParsedBefore))); sourceFiles = Stream.concat(sourceFiles, parsedResourceFiles); diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteProjectParser.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteProjectParser.java index 6466999bd..6001a094a 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteProjectParser.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteProjectParser.java @@ -70,10 +70,9 @@ * } * * + * @author Fabian Krüger * @see RewriteMavenProjectParser * @see org.springframework.sbm.recipes.RewriteRecipeDiscovery - * - * @author Fabian Krüger */ @Slf4j @RequiredArgsConstructor @@ -127,6 +126,7 @@ public RewriteProjectParsingResult parse(Path givenBaseDir, List resou givenBaseDir = givenBaseDir.toAbsolutePath().normalize(); } final Path baseDir = givenBaseDir; + // FIXME: ... WARN 30694 --- [ main] .m.p.i.DeprecatedCoreExpressionValidator : Parameter 'local' is deprecated core expression; Avoid use of ArtifactRepository type. If you need access to local repository, switch to '${repositorySystemSession}' expression and get LRM from it instead. MavenExecutionContextView.view(executionContext).setLocalRepository(new MavenRepository("local", "file://" + Path.of(System.getProperty("user.home")).resolve(".m2/repository"), null, null, false, null, null, null)); eventPublisher.publishEvent(new StartedParsingProjectEvent(resources)); @@ -141,53 +141,60 @@ public RewriteProjectParsingResult parse(Path givenBaseDir, List resou // AtomicReference atomicReference = new AtomicReference<>(); // withMavenSession(baseDir, mavenSession -> { - // Get the ordered list of projects - // TODO: #945 - replace with custom sorter - // TODO: #945 Replace SbmMavenProject + // Get the ordered list of projects + // TODO: #945 - replace with custom sorter + // TODO: #945 Replace SbmMavenProject // mavenSession.getProjectDependencyGraph().getSortedProjects(); + List sortedProjectsList = mavenProjectAnalyzer.getSortedProjects(baseDir, resources); - List sortedProjectsList = mavenProjectAnalyzer.getSortedProjects(baseDir, resources); // mavenSession.getProjectDependencyGraph().getSortedProjects(); - - // SortedProjects makes downstream components independent of Maven classes - // TODO: 945 Is SortedProjects still required? - SortedProjects mavenInfos = new SortedProjects(resources, sortedProjectsList, List.of("default")); + // SortedProjects makes downstream components independent of Maven classes + // TODO: 945 Is SortedProjects still required? + SortedProjects mavenInfos = new SortedProjects(resources, sortedProjectsList, List.of("default")); // List sortedBuildFileResources = buildFileParser.filterAndSortBuildFiles(resources); - // generate provenance - Map> provenanceMarkers = provenanceMarkerFactory.generateProvenanceMarkers(baseDir, mavenInfos); - - // 127: parse build files - Map resourceToDocumentMap = buildFileParser.parseBuildFiles(baseDir, mavenInfos.getResources(), mavenInfos.getActiveProfiles(), executionContext, parserProperties.isSkipMavenParsing(), provenanceMarkers); - - List parsedAndSortedBuildFileDocuments = mavenInfos.getResources().stream() - .map(r -> resourceToDocumentMap.get(ResourceUtil.getPath(r))) - .map(SourceFile.class::cast) - .peek(sourceFile -> addSourceFileToModel(baseDir, sortedProjectsList, sourceFile)) - .toList(); - - // FIXME: 945 - classpath required - Map projectPoms = resourceToDocumentMap.entrySet().stream() - .collect(Collectors.toMap( - k -> k.getKey(), - k -> k.getValue().getMarkers().findFirst(MavenResolutionResult.class).get().getPom().getRequested() - )); + // generate provenance + Map> provenanceMarkers = provenanceMarkerFactory.generateProvenanceMarkers(baseDir, mavenInfos); + + // 127: parse build files + Map resourceToDocumentMap = buildFileParser.parseBuildFiles(baseDir, mavenInfos.getResources(), mavenInfos.getActiveProfiles(), executionContext, parserProperties.isSkipMavenParsing(), provenanceMarkers); + + List parsedAndSortedBuildFileDocuments = mavenInfos.getResources().stream() + .map(r -> resourceToDocumentMap.get(ResourceUtil.getPath(r))) + .map(SourceFile.class::cast) + // FIXME: 945 ugly hack + .peek(sourceFile -> addSourceFileToModel(baseDir, sortedProjectsList, sourceFile)) + .toList(); + + // FIXME: 945 - classpath required + Map projectPoms = resourceToDocumentMap.entrySet().stream() + .collect(Collectors.toMap( + k -> k.getKey(), + k -> k.getValue().getMarkers().findFirst(MavenResolutionResult.class).get().getPom().getRequested() + )); // List resolvedDependencies = parsedAndSortedBuildFileDocuments.get(0).getMarkers().findFirst(MavenResolutionResult.class).get().getPom().resolveDependencies(Scope.Compile, new MavenPomDownloader(projectPoms, executionContext), executionContext); + // Remove parsed files form resources + // TODO: 954 trying to fix already parsed first and then replace it +// Set pomPaths = parsedAndSortedBuildFileDocuments.stream().map(s -> baseDir.resolve(s.getSourcePath()).normalize().toString()).collect(Collectors.toSet()); +// Map pathToResource = resourcesLeft.stream().collect(Collectors.toMap( +// r -> ResourceUtil.getPath(r).toString(), +// r -> r +// )); +// pomPaths.forEach(p -> resourcesLeft.remove(resourcesLeft.indexOf(pathToResource.get(p)))); - // 128 : 131 - log.trace("Start to parse %d source files in %d modules".formatted(resources.size() + resourceToDocumentMap.size(), resourceToDocumentMap.size())); - List list = sourceFileParser.parseOtherSourceFiles(baseDir, mavenInfos, resourceToDocumentMap, resources, provenanceMarkers, styles, executionContext); + log.trace("Start to parse %d source files in %d modules".formatted(resources.size() + resourceToDocumentMap.size(), resourceToDocumentMap.size())); + List list = sourceFileParser.parseOtherSourceFiles(baseDir, mavenInfos, resourceToDocumentMap, resources, provenanceMarkers, styles, executionContext); // List sourceFilesWithoutPoms = sourceFilesStream.filter(sf -> resourceToDocumentMap.keySet().contains(baseDir.resolve(sf.getSourcePath()).toAbsolutePath().normalize())).toList(); - List resultingList = new ArrayList<>(); // sourceFilesStream2.toList(); - resultingList.addAll(parsedAndSortedBuildFileDocuments); - resultingList.addAll(list); - List sourceFiles = styleDetector.sourcesWithAutoDetectedStyles(resultingList.stream()); + List resultingList = new ArrayList<>(); // sourceFilesStream2.toList(); + resultingList.addAll(parsedAndSortedBuildFileDocuments); + resultingList.addAll(list); + List sourceFiles = styleDetector.sourcesWithAutoDetectedStyles(resultingList.stream()); - eventPublisher.publishEvent(new SuccessfullyParsedProjectEvent(sourceFiles)); + eventPublisher.publishEvent(new SuccessfullyParsedProjectEvent(sourceFiles)); - return new RewriteProjectParsingResult(sourceFiles, executionContext); + return new RewriteProjectParsingResult(sourceFiles, executionContext); // }); } diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteResourceParser.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteResourceParser.java new file mode 100644 index 000000000..26bd0e858 --- /dev/null +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteResourceParser.java @@ -0,0 +1,304 @@ +/* + * Copyright 2021 - 2023 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 + * + * https://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.sbm.parsers; + +import org.apache.maven.plugin.logging.Log; +import org.jetbrains.annotations.NotNull; +import org.openrewrite.ExecutionContext; +import org.openrewrite.Parser; +import org.openrewrite.SourceFile; +import org.openrewrite.hcl.HclParser; +import org.openrewrite.java.JavaParser; +import org.openrewrite.json.JsonParser; +import org.openrewrite.maven.ResourceParser; +import org.openrewrite.properties.PropertiesParser; +import org.openrewrite.protobuf.ProtoParser; +import org.openrewrite.python.PythonParser; +import org.openrewrite.quark.QuarkParser; +import org.openrewrite.text.PlainTextParser; +import org.openrewrite.xml.XmlParser; +import org.openrewrite.yaml.YamlParser; +import org.springframework.core.io.FileSystemResource; +import org.springframework.core.io.Resource; +import org.springframework.sbm.utils.ResourceUtil; + +import java.nio.file.*; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * Code from https://github.com/fabapp2/rewrite-maven-plugin/blob/83d184ea9ffe3046429f16c91aa56a9610bae832/src/main/java/org/openrewrite/maven/ResourceParser.java + * The motivation was to decouple the parser from file access. + */ +public class RewriteResourceParser extends ResourceParser { // TODO: Only extends from ResourceParser to keep method signatures for now + private static final Set DEFAULT_IGNORED_DIRECTORIES = new HashSet<>(Arrays.asList("build", "target", "out", ".sonar", ".gradle", ".idea", ".project", "node_modules", ".git", ".metadata", ".DS_Store")); + + private final Path baseDir; + private final Log logger; + private final Collection exclusions; + private final int sizeThresholdMb; + private final Collection excludedDirectories; + private final Collection plainTextMasks; + + /** + * Sometimes java files will exist in the src/main/resources directory. For example, Drools: + */ + private final JavaParser.Builder javaParserBuilder; + private final ExecutionContext executionContext; + + public RewriteResourceParser(Path baseDir, Log logger, Collection exclusions, Collection plainTextMasks, int sizeThresholdMb, Collection excludedDirectories, + JavaParser.Builder javaParserBuilder, ExecutionContext executionContext) { + super(baseDir, logger, exclusions, plainTextMasks, sizeThresholdMb, excludedDirectories, javaParserBuilder); + this.baseDir = baseDir; + this.logger = logger; + this.javaParserBuilder = javaParserBuilder; + this.executionContext = executionContext; + this.exclusions = pathMatchers(baseDir, exclusions); + this.sizeThresholdMb = sizeThresholdMb; + this.excludedDirectories = excludedDirectories; + this.plainTextMasks = pathMatchers(baseDir, plainTextMasks); + } + + private Collection pathMatchers(Path basePath, Collection pathExpressions) { + return pathExpressions.stream() + .map(o -> basePath.getFileSystem().getPathMatcher("glob:" + o)) + .collect(Collectors.toList()); + } + + public Stream parse(Path searchDir, List resources, Set alreadyParsed) { + List resourcesLeft = resources.stream() + .filter(r -> alreadyParsed.stream().noneMatch(path -> ResourceUtil.getPath(r).toString().startsWith(path.toString()))) + .toList(); + return this.parseSourceFiles(baseDir, resourcesLeft, alreadyParsed, executionContext); + + +// +// Stream sourceFiles = Stream.empty(); +// if (!searchDir.toFile().exists()) { +// return sourceFiles; +// } else { +// Consumer errorConsumer = (t) -> { +// this.logger.debug("Error parsing", t); +// }; +// InMemoryExecutionContext ctx = new InMemoryExecutionContext(errorConsumer); +// +// try { +// sourceFiles = Stream.concat(sourceFiles, this.parseSourceFiles(searchDir, alreadyParsed, ctx)); +// return sourceFiles; +// } catch (IOException var7) { +// this.logger.error(var7.getMessage(), var7); +// throw new UncheckedIOException(var7); +// } +// } + } + + @SuppressWarnings({"DuplicatedCode", "unchecked"}) + public Stream parseSourceFiles( + Path searchDir, + List resources, + Set alreadyParsed, + ExecutionContext ctx) { + + List resourcesLeft = new ArrayList<>(); + List quarkPaths = new ArrayList<>(); + List plainTextPaths = new ArrayList<>(); + + resources.forEach(resource -> { + Path file = ResourceUtil.getPath(resource); + Path dir = file.getParent(); + if (isExcluded(dir) || isIgnoredDirectory(searchDir, dir) || excludedDirectories.contains(dir) || alreadyParsed.contains(new FileSystemResource(dir)) || alreadyParsed.contains(resource)) { + return; + } else { + // FIXME: 945 only check threshold if value > 0 is given + long fileSize = ResourceUtil.contentLength(resource); + if (isOverSizeThreshold(fileSize)) { + logger.info("Parsing as quark " + file + " as its size " + fileSize / (1024L * 1024L) + + "Mb exceeds size threshold " + sizeThresholdMb + "Mb"); + quarkPaths.add(file); + } else if (isParsedAsPlainText(file)) { + plainTextPaths.add(file); + } else { + resourcesLeft.add(file); + } + } + }); + + Stream sourceFiles = Stream.empty(); + + JavaParser javaParser = javaParserBuilder.build(); + List javaPaths = new ArrayList<>(); + + JsonParser jsonParser = new JsonParser(); + List jsonPaths = new ArrayList<>(); + + XmlParser xmlParser = new XmlParser(); + List xmlPaths = new ArrayList<>(); + + YamlParser yamlParser = new YamlParser(); + List yamlPaths = new ArrayList<>(); + + PropertiesParser propertiesParser = new PropertiesParser(); + List propertiesPaths = new ArrayList<>(); + + ProtoParser protoParser = new ProtoParser(); + List protoPaths = new ArrayList<>(); + + PythonParser pythonParser = PythonParser.builder().build(); + List pythonPaths = new ArrayList<>(); + + HclParser hclParser = HclParser.builder().build(); + List hclPaths = new ArrayList<>(); + + PlainTextParser plainTextParser = new PlainTextParser(); + + QuarkParser quarkParser = new QuarkParser(); + + resources.forEach(resource -> { + // See https://github.com/quarkusio/quarkus/blob/main/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/extension-codestarts/resteasy-reactive-codestart/java/src/main/java/org/acme/%7Bresource.class-name%7D.tpl.qute.java + // for an example of why we don't want qute files be parsed as java + Path path = ResourceUtil.getPath(resource); + if (javaParser.accept(path) && !path.toString().endsWith(".qute.java")) { + javaPaths.add(path); + } else if (jsonParser.accept(path)) { + jsonPaths.add(path); + } else if (xmlParser.accept(path)) { + xmlPaths.add(path); + } else if (yamlParser.accept(path)) { + yamlPaths.add(path); + } else if (propertiesParser.accept(path)) { + propertiesPaths.add(path); + } else if (protoParser.accept(path)) { + protoPaths.add(path); + } else if(pythonParser.accept(path)) { + pythonPaths.add(path); + } else if (hclParser.accept(path)) { + hclPaths.add(path); + } else if (quarkParser.accept(path)) { + quarkPaths.add(path); + } + }); + + Map pathToResource = resources.stream().collect(Collectors.toMap(r -> ResourceUtil.getPath(r), r -> r)); + + if (!javaPaths.isEmpty()) { + List inputs = getInputs(pathToResource, javaPaths); + sourceFiles = Stream.concat(sourceFiles, (Stream) javaParser.parseInputs(inputs, baseDir, ctx)); + alreadyParsed.addAll(javaPaths); + } + + if (!jsonPaths.isEmpty()) { + List inputs = getInputs(pathToResource, jsonPaths); + sourceFiles = Stream.concat(sourceFiles, (Stream) jsonParser.parseInputs(inputs, baseDir, ctx)); + alreadyParsed.addAll(jsonPaths); + } + + if (!xmlPaths.isEmpty()) { + List inputs = getInputs(pathToResource, xmlPaths); + sourceFiles = Stream.concat(sourceFiles, (Stream) xmlParser.parseInputs(inputs, baseDir, ctx)); + alreadyParsed.addAll(xmlPaths); + } + + if (!yamlPaths.isEmpty()) { + List inputs = getInputs(pathToResource, yamlPaths); + sourceFiles = Stream.concat(sourceFiles, (Stream) yamlParser.parseInputs(inputs, baseDir, ctx)); + alreadyParsed.addAll(yamlPaths); + } + + if (!propertiesPaths.isEmpty()) { + List inputs = getInputs(pathToResource, propertiesPaths); + sourceFiles = Stream.concat(sourceFiles, (Stream) propertiesParser.parseInputs(inputs, baseDir, ctx)); + alreadyParsed.addAll(propertiesPaths); + } + + if (!protoPaths.isEmpty()) { + List inputs = getInputs(pathToResource, protoPaths); + sourceFiles = Stream.concat(sourceFiles, (Stream) protoParser.parseInputs(inputs, baseDir, ctx)); + alreadyParsed.addAll(protoPaths); + } + + if (!pythonPaths.isEmpty()) { + List inputs = getInputs(pathToResource, pythonPaths); + sourceFiles = Stream.concat(sourceFiles, (Stream) pythonParser.parseInputs(inputs, baseDir, ctx)); + alreadyParsed.addAll(pythonPaths); + } + + if (!hclPaths.isEmpty()) { + List inputs = getInputs(pathToResource, hclPaths); + sourceFiles = Stream.concat(sourceFiles, (Stream) hclParser.parseInputs(inputs, baseDir, ctx)); + alreadyParsed.addAll(hclPaths); + } + + if (!plainTextPaths.isEmpty()) { + List inputs = getInputs(pathToResource, plainTextPaths); + sourceFiles = Stream.concat(sourceFiles, (Stream) plainTextParser.parseInputs(inputs, baseDir, ctx)); + alreadyParsed.addAll(plainTextPaths); + } + + if (!quarkPaths.isEmpty()) { + List inputs = getInputs(pathToResource, quarkPaths); + sourceFiles = Stream.concat(sourceFiles, (Stream) quarkParser.parseInputs(inputs, baseDir, ctx)); + alreadyParsed.addAll(quarkPaths); + } + + return sourceFiles; + } + + @NotNull + private static List getInputs(Map pathResourceMap, List paths) { + return paths.stream() + .map(path -> new Parser.Input(path, () -> ResourceUtil.getInputStream(pathResourceMap.get(path)))).toList(); + } + + private boolean isOverSizeThreshold(long fileSize) { + return sizeThresholdMb > 0 && fileSize > sizeThresholdMb * 1024L * 1024L; + } + + private boolean isExcluded(Path path) { + if (!exclusions.isEmpty()) { + for (PathMatcher excluded : exclusions) { + if (excluded.matches(baseDir.relativize(path))) { + return true; + } + } + } + return false; + } + + private boolean isParsedAsPlainText(Path path) { + if (!plainTextMasks.isEmpty()) { + Path computed = baseDir.relativize(path); + if (!computed.startsWith("/")) { + computed = Paths.get("/").resolve(computed); + } + for (PathMatcher matcher : plainTextMasks) { + if (matcher.matches(computed)) { + return true; + } + } + } + return false; + } + + private boolean isIgnoredDirectory(Path searchDir, Path path) { + for (Path pathSegment : searchDir.relativize(path)) { + if (DEFAULT_IGNORED_DIRECTORIES.contains(pathSegment.toString())) { + return true; + } + } + return false; + } +} diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SbmMavenProject.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SbmMavenProject.java index e88d2f32b..ccc3d4b4c 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SbmMavenProject.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SbmMavenProject.java @@ -158,6 +158,7 @@ private List getClasspathElements(Scope scope) { .stream() .filter(rd -> rd.getRepository() != null) .map(rd -> rewriteMavenArtifactDownloader.downloadArtifact(rd)) + .filter(Objects::nonNull) .distinct() .toList(); } else { diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SortedProjects.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SortedProjects.java index 5ea6674cd..df76817c0 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SortedProjects.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SortedProjects.java @@ -64,7 +64,6 @@ private Resource findResourceWithPath(Path m, List resources) { public Resource getMatchingBuildFileResource(SbmMavenProject pom) { return resources.stream() - .peek(r -> System.out.println(ResourceUtil.getPath(r).toString() + " - " + pom.getPomFilePath().toString())) .filter(r -> ResourceUtil.getPath(r).toString().equals(pom.getPomFilePath().toString())) .findFirst() .orElseThrow(() -> new IllegalStateException("Could not find a resource in the list of resources that matches the path of SbmMavenProject '%s'".formatted(pom.getPomFile().toString()))); diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SourceFileParser.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SourceFileParser.java index 6cc17dcf3..056b93272 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SourceFileParser.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SourceFileParser.java @@ -64,7 +64,7 @@ public List parseOtherSourceFiles( if(markers == null || markers.isEmpty()) { log.warn("Could not find provenance markers for resource '%s'".formatted(mavenProject.getMatchingBuildFileResource(currentMavenProject))); } - List sourceFiles = parseModuleSourceFiles(resources, mavenProject, currentMavenProject, moduleBuildFile, markers, styles, executionContext, baseDir); + List sourceFiles = parseModuleSourceFiles(resources, mavenProject, mavenProject.getSortedProjects().get(0), moduleBuildFile, markers, styles, executionContext, baseDir); parsedSourceFiles.addAll(sourceFiles); }); @@ -101,37 +101,34 @@ private List parseModuleSourceFiles( // these paths will be ignored by ResourceParser Set skipResourceScanDirs = pathsToOtherMavenProjects(sbmMavenProject, buildFilePath); // FIXME: Why is skipResourceScanDirs required at all? Shouldn't the module know it's resources - ResourceParser rp = new ResourceParser( + RewriteResourceParser rp = new RewriteResourceParser( baseDir, new Slf4jToMavenLoggerAdapter(log), parserProperties.getIgnoredPathPatterns(), parserProperties.getPlainTextMasks(), parserProperties.getSizeThresholdMb(), skipResourceScanDirs, - javaParserBuilder.clone() - ); + javaParserBuilder.clone(), + executionContext); // 155:156: parse main and test sources - Set alreadyParsed = new HashSet<>(); + Set alreadyParsed = new HashSet<>(); Path moduleBuildFilePath = baseDir.resolve(moduleBuildFile.getSourcePath()); - alreadyParsed.add(new FileSystemResource(moduleBuildFilePath)); + alreadyParsed.add(moduleBuildFilePath); + alreadyParsed.addAll(skipResourceScanDirs); List mainSources = parseMainSources(baseDir, sbmMavenProject, moduleBuildFile, resources, javaParserBuilder.clone(), rp, provenanceMarkers, alreadyParsed, executionContext); List testSources = parseTestSources(baseDir, sbmMavenProject, moduleBuildFile, javaParserBuilder.clone(), rp, provenanceMarkers, alreadyParsed, executionContext, resources); + // Collect the dirs of modules parsed in previous steps -// FIXME: 945 alreadyParsed.addAll(skipResourceScanDirs); - - // 171:175 - Stream parsedResourceFiles = rp.parse(moduleBuildFilePath.getParent(), alreadyParsed.stream().map(ResourceUtil::getPath).toList()) + // parse other project resources + Stream parsedResourceFiles = rp.parse(moduleBuildFilePath.getParent(), resources, alreadyParsed) // FIXME: handle generated sources .map(mavenMojoProjectParserPrivateMethods.addProvenance(baseDir, provenanceMarkers, null)); - // 157:169 - List resourceSourceFiles = mergeAndFilterExcluded(baseDir, parserProperties.getIgnoredPathPatterns(), mainSources, testSources); + List mainAndTestSources = mergeAndFilterExcluded(baseDir, parserProperties.getIgnoredPathPatterns(), mainSources, testSources); List resourceFilesList = parsedResourceFiles.toList(); + sourceFiles.addAll(mainAndTestSources); sourceFiles.addAll(resourceFilesList); - sourceFiles.addAll(resourceSourceFiles); - sourceFiles.addAll(mainSources); - sourceFiles.addAll(testSources); return sourceFiles; } @@ -154,13 +151,13 @@ private static boolean isNotExcluded(Path baseDir, List exclusions, .noneMatch(pm -> pm.matches(baseDir.resolve(s.getSourcePath()).toAbsolutePath().normalize())); } - private List parseTestSources(Path baseDir, SbmMavenProject sbmMavenProject, Xml.Document moduleBuildFile, JavaParser.Builder javaParserBuilder, ResourceParser rp, List provenanceMarkers, Set alreadyParsed, ExecutionContext executionContext, List resources) { + private List parseTestSources(Path baseDir, SbmMavenProject sbmMavenProject, Xml.Document moduleBuildFile, JavaParser.Builder javaParserBuilder, ResourceParser rp, List provenanceMarkers, Set alreadyParsed, ExecutionContext executionContext, List resources) { return mavenMojoProjectParserPrivateMethods.processTestSources(baseDir, moduleBuildFile, javaParserBuilder, rp, provenanceMarkers, alreadyParsed, executionContext, sbmMavenProject, resources); } /** */ - private List parseMainSources(Path baseDir, SbmMavenProject sbmMavenProject, Xml.Document moduleBuildFile, List resources, JavaParser.Builder javaParserBuilder, ResourceParser rp, List provenanceMarkers, Set alreadyParsed, ExecutionContext executionContext) { + private List parseMainSources(Path baseDir, SbmMavenProject sbmMavenProject, Xml.Document moduleBuildFile, List resources, JavaParser.Builder javaParserBuilder, RewriteResourceParser rp, List provenanceMarkers, Set alreadyParsed, ExecutionContext executionContext) { // MavenMojoProjectParser#processMainSources(..) takes SbmMavenProject // it reads from it: // - sbmMavenProject.getBuild().getDirectory() @@ -186,7 +183,7 @@ private List parseMainSources(Path baseDir, SbmMavenProject sbmMaven */ private Set pathsToOtherMavenProjects(SbmMavenProject sbmMavenProject, Path moduleBuildFile) { return sbmMavenProject.getCollectedProjects().stream() - .filter(p -> !p.getFile().toPath().equals(moduleBuildFile)) + .filter(p -> !p.getFile().toPath().toString().equals(moduleBuildFile.toString())) .map(p -> p.getFile().toPath().getParent()) .collect(Collectors.toSet()); } diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/utils/ResourceUtil.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/utils/ResourceUtil.java index 562f40677..0cb16a1c2 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/utils/ResourceUtil.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/utils/ResourceUtil.java @@ -80,4 +80,12 @@ public static String getContent(Resource r) { throw new RuntimeException(e); } } + + public static long contentLength(Resource resource) { + try { + return resource.contentLength(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } } diff --git a/sbm-support-rewrite/src/test/java/org/springframework/sbm/ParserTest.java b/sbm-support-rewrite/src/test/java/org/springframework/sbm/ParserTest.java index 40c81b3b3..b3088f58a 100644 --- a/sbm-support-rewrite/src/test/java/org/springframework/sbm/ParserTest.java +++ b/sbm-support-rewrite/src/test/java/org/springframework/sbm/ParserTest.java @@ -20,6 +20,8 @@ import org.openrewrite.SourceFile; import org.openrewrite.maven.MavenParser; +import static org.assertj.core.api.Assertions.assertThat; + /** * @author Fabian Krüger */ @@ -75,7 +77,6 @@ void mavenParserShouldParsePom() { """).toList().get(0); - System.out.println(sourceFile.printAll()); - + assertThat(sourceFile).isNotNull(); } } diff --git a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteProjectParserIntegrationTest.java b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteProjectParserIntegrationTest.java index 565e33124..70bcd4abb 100644 --- a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteProjectParserIntegrationTest.java +++ b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteProjectParserIntegrationTest.java @@ -78,8 +78,8 @@ void parseResources() { Path baseDir = TestProjectHelper.getMavenProject("resources"); List resources = projectScanner.scan(baseDir); - RewriteProjectParsingResult parsingResult1 = mavenProjectParser.parse(baseDir); - assertThat(parsingResult1.sourceFiles()).hasSize(5); +// RewriteProjectParsingResult parsingResult1 = mavenProjectParser.parse(baseDir); +// assertThat(parsingResult1.sourceFiles()).hasSize(5); RewriteProjectParsingResult parsingResult = sut.parse(baseDir, resources, new InMemoryExecutionContext(t -> { throw new RuntimeException(t); From 7e1ba920ae205190d8d19ec43278215003349c4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Kr=C3=BCger?= Date: Thu, 28 Sep 2023 11:37:45 +0200 Subject: [PATCH 08/14] Build successful --- .../MavenMojoProjectParserPrivateMethods.java | 66 ++++++++++----- .../sbm/parsers/MavenProjectAnalyzer.java | 33 ++++++-- .../sbm/parsers/ParserContext.java | 53 ++++++++++++ .../sbm/parsers/ProvenanceMarkerFactory.java | 11 +-- .../sbm/parsers/RewriteProjectParser.java | 59 ++++--------- .../sbm/parsers/RewriteResourceParser.java | 22 +++-- .../sbm/parsers/SbmMavenProject.java | 41 ++++++++- .../sbm/parsers/SortedProjects.java | 83 ------------------- .../sbm/parsers/SourceFileParser.java | 27 +++--- .../maven/CalculateClasspathTest.java | 5 +- ...ParserEventPublicationIntegrationTest.java | 20 ++++- .../parsers/ProvenanceMarkerFactoryTest.java | 2 +- 12 files changed, 233 insertions(+), 189 deletions(-) create mode 100644 sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/ParserContext.java delete mode 100644 sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SortedProjects.java diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenMojoProjectParserPrivateMethods.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenMojoProjectParserPrivateMethods.java index e12f27f6f..133c96516 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenMojoProjectParserPrivateMethods.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenMojoProjectParserPrivateMethods.java @@ -63,16 +63,29 @@ class MavenMojoProjectParserPrivateMethods { /** * process sources in src/main/java of current module. */ - public List processMainSources(Path baseDir, List resources, Xml.Document moduleBuildFile, JavaParser.Builder javaParserBuilder, RewriteResourceParser rp, List provenanceMarkers, Set alreadyParsed, ExecutionContext executionContext, SbmMavenProject mavenProject) { - log.info("Processing main sources in module '%s'".formatted(mavenProject.getModuleDir())); + public List processMainSources( + Path baseDir, + List resources, + Xml.Document moduleBuildFile, + JavaParser.Builder javaParserBuilder, + RewriteResourceParser rp, + List provenanceMarkers, + Set alreadyParsed, + ExecutionContext executionContext, + SbmMavenProject currentProject + ) { + log.info("Processing main sources in module '%s'".formatted(currentProject.getModuleDir())); // FIXME: 945 -// Some annotation processors output generated sources to the /target directory. These are added for parsing but + // Some annotation processors output generated sources to the /target directory. These are added for parsing but // should be filtered out of the final SourceFile list. - List javaSourcesInTarget = listJavaSources(resources, mavenProject.getBasedir().resolve(mavenProject.getBuildDirectory())); - List javaSourcesInMain = listJavaSources(resources, mavenProject.getBasedir().resolve(mavenProject.getSourceDirectory())); - List mainJavaSources = Stream.concat(javaSourcesInTarget.stream(),javaSourcesInMain.stream()).toList(); - log.info("[%s] Parsing source files".formatted(mavenProject)); + List mainJavaSources = new ArrayList<>(); + List javaSourcesInTarget = currentProject.getJavaSourcesInTarget(); // listJavaSources(resources, currentProject.getBasedir().resolve(currentProject.getBuildDirectory())); + List javaSourcesInMain = currentProject.getMainJavaSources(); // listJavaSources(resources, currentProject.getBasedir().resolve(currentProject.getSourceDirectory())); + mainJavaSources.addAll(javaSourcesInTarget); + mainJavaSources.addAll(javaSourcesInMain); + + log.info("[%s] Parsing source files".formatted(currentProject)); // FIXME 945 classpath // - Resolve dependencies to non-reactor projects from Maven repository @@ -85,7 +98,7 @@ public List processMainSources(Path baseDir, List resource // Or, the classpath must be created from the sources of the project. - List dependencies = mavenProject.getCompileClasspathElements(); + List dependencies = currentProject.getCompileClasspathElements(); javaParserBuilder.classpath(dependencies); @@ -105,30 +118,43 @@ public List processMainSources(Path baseDir, List resource mainProjectProvenance.add(sourceSet("main", dependencies, typeCache)); // FIXME: 945 Why target and not all main? - List parsedJavaPaths = javaSourcesInTarget.stream().map(ResourceUtil::getPath).toList(); + List parsedJavaPaths = mainJavaSources.stream().map(ResourceUtil::getPath).toList(); Stream parsedJava = cus.map(addProvenance(baseDir, mainProjectProvenance, parsedJavaPaths)); - log.debug("[%s] Scanned %d java source files in main scope.".formatted(mavenProject, mainJavaSources.size())); + log.debug("[%s] Scanned %d java source files in main scope.".formatted(currentProject, mainJavaSources.size())); //Filter out any generated source files from the returned list, as we do not want to apply the recipe to the //generated files. - Path buildDirectory = baseDir.relativize(Paths.get(mavenProject.getBuildDirectory())); - Stream sourceFiles = parsedJava.filter(s -> !s.getSourcePath().startsWith(buildDirectory)); + Path buildDirectory = Paths.get(currentProject.getBuildDirectory()); + List sourceFiles = parsedJava + .filter(s -> !s.getSourcePath().startsWith(buildDirectory)) + .collect(Collectors.toCollection(ArrayList::new)); int sourcesParsedBefore = alreadyParsed.size(); - // FIXME: 945 alreadyParsed hack - Stream parsedResourceFiles = rp.parse(mavenProject.getBasedir().resolve("src/main/resources"), resources, alreadyParsed) - .map(addProvenance(baseDir, mainProjectProvenance, null)); + alreadyParsed.addAll(parsedJavaPaths); + List parsedResourceFiles = rp.parse(currentProject.getModulePath().resolve("src/main/resources"), resources, alreadyParsed) + .map(addProvenance(baseDir, mainProjectProvenance, null)) + .toList(); - log.debug("[%s] Scanned %d resource files in main scope.".formatted(mavenProject, (alreadyParsed.size() - sourcesParsedBefore))); + log.debug("[%s] Scanned %d resource files in main scope.".formatted(currentProject, (alreadyParsed.size() - sourcesParsedBefore))); // Any resources parsed from "main/resources" should also have the main source set added to them. - sourceFiles = Stream.concat(sourceFiles, parsedResourceFiles); - return sourceFiles.toList(); + sourceFiles.addAll(parsedResourceFiles); + return sourceFiles; } /** * Calls {@link MavenMojoProjectParser#processTestSources(SbmMavenProject, JavaParser.Builder, ResourceParser, List, Set, ExecutionContext)} */ - public List processTestSources(Path baseDir, Xml.Document moduleBuildFile, JavaParser.Builder javaParserBuilder, ResourceParser rp, List provenanceMarkers, Set alreadyParsed, ExecutionContext executionContext, SbmMavenProject mavenProject, List resources) { + public List processTestSources( + Path baseDir, + Xml.Document moduleBuildFile, + JavaParser.Builder javaParserBuilder, + RewriteResourceParser rp, + List provenanceMarkers, + Set alreadyParsed, + ExecutionContext executionContext, + SbmMavenProject mavenProject, + List resources + ) { List testDependencies = mavenProject.getTestClasspathElements(); javaParserBuilder.classpath(testDependencies); @@ -156,7 +182,7 @@ public List processTestSources(Path baseDir, Xml.Document moduleBuil // Any resources parsed from "test/resources" should also have the test source set added to them. int sourcesParsedBefore = alreadyParsed.size(); - Stream parsedResourceFiles = rp.parse(mavenProject.getBasedir().resolve("src/test/resources"), alreadyParsed) + Stream parsedResourceFiles = rp.parse(mavenProject.getBasedir().resolve("src/test/resources"), resources, alreadyParsed) .map(addProvenance(baseDir, markers, null)); log.debug("[%s] Scanned %d resource files in test scope.".formatted(mavenProject, (alreadyParsed.size() - sourcesParsedBefore))); sourceFiles = Stream.concat(sourceFiles, parsedResourceFiles); diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenProjectAnalyzer.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenProjectAnalyzer.java index fce2fc3dc..bf8da395a 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenProjectAnalyzer.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenProjectAnalyzer.java @@ -57,19 +57,24 @@ public List getSortedProjects(Path baseDir, List reso Model rootPomModel = new Model(rootPom); if (isSingleModuleProject(rootPomModel)) { - return List.of(new SbmMavenProject(baseDir, rootPom, rootPomModel, rewriteMavenArtifactDownloader)); + return List.of(new SbmMavenProject(baseDir, rootPom, rootPomModel, rewriteMavenArtifactDownloader, resources)); } List reactorModels = new ArrayList<>(); recursivelyFindReactorModules(baseDir, null, reactorModels, allPomFiles, rootPomModel); List sortedModels = sortModels(reactorModels); - return map(baseDir, sortedModels); + return map(baseDir, resources, sortedModels); } - private List map(Path baseDir, List sortedModels) { + private List map(Path baseDir, List resources, List sortedModels) { List sbmMavenProjects = new ArrayList<>(); - sortedModels.forEach(m -> { - sbmMavenProjects.add(new SbmMavenProject(baseDir, m.getResource(), m, rewriteMavenArtifactDownloader)); - }); + sortedModels + .stream() + .filter(Objects::nonNull) + .forEach(m -> { + String projectDir = baseDir.resolve(m.getProjectDirectory().toString()).normalize().toString(); + List filteredResources = resources.stream().filter(r -> ResourceUtil.getPath(r).toString().startsWith(projectDir)).toList(); + sbmMavenProjects.add(new SbmMavenProject(baseDir, m.getResource(), m, rewriteMavenArtifactDownloader, filteredResources)); + }); // set all non parent poms as collected projects for root parent pom List collected = new ArrayList<>(sbmMavenProjects); collected.remove(0); @@ -79,8 +84,11 @@ private List map(Path baseDir, List sortedModels) { private List recursivelyFindReactorModules(Path baseDir, String path, List reactorModels, List allPomFiles, Model pomModel) { // TODO: verify given module is root pom - - reactorModels.add(pomModel); + if(pomModel != null) { + reactorModels.add(pomModel); + } else { + throw new IllegalStateException("PomModel was null."); + } List moduleNames = pomModel.getModules(); @@ -179,6 +187,12 @@ private static boolean isSingleModuleProject(Model rootPomModel) { return !rootPomModel.getPackaging().equals("pom"); } + public ParserContext createParserContext(Path baseDir, List resources) { + List sortedProjectsList = getSortedProjects(baseDir, resources); + ParserContext parserContext = new ParserContext(resources, sortedProjectsList); + return parserContext; + } + static class Model extends org.apache.maven.model.Model { private final Resource resource; private final org.apache.maven.model.Model delegate; @@ -187,6 +201,7 @@ public Model(Resource resource) { this.resource = resource; try { this.delegate = XPP_3_READER.read(ResourceUtil.getInputStream(resource)); + this.delegate.setPomFile(resource.getFile()); } catch (IOException e) { throw new RuntimeException(e); } catch (XmlPullParserException e) { @@ -325,7 +340,7 @@ public File getPomFile() { @Override public File getProjectDirectory() { - return delegate.getProjectDirectory(); + return delegate.getPomFile().toPath().getParent().toFile(); } @Override diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/ParserContext.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/ParserContext.java new file mode 100644 index 000000000..6fa977e03 --- /dev/null +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/ParserContext.java @@ -0,0 +1,53 @@ +/* + * Copyright 2021 - 2023 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 + * + * https://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.sbm.parsers; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.springframework.core.io.Resource; +import org.springframework.sbm.utils.ResourceUtil; + +import java.util.List; + +/** + * @author Fabian Krüger + */ +@RequiredArgsConstructor +public class ParserContext { + + @Getter + private final List resources; + @Getter + private final List sortedProjects; + + public List getActiveProfiles() { + // FIXME: Add support for Maven profiles + return List.of("default"); + } + + public Resource getMatchingBuildFileResource(SbmMavenProject pom) { + return resources.stream() + .filter(r -> ResourceUtil.getPath(r).toString().equals(pom.getPomFilePath().toString())) + .findFirst() + .orElseThrow(() -> new IllegalStateException("Could not find a resource in the list of resources that matches the path of SbmMavenProject '%s'".formatted(pom.getPomFile().toString()))); + } + + public List getBuildFileResources() { + return sortedProjects.stream() + .map(p -> p.getPomFile()) + .toList(); + } +} diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/ProvenanceMarkerFactory.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/ProvenanceMarkerFactory.java index 74c026b52..e4e683244 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/ProvenanceMarkerFactory.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/ProvenanceMarkerFactory.java @@ -38,21 +38,18 @@ class ProvenanceMarkerFactory { /** * Reuses {@link MavenMojoProjectParser#generateProvenance(MavenProject)} to create {@link Marker}s for pom files in - * provided {@code pomFileResources}. + * provided {@code parserContext}. * * @return the map of pom.xml {@link Resource}s and their {@link Marker}s. */ - public Map> generateProvenanceMarkers(Path baseDir, SortedProjects pomFileResources) { - - RuntimeInformation runtimeInformation = new DefaultRuntimeInformation(); - SettingsDecrypter settingsDecrypter = null; + public Map> generateProvenanceMarkers(Path baseDir, ParserContext parserContext) { Map> result = new HashMap<>(); - pomFileResources.getSortedProjects().forEach(mavenProject -> { + parserContext.getSortedProjects().forEach(mavenProject -> { List markers = markerFactory.generateProvenance(baseDir, mavenProject); - Resource resource = pomFileResources.getMatchingBuildFileResource(mavenProject); + Resource resource = parserContext.getMatchingBuildFileResource(mavenProject); Path path = ResourceUtil.getPath(resource); result.put(path, markers); }); diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteProjectParser.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteProjectParser.java index 6001a094a..478205f73 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteProjectParser.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteProjectParser.java @@ -20,14 +20,12 @@ import org.apache.maven.execution.MavenSession; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; +import org.jetbrains.annotations.NotNull; import org.openrewrite.ExecutionContext; import org.openrewrite.SourceFile; import org.openrewrite.marker.Marker; import org.openrewrite.maven.AbstractRewriteMojo; -import org.openrewrite.maven.MavenDownloadingExceptions; import org.openrewrite.maven.MavenExecutionContextView; -import org.openrewrite.maven.MavenMojoProjectParser; -import org.openrewrite.maven.internal.MavenPomDownloader; import org.openrewrite.maven.tree.*; import org.openrewrite.style.NamedStyles; import org.openrewrite.tree.ParsingEventListener; @@ -45,7 +43,6 @@ import java.lang.reflect.Method; import java.nio.file.Path; import java.util.*; -import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -94,7 +91,6 @@ public class RewriteProjectParser { public RewriteProjectParsingResult parse(Path baseDir) { - Set ignorePatterns = parserProperties.getIgnoredPathPatterns(); List resources = scanner.scan(baseDir); return this.parse(baseDir, resources, executionContext); } @@ -116,16 +112,11 @@ public RewriteProjectParsingResult parse(Path baseDir) { * Parse resources * processMainSources() * processTestSources() - * - * @see MavenMojoProjectParser#listSourceFiles(SbmMavenProject, List, ExecutionContext) */ public RewriteProjectParsingResult parse(Path givenBaseDir, List resources, ExecutionContext executionContext) { scanScope.clear(beanFactory); - if (!givenBaseDir.isAbsolute()) { - givenBaseDir = givenBaseDir.toAbsolutePath().normalize(); - } - final Path baseDir = givenBaseDir; + final Path baseDir = normalizePath(givenBaseDir); // FIXME: ... WARN 30694 --- [ main] .m.p.i.DeprecatedCoreExpressionValidator : Parameter 'local' is deprecated core expression; Avoid use of ArtifactRepository type. If you need access to local repository, switch to '${repositorySystemSession}' expression and get LRM from it instead. MavenExecutionContextView.view(executionContext).setLocalRepository(new MavenRepository("local", "file://" + Path.of(System.getProperty("user.home")).resolve(".m2/repository"), null, null, false, null, null, null)); @@ -138,53 +129,28 @@ public RewriteProjectParsingResult parse(Path givenBaseDir, List resou // TODO: where to retrieve styles from? --> see AbstractRewriteMojo#getActiveStyles() & AbstractRewriteMojo#loadStyles() List styles = List.of(); -// AtomicReference atomicReference = new AtomicReference<>(); - -// withMavenSession(baseDir, mavenSession -> { // Get the ordered list of projects - // TODO: #945 - replace with custom sorter - // TODO: #945 Replace SbmMavenProject -// mavenSession.getProjectDependencyGraph().getSortedProjects(); - List sortedProjectsList = mavenProjectAnalyzer.getSortedProjects(baseDir, resources); + ParserContext parserContext = mavenProjectAnalyzer.createParserContext(baseDir, resources); // SortedProjects makes downstream components independent of Maven classes // TODO: 945 Is SortedProjects still required? - SortedProjects mavenInfos = new SortedProjects(resources, sortedProjectsList, List.of("default")); - // List sortedBuildFileResources = buildFileParser.filterAndSortBuildFiles(resources); // generate provenance - Map> provenanceMarkers = provenanceMarkerFactory.generateProvenanceMarkers(baseDir, mavenInfos); + Map> provenanceMarkers = provenanceMarkerFactory.generateProvenanceMarkers(baseDir, parserContext); // 127: parse build files - Map resourceToDocumentMap = buildFileParser.parseBuildFiles(baseDir, mavenInfos.getResources(), mavenInfos.getActiveProfiles(), executionContext, parserProperties.isSkipMavenParsing(), provenanceMarkers); + Map resourceToDocumentMap = buildFileParser.parseBuildFiles(baseDir, parserContext.getBuildFileResources(), parserContext.getActiveProfiles(), executionContext, parserProperties.isSkipMavenParsing(), provenanceMarkers); - List parsedAndSortedBuildFileDocuments = mavenInfos.getResources().stream() + List parsedAndSortedBuildFileDocuments = parserContext.getBuildFileResources().stream() .map(r -> resourceToDocumentMap.get(ResourceUtil.getPath(r))) .map(SourceFile.class::cast) // FIXME: 945 ugly hack - .peek(sourceFile -> addSourceFileToModel(baseDir, sortedProjectsList, sourceFile)) + .peek(sourceFile -> addSourceFileToModel(baseDir, parserContext.getSortedProjects(), sourceFile)) .toList(); - // FIXME: 945 - classpath required - Map projectPoms = resourceToDocumentMap.entrySet().stream() - .collect(Collectors.toMap( - k -> k.getKey(), - k -> k.getValue().getMarkers().findFirst(MavenResolutionResult.class).get().getPom().getRequested() - )); -// List resolvedDependencies = parsedAndSortedBuildFileDocuments.get(0).getMarkers().findFirst(MavenResolutionResult.class).get().getPom().resolveDependencies(Scope.Compile, new MavenPomDownloader(projectPoms, executionContext), executionContext); - - // Remove parsed files form resources - // TODO: 954 trying to fix already parsed first and then replace it -// Set pomPaths = parsedAndSortedBuildFileDocuments.stream().map(s -> baseDir.resolve(s.getSourcePath()).normalize().toString()).collect(Collectors.toSet()); -// Map pathToResource = resourcesLeft.stream().collect(Collectors.toMap( -// r -> ResourceUtil.getPath(r).toString(), -// r -> r -// )); -// pomPaths.forEach(p -> resourcesLeft.remove(resourcesLeft.indexOf(pathToResource.get(p)))); - log.trace("Start to parse %d source files in %d modules".formatted(resources.size() + resourceToDocumentMap.size(), resourceToDocumentMap.size())); - List list = sourceFileParser.parseOtherSourceFiles(baseDir, mavenInfos, resourceToDocumentMap, resources, provenanceMarkers, styles, executionContext); + List list = sourceFileParser.parseOtherSourceFiles(baseDir, parserContext, resourceToDocumentMap, resources, provenanceMarkers, styles, executionContext); // List sourceFilesWithoutPoms = sourceFilesStream.filter(sf -> resourceToDocumentMap.keySet().contains(baseDir.resolve(sf.getSourcePath()).toAbsolutePath().normalize())).toList(); List resultingList = new ArrayList<>(); // sourceFilesStream2.toList(); @@ -199,6 +165,15 @@ public RewriteProjectParsingResult parse(Path givenBaseDir, List resou } + @NotNull + private static Path normalizePath(Path givenBaseDir) { + if (!givenBaseDir.isAbsolute()) { + givenBaseDir = givenBaseDir.toAbsolutePath().normalize(); + } + final Path baseDir = givenBaseDir; + return baseDir; + } + private static void addSourceFileToModel(Path baseDir, List sortedProjectsList, SourceFile s) { sortedProjectsList.stream() .filter(p -> ResourceUtil.getPath(p.getPomFile()).toString().equals(baseDir.resolve(s.getSourcePath()).toString())) diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteResourceParser.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteResourceParser.java index 26bd0e858..ec24f6887 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteResourceParser.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteResourceParser.java @@ -80,10 +80,11 @@ private Collection pathMatchers(Path basePath, Collection p } public Stream parse(Path searchDir, List resources, Set alreadyParsed) { + // TODO: 945 remove/clean this up List resourcesLeft = resources.stream() .filter(r -> alreadyParsed.stream().noneMatch(path -> ResourceUtil.getPath(r).toString().startsWith(path.toString()))) .toList(); - return this.parseSourceFiles(baseDir, resourcesLeft, alreadyParsed, executionContext); + return this.parseSourceFiles(searchDir, resourcesLeft, alreadyParsed, executionContext); // @@ -117,7 +118,12 @@ public Stream parseSourceFiles( List quarkPaths = new ArrayList<>(); List plainTextPaths = new ArrayList<>(); - resources.forEach(resource -> { + List filteredResources = resources + .stream() + .filter(r -> ResourceUtil.getPath(r).toString().startsWith(searchDir.toString())) + .toList(); + + filteredResources.forEach(resource -> { Path file = ResourceUtil.getPath(resource); Path dir = file.getParent(); if (isExcluded(dir) || isIgnoredDirectory(searchDir, dir) || excludedDirectories.contains(dir) || alreadyParsed.contains(new FileSystemResource(dir)) || alreadyParsed.contains(resource)) { @@ -167,13 +173,15 @@ public Stream parseSourceFiles( QuarkParser quarkParser = new QuarkParser(); - resources.forEach(resource -> { + filteredResources + .forEach(resource -> { // See https://github.com/quarkusio/quarkus/blob/main/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/extension-codestarts/resteasy-reactive-codestart/java/src/main/java/org/acme/%7Bresource.class-name%7D.tpl.qute.java // for an example of why we don't want qute files be parsed as java Path path = ResourceUtil.getPath(resource); - if (javaParser.accept(path) && !path.toString().endsWith(".qute.java")) { - javaPaths.add(path); - } else if (jsonParser.accept(path)) { +// if (javaParser.accept(path) && !path.toString().endsWith(".qute.java")) { +// javaPaths.add(path); +// } + if (jsonParser.accept(path)) { jsonPaths.add(path); } else if (xmlParser.accept(path)) { xmlPaths.add(path); @@ -192,7 +200,7 @@ public Stream parseSourceFiles( } }); - Map pathToResource = resources.stream().collect(Collectors.toMap(r -> ResourceUtil.getPath(r), r -> r)); + Map pathToResource = filteredResources.stream().collect(Collectors.toMap(r -> ResourceUtil.getPath(r), r -> r)); if (!javaPaths.isEmpty()) { List inputs = getInputs(pathToResource, javaPaths); diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SbmMavenProject.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SbmMavenProject.java index ccc3d4b4c..860929c4a 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SbmMavenProject.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SbmMavenProject.java @@ -29,7 +29,7 @@ import java.io.File; import java.nio.file.Path; import java.util.*; -import java.util.stream.Collectors; +import java.util.function.Predicate; @Getter @@ -46,12 +46,14 @@ public class SbmMavenProject { private List collectedProjects = new ArrayList<>(); private SourceFile sourceFile; private final MavenArtifactDownloader rewriteMavenArtifactDownloader; + private final List resources; - public SbmMavenProject(Path projectRoot, Resource pomFile, Model pomModel, MavenArtifactDownloader rewriteMavenArtifactDownloader) { + public SbmMavenProject(Path projectRoot, Resource pomFile, Model pomModel, MavenArtifactDownloader rewriteMavenArtifactDownloader, List resources) { this.projectRoot = projectRoot; this.pomFile = pomFile; this.pomModel = pomModel; this.rewriteMavenArtifactDownloader = rewriteMavenArtifactDownloader; + this.resources = resources; } public File getFile() { @@ -59,6 +61,7 @@ public File getFile() { } public Path getBasedir() { + // TODO: 945 Check if this is correct return pomFile == null ? null : ResourceUtil.getPath(pomFile).getParent(); } @@ -174,4 +177,38 @@ public String getTestSourceDirectory() { public void setSourceFile(SourceFile sourceFile) { this.sourceFile = sourceFile; } + + private static List listJavaSources(List resources, Path sourceDirectory) { + return resources.stream() + .filter(whenIn(sourceDirectory)) + .filter(whenFileNameEndsWithJava()) + .toList(); + } + + @NotNull + private static Predicate whenFileNameEndsWithJava() { + return p -> ResourceUtil.getPath(p).getFileName().toString().endsWith(".java"); + } + + @NotNull + private static Predicate whenIn(Path sourceDirectory) { + return r -> ResourceUtil.getPath(r).toString().startsWith(sourceDirectory.toString()); + } + + + public List getJavaSourcesInTarget() { + return listJavaSources(getResources(), getBasedir().resolve(getBuildDirectory())); + } + + private List getResources() { + return this.resources; + } + + public List getMainJavaSources() { + return listJavaSources(resources, getProjectRoot().resolve(getModuleDir()).resolve("src/main/java")); + } + + public Path getModulePath() { + return projectRoot.resolve(getModuleDir()); + } } diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SortedProjects.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SortedProjects.java deleted file mode 100644 index df76817c0..000000000 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SortedProjects.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2021 - 2023 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 - * - * https://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.sbm.parsers; - -import lombok.Getter; -import org.apache.maven.model.Model; -import org.springframework.core.io.Resource; -import org.springframework.sbm.utils.ResourceUtil; - -import java.nio.file.Path; -import java.util.List; - -/** - * Helper class - * - * TODO: Make class independant to Maven and find better name. - * TODO: Can this class be used to transport build information from Maven and Gradle to reuse functionality? - * - * @author Fabian Krüger - */ -public class SortedProjects { - private final List resources; - @Getter - private final List sortedProjects; - @Getter - private final List activeProfiles; - - - - // FIXME: The relation between resource and project is brittle, if it's really needed we should validate in constructor - public SortedProjects(List given, List allProjects, List activeProfiles) { - this.resources = given; - this.sortedProjects = allProjects; - this.activeProfiles = activeProfiles; - } - - public List getResources() { - return sortedProjects - .stream() - .map(SbmMavenProject::getPomFilePath) - .map(m -> this.findResourceWithPath(m, resources)) - .toList(); - } - - private Resource findResourceWithPath(Path m, List resources) { - return resources.stream() - .filter(r -> ResourceUtil.getPath(r).equals(m)) - .findFirst() - .orElseThrow(() -> new IllegalStateException("Could not find a resource in the list of resources that matches the path of pom '%s'".formatted(m.toString()))); - } - - public Resource getMatchingBuildFileResource(SbmMavenProject pom) { - return resources.stream() - .filter(r -> ResourceUtil.getPath(r).toString().equals(pom.getPomFilePath().toString())) - .findFirst() - .orElseThrow(() -> new IllegalStateException("Could not find a resource in the list of resources that matches the path of SbmMavenProject '%s'".formatted(pom.getPomFile().toString()))); - } - - private List readActiveProfiles(Model topLevelModel) { - return activeProfiles; - } - - public SbmMavenProject getMavenProject(Resource r) { - Path path = ResourceUtil.getPath(r); - return sortedProjects.stream() - .filter(p -> p.getFile().getPath().toString().equals(path.toString())) - .findFirst() - .orElseThrow(() -> new IllegalArgumentException("Could not find SbmMavenProject for given resource '%s'".formatted(path))); - } -} diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SourceFileParser.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SourceFileParser.java index 056b93272..cbe6f3f17 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SourceFileParser.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SourceFileParser.java @@ -24,7 +24,6 @@ import org.openrewrite.maven.ResourceParser; import org.openrewrite.style.NamedStyles; import org.openrewrite.xml.tree.Xml; -import org.springframework.core.io.FileSystemResource; import org.springframework.core.io.Resource; import org.springframework.sbm.utils.ResourceUtil; @@ -48,7 +47,7 @@ public class SourceFileParser { public List parseOtherSourceFiles( Path baseDir, - SortedProjects mavenProject, + ParserContext parserContext, Map pathToDocumentMap, List resources, Map> provenanceMarkers, @@ -57,14 +56,14 @@ public List parseOtherSourceFiles( Set parsedSourceFiles = new LinkedHashSet<>(); - mavenProject.getSortedProjects().forEach(currentMavenProject -> { - Resource moduleBuildFileResource = mavenProject.getMatchingBuildFileResource(currentMavenProject); + parserContext.getSortedProjects().forEach(currentMavenProject -> { + Resource moduleBuildFileResource = parserContext.getMatchingBuildFileResource(currentMavenProject); Xml.Document moduleBuildFile = pathToDocumentMap.get(ResourceUtil.getPath(moduleBuildFileResource)); List markers = provenanceMarkers.get(ResourceUtil.getPath(moduleBuildFileResource)); if(markers == null || markers.isEmpty()) { - log.warn("Could not find provenance markers for resource '%s'".formatted(mavenProject.getMatchingBuildFileResource(currentMavenProject))); + log.warn("Could not find provenance markers for resource '%s'".formatted(parserContext.getMatchingBuildFileResource(currentMavenProject))); } - List sourceFiles = parseModuleSourceFiles(resources, mavenProject, mavenProject.getSortedProjects().get(0), moduleBuildFile, markers, styles, executionContext, baseDir); + List sourceFiles = parseModuleSourceFiles(resources, parserContext, currentMavenProject, moduleBuildFile, markers, styles, executionContext, baseDir); parsedSourceFiles.addAll(sourceFiles); }); @@ -76,14 +75,15 @@ public List parseOtherSourceFiles( */ private List parseModuleSourceFiles( List resources, - SortedProjects mavenProject, - SbmMavenProject sbmMavenProject, + ParserContext parserContext, + SbmMavenProject currentProject, Xml.Document moduleBuildFile, List provenanceMarkers, List styles, ExecutionContext executionContext, Path baseDir) { + List sourceFiles = new ArrayList<>(); // 146:149: get source encoding from maven // TDOD: @@ -97,9 +97,10 @@ private List parseModuleSourceFiles( .styles(styles) .logCompilationWarningsAndErrors(false); - Path buildFilePath = sbmMavenProject.getBasedir().resolve(moduleBuildFile.getSourcePath()); + Path buildFilePath = currentProject.getBasedir().resolve(moduleBuildFile.getSourcePath()); + log.info("Parsing module " + buildFilePath); // these paths will be ignored by ResourceParser - Set skipResourceScanDirs = pathsToOtherMavenProjects(sbmMavenProject, buildFilePath); + Set skipResourceScanDirs = pathsToOtherMavenProjects(currentProject, buildFilePath); // FIXME: Why is skipResourceScanDirs required at all? Shouldn't the module know it's resources RewriteResourceParser rp = new RewriteResourceParser( baseDir, @@ -116,8 +117,8 @@ private List parseModuleSourceFiles( Path moduleBuildFilePath = baseDir.resolve(moduleBuildFile.getSourcePath()); alreadyParsed.add(moduleBuildFilePath); alreadyParsed.addAll(skipResourceScanDirs); - List mainSources = parseMainSources(baseDir, sbmMavenProject, moduleBuildFile, resources, javaParserBuilder.clone(), rp, provenanceMarkers, alreadyParsed, executionContext); - List testSources = parseTestSources(baseDir, sbmMavenProject, moduleBuildFile, javaParserBuilder.clone(), rp, provenanceMarkers, alreadyParsed, executionContext, resources); + List mainSources = parseMainSources(baseDir, currentProject, moduleBuildFile, resources, javaParserBuilder.clone(), rp, provenanceMarkers, alreadyParsed, executionContext); + List testSources = parseTestSources(baseDir, currentProject, moduleBuildFile, javaParserBuilder.clone(), rp, provenanceMarkers, alreadyParsed, executionContext, resources); // Collect the dirs of modules parsed in previous steps // parse other project resources @@ -151,7 +152,7 @@ private static boolean isNotExcluded(Path baseDir, List exclusions, .noneMatch(pm -> pm.matches(baseDir.resolve(s.getSourcePath()).toAbsolutePath().normalize())); } - private List parseTestSources(Path baseDir, SbmMavenProject sbmMavenProject, Xml.Document moduleBuildFile, JavaParser.Builder javaParserBuilder, ResourceParser rp, List provenanceMarkers, Set alreadyParsed, ExecutionContext executionContext, List resources) { + private List parseTestSources(Path baseDir, SbmMavenProject sbmMavenProject, Xml.Document moduleBuildFile, JavaParser.Builder javaParserBuilder, RewriteResourceParser rp, List provenanceMarkers, Set alreadyParsed, ExecutionContext executionContext, List resources) { return mavenMojoProjectParserPrivateMethods.processTestSources(baseDir, moduleBuildFile, javaParserBuilder, rp, provenanceMarkers, alreadyParsed, executionContext, sbmMavenProject, resources); } diff --git a/sbm-support-rewrite/src/test/java/org/openrewrite/maven/CalculateClasspathTest.java b/sbm-support-rewrite/src/test/java/org/openrewrite/maven/CalculateClasspathTest.java index e369d5589..da183ff5f 100644 --- a/sbm-support-rewrite/src/test/java/org/openrewrite/maven/CalculateClasspathTest.java +++ b/sbm-support-rewrite/src/test/java/org/openrewrite/maven/CalculateClasspathTest.java @@ -18,6 +18,7 @@ import org.intellij.lang.annotations.Language; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; import org.openrewrite.SourceFile; import org.openrewrite.java.marker.JavaSourceSet; import org.openrewrite.java.tree.J; @@ -48,7 +49,7 @@ public class CalculateClasspathTest { @Test @DisplayName("classpath for single-module project") - void classpathForSingleModuleProject() { + void classpathForSingleModuleProject(@TempDir Path tmpDir) { @Language("xml") String pom = """ @@ -100,7 +101,7 @@ void someTest() {} } """; - Path baseDir = Path.of("./target/example-1").toAbsolutePath().normalize(); + Path baseDir = tmpDir.resolve("/example-1").toAbsolutePath().normalize(); List resources = List.of( new DummyResource(baseDir.resolve("pom.xml"), pom), new DummyResource(baseDir.resolve("src/main/java/com/example/MainClass.java"), mainClass), diff --git a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/ParserEventPublicationIntegrationTest.java b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/ParserEventPublicationIntegrationTest.java index a4b7762fe..3e605cbdf 100644 --- a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/ParserEventPublicationIntegrationTest.java +++ b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/ParserEventPublicationIntegrationTest.java @@ -51,6 +51,9 @@ public class ParserEventPublicationIntegrationTest { @Autowired ParserProperties parserProperties; + @Autowired + ExecutionContext executionContext; + private static List capturedEvents = new ArrayList<>(); private static StartedParsingProjectEvent startedParsingEvent; private static SuccessfullyParsedProjectEvent finishedParsingEvent; @@ -61,11 +64,20 @@ void shouldPublishParsingEvents() { Path baseDir = Path.of("./testcode/maven-projects/multi-module-events"); parserProperties.setIgnoredPathPatterns(Set.of("{**/target/**,target/**}", "**.adoc")); List resources = projectScanner.scan(baseDir); - ExecutionContext ctx = new InMemoryExecutionContext(t -> {throw new RuntimeException(t);}); - RewriteProjectParsingResult parsingResult = sut.parse(baseDir, resources, ctx); + RewriteProjectParsingResult parsingResult = sut.parse(baseDir, resources, executionContext); + + assertThat(parsingResult.sourceFiles()).hasSize(5); + assertThat(parsingResult.sourceFiles().stream().map(s -> s.getSourcePath().toString()).toList()) + .containsExactly( + "pom.xml", + "module-b/pom.xml", + "module-a/pom.xml", + "module-b/src/test/resources/application.yaml", + "module-a/src/main/java/com/acme/SomeClass.java" + ); -// assertThat(capturedEvents).hasSize(5); + assertThat(capturedEvents).hasSize(5); assertThat(capturedEvents.get(0).sourceFile().getSourcePath().toString()) .isEqualTo("pom.xml"); @@ -74,6 +86,8 @@ void shouldPublishParsingEvents() { assertThat(capturedEvents.get(2).sourceFile().getSourcePath().toString()) .isEqualTo("module-a/pom.xml"); assertThat(capturedEvents.get(3).sourceFile().getSourcePath().toString()) + .isEqualTo("module-b/src/test/resources/application.yaml"); + assertThat(capturedEvents.get(4).sourceFile().getSourcePath().toString()) .isEqualTo("module-a/src/main/java/com/acme/SomeClass.java"); // ResourceParser not firing events // TODO: reactivate after https://github.com/openrewrite/rewrite-maven-plugin/issues/622 diff --git a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/ProvenanceMarkerFactoryTest.java b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/ProvenanceMarkerFactoryTest.java index 8bc2920d3..56a2e74d0 100644 --- a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/ProvenanceMarkerFactoryTest.java +++ b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/ProvenanceMarkerFactoryTest.java @@ -170,7 +170,7 @@ void shouldCreateProvenanceMarkers(@TempDir Path tempDir) { when(parserFactory.create(isA(Path.class), isA(DefaultRuntimeInformation.class), isNull())).thenReturn(mojoProjectParser); - SortedProjects sortedProjects = mock(SortedProjects.class); + ParserContext sortedProjects = mock(ParserContext.class); SbmMavenProject sbmMavenProject1 = mock(SbmMavenProject.class); SbmMavenProject sbmMavenProject2 = mock(SbmMavenProject.class); List sbmMavenProjects = List.of( From ccf41ed45e002d46c692ef0d7618466fbd13a205 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Kr=C3=BCger?= Date: Thu, 28 Sep 2023 11:55:12 +0200 Subject: [PATCH 09/14] Add ProjectId for Maven projects --- .../MavenMojoProjectParserPrivateMethods.java | 16 +++---- .../sbm/parsers/ProjectId.java | 42 +++++++++++++++++++ .../sbm/parsers/SbmMavenProject.java | 6 +++ 3 files changed, 57 insertions(+), 7 deletions(-) create mode 100644 sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/ProjectId.java diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenMojoProjectParserPrivateMethods.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenMojoProjectParserPrivateMethods.java index 133c96516..aee9a7e4b 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenMojoProjectParserPrivateMethods.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenMojoProjectParserPrivateMethods.java @@ -74,7 +74,7 @@ public List processMainSources( ExecutionContext executionContext, SbmMavenProject currentProject ) { - log.info("Processing main sources in module '%s'".formatted(currentProject.getModuleDir())); + log.info("Processing main sources in module '%s'".formatted(currentProject.getProjectId())); // FIXME: 945 // Some annotation processors output generated sources to the /target directory. These are added for parsing but // should be filtered out of the final SourceFile list. @@ -152,16 +152,18 @@ public List processTestSources( List provenanceMarkers, Set alreadyParsed, ExecutionContext executionContext, - SbmMavenProject mavenProject, + SbmMavenProject currentProject, List resources ) { - List testDependencies = mavenProject.getTestClasspathElements(); + log.info("Processing test sources in module '%s'".formatted(currentProject.getProjectId())); + + List testDependencies = currentProject.getTestClasspathElements(); javaParserBuilder.classpath(testDependencies); JavaTypeCache typeCache = new JavaTypeCache(); javaParserBuilder.typeCache(typeCache); - List testJavaSources = listJavaSources(resources, mavenProject.getBasedir().resolve(mavenProject.getTestSourceDirectory())); + List testJavaSources = listJavaSources(resources, currentProject.getBasedir().resolve(currentProject.getTestSourceDirectory())); alreadyParsed.addAll(testJavaSources.stream().map(ResourceUtil::getPath).toList()); Iterable inputs = testJavaSources.stream() @@ -177,14 +179,14 @@ public List processTestSources( Stream parsedJava = cus.map(addProvenance(baseDir, markers, null)); - log.debug("[%s] Scanned %d java source files in test scope.".formatted(mavenProject, testJavaSources.size())); + log.debug("[%s] Scanned %d java source files in test scope.".formatted(currentProject, testJavaSources.size())); Stream sourceFiles = parsedJava; // Any resources parsed from "test/resources" should also have the test source set added to them. int sourcesParsedBefore = alreadyParsed.size(); - Stream parsedResourceFiles = rp.parse(mavenProject.getBasedir().resolve("src/test/resources"), resources, alreadyParsed) + Stream parsedResourceFiles = rp.parse(currentProject.getBasedir().resolve("src/test/resources"), resources, alreadyParsed) .map(addProvenance(baseDir, markers, null)); - log.debug("[%s] Scanned %d resource files in test scope.".formatted(mavenProject, (alreadyParsed.size() - sourcesParsedBefore))); + log.debug("[%s] Scanned %d resource files in test scope.".formatted(currentProject, (alreadyParsed.size() - sourcesParsedBefore))); sourceFiles = Stream.concat(sourceFiles, parsedResourceFiles); List result = sourceFiles.toList(); return result; diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/ProjectId.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/ProjectId.java new file mode 100644 index 000000000..7ecce0a2b --- /dev/null +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/ProjectId.java @@ -0,0 +1,42 @@ +/* + * Copyright 2021 - 2023 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 + * + * https://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.sbm.parsers; + +import java.util.Objects; + +/** + * @author Fabian Krüger + */ +public record ProjectId(String groupId, String artifactId) { + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ProjectId projectId = (ProjectId) o; + return Objects.equals(groupId, projectId.groupId) && Objects.equals(artifactId, projectId.artifactId); + } + + @Override + public int hashCode() { + return Objects.hash(groupId, artifactId); + } + + @Override + public String toString() { + return groupId + ":" + artifactId; + } +} diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SbmMavenProject.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SbmMavenProject.java index 860929c4a..0debaebb9 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SbmMavenProject.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SbmMavenProject.java @@ -47,6 +47,7 @@ public class SbmMavenProject { private SourceFile sourceFile; private final MavenArtifactDownloader rewriteMavenArtifactDownloader; private final List resources; + private ProjectId projectId; public SbmMavenProject(Path projectRoot, Resource pomFile, Model pomModel, MavenArtifactDownloader rewriteMavenArtifactDownloader, List resources) { this.projectRoot = projectRoot; @@ -54,6 +55,7 @@ public SbmMavenProject(Path projectRoot, Resource pomFile, Model pomModel, Maven this.pomModel = pomModel; this.rewriteMavenArtifactDownloader = rewriteMavenArtifactDownloader; this.resources = resources; + projectId = new ProjectId(getGroupId(), getArtifactId()); } public File getFile() { @@ -211,4 +213,8 @@ public List getMainJavaSources() { public Path getModulePath() { return projectRoot.resolve(getModuleDir()); } + + public ProjectId getProjectId() { + return projectId; + } } From 0952a8bef98d44f39eacd4b65272f6a39dfbf361 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Kr=C3=BCger?= Date: Thu, 28 Sep 2023 12:10:09 +0200 Subject: [PATCH 10/14] Remove broken import --- .../springframework/sbm/java/impl/DependencyChangeHandler.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/components/sbm-core/src/main/java/org/springframework/sbm/java/impl/DependencyChangeHandler.java b/components/sbm-core/src/main/java/org/springframework/sbm/java/impl/DependencyChangeHandler.java index 5c6dae61a..d676a9891 100644 --- a/components/sbm-core/src/main/java/org/springframework/sbm/java/impl/DependencyChangeHandler.java +++ b/components/sbm-core/src/main/java/org/springframework/sbm/java/impl/DependencyChangeHandler.java @@ -35,7 +35,6 @@ import org.springframework.sbm.engine.context.ProjectContextHolder; import org.springframework.sbm.java.api.JavaSource; import org.springframework.sbm.parsers.JavaParserBuilder; -import org.springframework.sbm.parsers.SortedProjects; import org.springframework.sbm.parsers.SourceFileParser; import org.springframework.sbm.utils.JavaHelper; import org.springframework.stereotype.Component; @@ -43,7 +42,6 @@ import java.io.ByteArrayInputStream; import java.nio.file.Path; import java.util.*; -import java.util.stream.Stream; /** * @author Fabian Krüger From 7b57a5050743842c2b33cd33f12fd4c74cf2354c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Kr=C3=BCger?= Date: Thu, 28 Sep 2023 14:56:06 +0200 Subject: [PATCH 11/14] Decoupled main from non-required Maven deps * Moved all Maven related classes not required by RewriteProjectParser to test * Set Maven dependencies to test scope where possible --- sbm-support-rewrite/pom.xml | 158 +++++-------- .../sbm/parsers/BuildFileParser.java | 6 - ...thods.java => HelperWithoutAGoodName.java} | 114 +++------- .../sbm/parsers/MavenConfigFileParser.java | 1 - .../sbm/parsers/MavenParserConfiguration.java | 46 ---- .../sbm/parsers/ProvenanceMarkerFactory.java | 5 - .../parsers/RewriteParserConfiguration.java | 67 +++--- .../sbm/parsers/RewriteProjectParser.java | 34 --- .../sbm/parsers/RewriteResourceParser.java | 42 ++-- .../sbm/parsers/SourceFileParser.java | 11 +- .../sbm/parsers/StyleDetector.java | 66 ++++-- .../sbm/recipes/RewriteRecipeDiscovery.java | 209 +++++++++--------- .../sbm/parsers/BuildFileParserTest.java | 3 +- .../parsers/MavenExecutionRequestFactory.java | 1 + .../MavenExecutionResultException.java | 0 .../sbm/parsers/MavenExecutor.java | 0 .../MavenMojoProjectParserFactory.java | 0 .../MavenMojoProjectParserPrivateMethods.java | 64 ++++++ .../sbm/parsers/MavenPlexusContainer.java | 0 .../parsers/RewriteMavenProjectParser.java | 0 ...riteMavenProjectParserIntegrationTest.java | 3 +- .../RewriteMavenProjectParserTest.java | 5 +- .../RewriteProjectParserIntegrationTest.java | 4 +- .../sbm/parsers/RewriteProjectParserTest.java | 5 +- .../sbm/parsers/SbmTestConfiguration.java | 90 ++++++++ .../parsers/Slf4jToMavenLoggerAdapter.java | 0 26 files changed, 459 insertions(+), 475 deletions(-) rename sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/{MavenMojoProjectParserPrivateMethods.java => HelperWithoutAGoodName.java} (84%) delete mode 100644 sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenParserConfiguration.java rename sbm-support-rewrite/src/{main => test}/java/org/springframework/sbm/parsers/MavenExecutionRequestFactory.java (98%) rename sbm-support-rewrite/src/{main => test}/java/org/springframework/sbm/parsers/MavenExecutionResultException.java (100%) rename sbm-support-rewrite/src/{main => test}/java/org/springframework/sbm/parsers/MavenExecutor.java (100%) rename sbm-support-rewrite/src/{main => test}/java/org/springframework/sbm/parsers/MavenMojoProjectParserFactory.java (100%) create mode 100644 sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/MavenMojoProjectParserPrivateMethods.java rename sbm-support-rewrite/src/{main => test}/java/org/springframework/sbm/parsers/MavenPlexusContainer.java (100%) rename sbm-support-rewrite/src/{main => test}/java/org/springframework/sbm/parsers/RewriteMavenProjectParser.java (100%) create mode 100644 sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/SbmTestConfiguration.java rename sbm-support-rewrite/src/{main => test}/java/org/springframework/sbm/parsers/Slf4jToMavenLoggerAdapter.java (100%) diff --git a/sbm-support-rewrite/pom.xml b/sbm-support-rewrite/pom.xml index c34d8072b..47d1535fb 100644 --- a/sbm-support-rewrite/pom.xml +++ b/sbm-support-rewrite/pom.xml @@ -142,60 +142,71 @@ ${rewrite.version} - org.openrewrite.maven - rewrite-maven-plugin - ${rewrite-maven-plugin.version} + org.openrewrite + rewrite-properties + ${rewrite.version} org.projectlombok lombok provided + + org.apache.maven + maven-model + 3.9.1 + + + + org.openrewrite.maven + rewrite-maven-plugin + ${rewrite-maven-plugin.version} + test + org.apache.maven.wagon wagon-http ${maven-wagon-http.version} + test org.apache.maven.resolver maven-resolver-transport-wagon ${maven-resolver.version} + test org.apache.maven.resolver maven-resolver-connector-basic ${maven-resolver.version} + test org.apache.maven.resolver maven-resolver-impl ${maven-resolver.version} + test org.apache.maven maven-resolver-provider ${maven.version} + test org.apache.maven maven-compat ${maven.version} + test - - org.apache.maven - maven-embedder - ${maven.version} - - - org.sonatype.plexus - plexus-cipher - - - + + + org.codehaus.plexus plexus-cipher ${plexus-cypher.version} + test org.apache.maven.shared @@ -207,6 +218,7 @@ javax.xml.bind jaxb-api ${jaxb-api.version} + test org.springframework.boot @@ -219,6 +231,31 @@ ${junit-pioneer.version} test + + + + + org.codehaus.plexus + plexus-sec-dispatcher + 2.0 + + + + org.apache.maven + maven-embedder + ${maven.version} + + + org.sonatype.plexus + plexus-cipher + + + + + commons-cli + commons-cli + 1.4 + @@ -377,37 +414,6 @@ limitations under the License. - - org.codehaus.mojo - flatten-maven-plugin - 1.4.1 - - - flatten - process-resources - - flatten - - - true - oss - - remove - remove - remove - remove - - - - - flatten-clean - clean - - clean - - - - org.apache.maven.plugins maven-release-plugin @@ -432,37 +438,6 @@ limitations under the License. - - org.codehaus.mojo - flatten-maven-plugin - 1.4.1 - - - flatten - process-resources - - flatten - - - true - oss - - remove - remove - remove - remove - - - - - flatten-clean - clean - - clean - - - - org.apache.maven.plugins maven-release-plugin @@ -474,37 +449,6 @@ limitations under the License. true - - org.codehaus.mojo - flatten-maven-plugin - 1.4.1 - - - flatten - process-resources - - flatten - - - true - oss - - remove - remove - remove - remove - - - - - flatten-clean - clean - - clean - - - - org.apache.maven.plugins maven-release-plugin diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/BuildFileParser.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/BuildFileParser.java index 0239cd850..cd11195b4 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/BuildFileParser.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/BuildFileParser.java @@ -17,20 +17,14 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.apache.maven.execution.MavenSession; import org.openrewrite.ExecutionContext; import org.openrewrite.Parser; import org.openrewrite.SourceFile; import org.openrewrite.marker.Marker; -import org.openrewrite.maven.MavenExecutionContextView; -import org.openrewrite.maven.MavenMojoProjectParser; import org.openrewrite.maven.MavenParser; -import org.openrewrite.maven.cache.InMemoryMavenPomCache; -import org.openrewrite.maven.cache.MavenPomCache; import org.openrewrite.xml.tree.Xml; import org.springframework.core.io.Resource; import org.springframework.sbm.utils.ResourceUtil; -import org.springframework.stereotype.Component; import org.springframework.util.Assert; import java.nio.file.Path; diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenMojoProjectParserPrivateMethods.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/HelperWithoutAGoodName.java similarity index 84% rename from sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenMojoProjectParserPrivateMethods.java rename to sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/HelperWithoutAGoodName.java index aee9a7e4b..d6503c22a 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenMojoProjectParserPrivateMethods.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/HelperWithoutAGoodName.java @@ -15,10 +15,7 @@ */ package org.springframework.sbm.parsers; -import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.apache.maven.rtinfo.internal.DefaultRuntimeInformation; -import org.apache.maven.settings.crypto.DefaultSettingsDecrypter; import org.jetbrains.annotations.NotNull; import org.openrewrite.ExecutionContext; import org.openrewrite.Parser; @@ -31,18 +28,12 @@ import org.openrewrite.marker.Generated; import org.openrewrite.marker.Marker; import org.openrewrite.marker.Markers; -import org.openrewrite.maven.MavenMojoProjectParser; -import org.openrewrite.maven.ResourceParser; -import org.openrewrite.maven.tree.ResolvedDependency; -import org.openrewrite.maven.utilities.MavenArtifactDownloader; import org.openrewrite.xml.tree.Xml; -import org.sonatype.plexus.components.cipher.DefaultPlexusCipher; -import org.sonatype.plexus.components.cipher.PlexusCipherException; -import org.sonatype.plexus.components.sec.dispatcher.DefaultSecDispatcher; import org.springframework.core.io.Resource; import org.springframework.sbm.utils.ResourceUtil; -import java.nio.file.*; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.*; import java.util.function.Predicate; import java.util.function.UnaryOperator; @@ -53,12 +44,35 @@ * @author Fabian Krüger */ @Slf4j -@RequiredArgsConstructor -class MavenMojoProjectParserPrivateMethods { +public class HelperWithoutAGoodName { + /** + * {@link MavenMojoProjectParser#addProvenance(Path, List, Collection)} + */ + public UnaryOperator addProvenance(Path baseDir, List provenance, @Nullable Collection generatedSources) { +// MavenMojoProjectParser mavenMojoProjectParser = createMavenMojoProjectParser(baseDir); +// Method method = ReflectionUtils.findMethod(MavenMojoProjectParser.class, "addProvenance", Path.class, List.class, Collection.class); +// ReflectionUtils.makeAccessible(method); +// if(method == null) { +// throw new IllegalStateException("Could not find method '%s' on %s while trying to call it.".formatted("addProvenance", MavenMojoProjectParser.class.getName())); +// } +// Object result = ReflectionUtils.invokeMethod(method, mavenMojoProjectParser, baseDir, provenance, generatedSources); +// return (UnaryOperator) result; + return (s) -> { + Markers markers = s.getMarkers(); - private final MavenMojoProjectParserFactory mavenMojoProjectParserFactory; - private final MavenArtifactDownloader artifactDownloader; + Marker marker; + for (Iterator var5 = provenance.iterator(); var5.hasNext(); markers = markers.addIfAbsent(marker)) { + marker = (Marker) var5.next(); + } + if (generatedSources != null && generatedSources.contains(baseDir.resolve(s.getSourcePath()))) { + markers = markers.addIfAbsent(new Generated(Tree.randomId())); + } + + return (T) s.withMarkers(markers); + }; + } /** * process sources in src/main/java of current module. @@ -141,6 +155,12 @@ public List processMainSources( return sourceFiles; } + @NotNull + private static JavaSourceSet sourceSet(String name, List dependencies, JavaTypeCache typeCache) { + return JavaSourceSet.build(name, dependencies, typeCache, false); + } + + /** * Calls {@link MavenMojoProjectParser#processTestSources(SbmMavenProject, JavaParser.Builder, ResourceParser, List, Set, ExecutionContext)} */ @@ -192,11 +212,6 @@ public List processTestSources( return result; } - @NotNull - private static JavaSourceSet sourceSet(String name, List dependencies, JavaTypeCache typeCache) { - return JavaSourceSet.build(name, dependencies, typeCache, false); - } - // FIXME: 945 take Java sources from resources private static List listJavaSources(List resources, Path sourceDirectory) { @@ -215,63 +230,4 @@ private static Predicate whenFileNameEndsWithJava() { private static Predicate whenIn(Path sourceDirectory) { return r -> ResourceUtil.getPath(r).toString().startsWith(sourceDirectory.toString()); } - - - // TODO: 945 keep but move to a better class - - /** - * {@link MavenMojoProjectParser#addProvenance(Path, List, Collection)} - */ - public UnaryOperator addProvenance(Path baseDir, List provenance, @Nullable Collection generatedSources) { -// MavenMojoProjectParser mavenMojoProjectParser = createMavenMojoProjectParser(baseDir); -// Method method = ReflectionUtils.findMethod(MavenMojoProjectParser.class, "addProvenance", Path.class, List.class, Collection.class); -// ReflectionUtils.makeAccessible(method); -// if(method == null) { -// throw new IllegalStateException("Could not find method '%s' on %s while trying to call it.".formatted("addProvenance", MavenMojoProjectParser.class.getName())); -// } -// Object result = ReflectionUtils.invokeMethod(method, mavenMojoProjectParser, baseDir, provenance, generatedSources); -// return (UnaryOperator) result; - return (s) -> { - Markers markers = s.getMarkers(); - - Marker marker; - for (Iterator var5 = provenance.iterator(); var5.hasNext(); markers = markers.addIfAbsent(marker)) { - marker = (Marker) var5.next(); - } - - if (generatedSources != null && generatedSources.contains(baseDir.resolve(s.getSourcePath()))) { - markers = markers.addIfAbsent(new Generated(Tree.randomId())); - } - - return (T) s.withMarkers(markers); - }; - } - - private MavenMojoProjectParser createMavenMojoProjectParser(Path baseDir) { - try { - return mavenMojoProjectParserFactory.create(baseDir, new DefaultRuntimeInformation(), new DefaultSettingsDecrypter(new DefaultSecDispatcher(new DefaultPlexusCipher()))); - } catch (PlexusCipherException e) { - throw new RuntimeException(e); - } - } - - private List downloadArtifacts(List dependencies) { - -// eventPublisher.publishEvent(new StartDownloadingDependenciesEvent(dependencies.size())); - - - List paths = dependencies - .stream() - .filter(d -> d.getRepository() != null) -// .peek(d -> eventPublisher.publishEvent(new StartDownloadingDependencyEvent(d.getRequested()))) -// .parallel() - .map(artifactDownloader::downloadArtifact) - .filter(Objects::nonNull) - .collect(Collectors.toList()); - -// eventPublisher.publishEvent(new FinishedDownloadingDependencies()); - - return paths; - } } diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenConfigFileParser.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenConfigFileParser.java index 2d2137b73..74f54743c 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenConfigFileParser.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenConfigFileParser.java @@ -18,7 +18,6 @@ import org.apache.commons.cli.*; import org.apache.maven.cli.CleanArgument; import org.jetbrains.annotations.NotNull; -import org.springframework.stereotype.Component; import java.io.File; import java.io.IOException; diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenParserConfiguration.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenParserConfiguration.java deleted file mode 100644 index dd9d93f1e..000000000 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenParserConfiguration.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2021 - 2023 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 - * - * https://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.sbm.parsers; - -import org.springframework.boot.autoconfigure.AutoConfiguration; -import org.springframework.context.annotation.Bean; - -/** - * @author Fabian Krüger - */ -@AutoConfiguration -public class MavenParserConfiguration { - @Bean - MavenConfigFileParser configFileParser() { - return new MavenConfigFileParser(); - } - - @Bean - MavenExecutionRequestFactory requestFactory(MavenConfigFileParser configFileParser) { - return new MavenExecutionRequestFactory(configFileParser); - } - - @Bean - MavenExecutor mavenExecutor(MavenExecutionRequestFactory requestFactory, MavenPlexusContainer plexusContainer) { - return new MavenExecutor(requestFactory, plexusContainer); - } - - @Bean - MavenModelReader modelReader() { - return new MavenModelReader(); - } - -} diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/ProvenanceMarkerFactory.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/ProvenanceMarkerFactory.java index e4e683244..5fbaebaf6 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/ProvenanceMarkerFactory.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/ProvenanceMarkerFactory.java @@ -16,12 +16,7 @@ package org.springframework.sbm.parsers; import lombok.RequiredArgsConstructor; -import org.apache.maven.project.MavenProject; -import org.apache.maven.rtinfo.RuntimeInformation; -import org.apache.maven.rtinfo.internal.DefaultRuntimeInformation; -import org.apache.maven.settings.crypto.SettingsDecrypter; import org.openrewrite.marker.Marker; -import org.openrewrite.maven.MavenMojoProjectParser; import org.springframework.core.io.Resource; import org.springframework.sbm.utils.ResourceUtil; diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteParserConfiguration.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteParserConfiguration.java index 4e155f21e..82f8bf20f 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteParserConfiguration.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteParserConfiguration.java @@ -47,30 +47,29 @@ * @author Fabian Krüger */ @Slf4j -@AutoConfiguration(after = {MavenParserConfiguration.class, ScopeConfiguration.class}) +@AutoConfiguration(after = {ScopeConfiguration.class}) @EnableConfigurationProperties(ParserProperties.class) -@Import({ScanScope.class, ScopeConfiguration.class, MavenParserConfiguration.class}) +@Import({ScanScope.class, ScopeConfiguration.class}) public class RewriteParserConfiguration { @Autowired private ParserProperties parserProperties; +// @Bean +// ProvenanceMarkerFactory provenanceMarkerFactory(MavenMojoProjectParserFactory projectParserFactory) { +// return new ProvenanceMarkerFactory(projectParserFactory); +// } + @Bean - MavenPlexusContainer plexusContainer() { - return new MavenPlexusContainer(); + MavenProvenanceMarkerFactory mavenProvenanceMarkerFactory() { + return new MavenProvenanceMarkerFactory(); } - @Bean - MavenMojoProjectParserFactory projectParserFactory() { - return new MavenMojoProjectParserFactory(parserProperties); + ProvenanceMarkerFactory provenanceMarkerFactory(MavenProvenanceMarkerFactory mavenPovenanceMarkerFactory) { + return new ProvenanceMarkerFactory(mavenPovenanceMarkerFactory); } -// @Bean -// ProvenanceMarkerFactory provenanceMarkerFactory(MavenMojoProjectParserFactory projectParserFactory) { -// return new ProvenanceMarkerFactory(projectParserFactory); -// } - @Bean @org.springframework.sbm.scopes.annotations.ScanScope JavaParserBuilder javaParserBuilder() { @@ -101,25 +100,14 @@ RewriteMavenArtifactDownloader artifactDownloader(MavenArtifactCache mavenArtifa return new RewriteMavenArtifactDownloader(mavenArtifactCache, projectMetadata.getMavenSettings(), artifactDownloaderErrorConsumer); } - // FIXME: 945 remove @Bean - MavenMojoProjectParserPrivateMethods mavenMojoProjectParserPrivateMethods(MavenMojoProjectParserFactory parserFactory, MavenArtifactDownloader artifactDownloader) { - return new MavenMojoProjectParserPrivateMethods(parserFactory, artifactDownloader); + HelperWithoutAGoodName helperWithoutAGoodName() { + return new HelperWithoutAGoodName(); } @Bean - SourceFileParser sourceFileParser(JavaParserBuilder javaParserBuilder, MavenMojoProjectParserPrivateMethods mavenMojoProjectParserPrivateMethods) { - return new SourceFileParser(parserProperties, mavenMojoProjectParserPrivateMethods, javaParserBuilder); - } - - @Bean - MavenProvenanceMarkerFactory mavenProvenanceMarkerFactory(MavenMojoProjectParserFactory mavenMojoProjectParserFactory) { - return new MavenProvenanceMarkerFactory(); - } - - @Bean - ProvenanceMarkerFactory provenanceMarkerFactory(MavenProvenanceMarkerFactory mavenPovenanceMarkerFactory) { - return new ProvenanceMarkerFactory(mavenPovenanceMarkerFactory); + SourceFileParser sourceFileParser(JavaParserBuilder javaParserBuilder, HelperWithoutAGoodName helperWithoutAGoodName) { + return new SourceFileParser(parserProperties, helperWithoutAGoodName); } @Bean @@ -133,17 +121,18 @@ ParsingEventListener parsingEventListener(ApplicationEventPublisher eventPublish return new RewriteParsingEventListenerAdapter(eventPublisher); } - @Bean - RewriteMavenProjectParser rewriteMavenProjectParser(MavenPlexusContainer plexusContainer, ParsingEventListener parsingListener, MavenExecutor mavenExecutor, MavenMojoProjectParserFactory projectParserFactory, ScanScope scanScope, ConfigurableListableBeanFactory beanFactory, ExecutionContext executionContext) { - return new RewriteMavenProjectParser( - plexusContainer, - parsingListener, - mavenExecutor, - projectParserFactory, - scanScope, - beanFactory, - executionContext); - } + // FIXME: 945 +// @Bean +// RewriteMavenProjectParser rewriteMavenProjectParser(MavenPlexusContainer plexusContainer, ParsingEventListener parsingListener, MavenExecutor mavenExecutor, MavenMojoProjectParserFactory projectParserFactory, ScanScope scanScope, ConfigurableListableBeanFactory beanFactory, ExecutionContext executionContext) { +// return new RewriteMavenProjectParser( +// plexusContainer, +// parsingListener, +// mavenExecutor, +// projectParserFactory, +// scanScope, +// beanFactory, +// executionContext); +// } @Bean MavenProjectAnalyzer mavenProjectAnalyzer(MavenArtifactDownloader artifactDownloader) { @@ -152,7 +141,6 @@ MavenProjectAnalyzer mavenProjectAnalyzer(MavenArtifactDownloader artifactDownlo @Bean RewriteProjectParser rewriteProjectParser( - MavenExecutor mavenExecutor, ProvenanceMarkerFactory provenanceMarkerFactory, BuildFileParser buildFileParser, SourceFileParser sourceFileParser, @@ -166,7 +154,6 @@ RewriteProjectParser rewriteProjectParser( ExecutionContext executionContext, MavenProjectAnalyzer mavenProjectAnalyzer) { return new RewriteProjectParser( - mavenExecutor, provenanceMarkerFactory, buildFileParser, sourceFileParser, diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteProjectParser.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteProjectParser.java index 478205f73..1a4881906 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteProjectParser.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteProjectParser.java @@ -17,14 +17,10 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.apache.maven.execution.MavenSession; -import org.apache.maven.plugin.MojoExecutionException; -import org.apache.maven.plugin.MojoFailureException; import org.jetbrains.annotations.NotNull; import org.openrewrite.ExecutionContext; import org.openrewrite.SourceFile; import org.openrewrite.marker.Marker; -import org.openrewrite.maven.AbstractRewriteMojo; import org.openrewrite.maven.MavenExecutionContextView; import org.openrewrite.maven.tree.*; import org.openrewrite.style.NamedStyles; @@ -68,14 +64,12 @@ * * * @author Fabian Krüger - * @see RewriteMavenProjectParser * @see org.springframework.sbm.recipes.RewriteRecipeDiscovery */ @Slf4j @RequiredArgsConstructor public class RewriteProjectParser { - private final MavenExecutor mavenExecutor; private final ProvenanceMarkerFactory provenanceMarkerFactory; private final BuildFileParser buildFileParser; private final SourceFileParser sourceFileParser; @@ -179,32 +173,4 @@ private static void addSourceFileToModel(Path baseDir, List sor .filter(p -> ResourceUtil.getPath(p.getPomFile()).toString().equals(baseDir.resolve(s.getSourcePath()).toString())) .forEach(p -> p.setSourceFile(s)); } - - private void withMavenSession(Path baseDir, Consumer consumer) { - List goals = List.of("clean", "package"); - log.debug("Successfully finished goals %s".formatted(goals)); - mavenExecutor.onProjectSucceededEvent(baseDir, goals, event -> consumer.accept(event.getSession())); - } - - @org.jetbrains.annotations.Nullable - private static List autoDetectStyles(Stream sourceFilesStream) { - RewriteMojo dummyRewriteMojo = new RewriteMojo(); - Method sourcesWithAutoDetectedStylesMethod = ReflectionUtils.findMethod(RewriteMojo.class, "sourcesWithAutoDetectedStyles"); - ReflectionUtils.makeAccessible(sourcesWithAutoDetectedStylesMethod); - Object o = ReflectionUtils.invokeMethod(sourcesWithAutoDetectedStylesMethod, dummyRewriteMojo, sourceFilesStream); - List sourceFiles = (List) o; - return sourceFiles; - } - - /** - * Extending {@code AbstractRewriteMojo} to open up protected method for reuse - */ - static class RewriteMojo extends AbstractRewriteMojo { - - @Override - public void execute() throws MojoExecutionException, MojoFailureException { - - } - } - } diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteResourceParser.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteResourceParser.java index ec24f6887..20fbebfd0 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteResourceParser.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteResourceParser.java @@ -15,7 +15,7 @@ */ package org.springframework.sbm.parsers; -import org.apache.maven.plugin.logging.Log; +import lombok.extern.slf4j.Slf4j; import org.jetbrains.annotations.NotNull; import org.openrewrite.ExecutionContext; import org.openrewrite.Parser; @@ -23,10 +23,8 @@ import org.openrewrite.hcl.HclParser; import org.openrewrite.java.JavaParser; import org.openrewrite.json.JsonParser; -import org.openrewrite.maven.ResourceParser; import org.openrewrite.properties.PropertiesParser; import org.openrewrite.protobuf.ProtoParser; -import org.openrewrite.python.PythonParser; import org.openrewrite.quark.QuarkParser; import org.openrewrite.text.PlainTextParser; import org.openrewrite.xml.XmlParser; @@ -44,11 +42,11 @@ * Code from https://github.com/fabapp2/rewrite-maven-plugin/blob/83d184ea9ffe3046429f16c91aa56a9610bae832/src/main/java/org/openrewrite/maven/ResourceParser.java * The motivation was to decouple the parser from file access. */ -public class RewriteResourceParser extends ResourceParser { // TODO: Only extends from ResourceParser to keep method signatures for now +@Slf4j +public class RewriteResourceParser { private static final Set DEFAULT_IGNORED_DIRECTORIES = new HashSet<>(Arrays.asList("build", "target", "out", ".sonar", ".gradle", ".idea", ".project", "node_modules", ".git", ".metadata", ".DS_Store")); private final Path baseDir; - private final Log logger; private final Collection exclusions; private final int sizeThresholdMb; private final Collection excludedDirectories; @@ -60,11 +58,16 @@ public class RewriteResourceParser extends ResourceParser { // TODO: Only extend private final JavaParser.Builder javaParserBuilder; private final ExecutionContext executionContext; - public RewriteResourceParser(Path baseDir, Log logger, Collection exclusions, Collection plainTextMasks, int sizeThresholdMb, Collection excludedDirectories, - JavaParser.Builder javaParserBuilder, ExecutionContext executionContext) { - super(baseDir, logger, exclusions, plainTextMasks, sizeThresholdMb, excludedDirectories, javaParserBuilder); + public RewriteResourceParser( + Path baseDir, + Collection exclusions, + Collection plainTextMasks, + int sizeThresholdMb, + Collection excludedDirectories, + JavaParser.Builder javaParserBuilder, + ExecutionContext executionContext + ) { this.baseDir = baseDir; - this.logger = logger; this.javaParserBuilder = javaParserBuilder; this.executionContext = executionContext; this.exclusions = pathMatchers(baseDir, exclusions); @@ -132,7 +135,7 @@ public Stream parseSourceFiles( // FIXME: 945 only check threshold if value > 0 is given long fileSize = ResourceUtil.contentLength(resource); if (isOverSizeThreshold(fileSize)) { - logger.info("Parsing as quark " + file + " as its size " + fileSize / (1024L * 1024L) + + log.info("Parsing as quark " + file + " as its size " + fileSize / (1024L * 1024L) + "Mb exceeds size threshold " + sizeThresholdMb + "Mb"); quarkPaths.add(file); } else if (isParsedAsPlainText(file)) { @@ -163,8 +166,9 @@ public Stream parseSourceFiles( ProtoParser protoParser = new ProtoParser(); List protoPaths = new ArrayList<>(); - PythonParser pythonParser = PythonParser.builder().build(); - List pythonPaths = new ArrayList<>(); + // Python currently not supported +// PythonParser pythonParser = PythonParser.builder().build(); +// List pythonPaths = new ArrayList<>(); HclParser hclParser = HclParser.builder().build(); List hclPaths = new ArrayList<>(); @@ -191,9 +195,9 @@ public Stream parseSourceFiles( propertiesPaths.add(path); } else if (protoParser.accept(path)) { protoPaths.add(path); - } else if(pythonParser.accept(path)) { + } /*else if(pythonParser.accept(path)) { pythonPaths.add(path); - } else if (hclParser.accept(path)) { + }*/ else if (hclParser.accept(path)) { hclPaths.add(path); } else if (quarkParser.accept(path)) { quarkPaths.add(path); @@ -238,11 +242,11 @@ public Stream parseSourceFiles( alreadyParsed.addAll(protoPaths); } - if (!pythonPaths.isEmpty()) { - List inputs = getInputs(pathToResource, pythonPaths); - sourceFiles = Stream.concat(sourceFiles, (Stream) pythonParser.parseInputs(inputs, baseDir, ctx)); - alreadyParsed.addAll(pythonPaths); - } +// if (!pythonPaths.isEmpty()) { +// List inputs = getInputs(pathToResource, pythonPaths); +// sourceFiles = Stream.concat(sourceFiles, (Stream) pythonParser.parseInputs(inputs, baseDir, ctx)); +// alreadyParsed.addAll(pythonPaths); +// } if (!hclPaths.isEmpty()) { List inputs = getInputs(pathToResource, hclPaths); diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SourceFileParser.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SourceFileParser.java index cbe6f3f17..eccdcbd7b 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SourceFileParser.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/SourceFileParser.java @@ -21,7 +21,6 @@ import org.openrewrite.SourceFile; import org.openrewrite.java.JavaParser; import org.openrewrite.marker.Marker; -import org.openrewrite.maven.ResourceParser; import org.openrewrite.style.NamedStyles; import org.openrewrite.xml.tree.Xml; import org.springframework.core.io.Resource; @@ -42,8 +41,7 @@ public class SourceFileParser { private final ParserProperties parserProperties; - private final MavenMojoProjectParserPrivateMethods mavenMojoProjectParserPrivateMethods; - private final JavaParserBuilder javaParserBuilder; + private final HelperWithoutAGoodName mavenMojoProjectParserPrivateMethods; public List parseOtherSourceFiles( Path baseDir, @@ -63,19 +61,15 @@ public List parseOtherSourceFiles( if(markers == null || markers.isEmpty()) { log.warn("Could not find provenance markers for resource '%s'".formatted(parserContext.getMatchingBuildFileResource(currentMavenProject))); } - List sourceFiles = parseModuleSourceFiles(resources, parserContext, currentMavenProject, moduleBuildFile, markers, styles, executionContext, baseDir); + List sourceFiles = parseModuleSourceFiles(resources, currentMavenProject, moduleBuildFile, markers, styles, executionContext, baseDir); parsedSourceFiles.addAll(sourceFiles); }); return new ArrayList<>(parsedSourceFiles); } - /** - * {@link org.openrewrite.maven.MavenMojoProjectParser#listSourceFiles(SbmMavenProject, Xml.Document, List, List, ExecutionContext)} - */ private List parseModuleSourceFiles( List resources, - ParserContext parserContext, SbmMavenProject currentProject, Xml.Document moduleBuildFile, List provenanceMarkers, @@ -104,7 +98,6 @@ private List parseModuleSourceFiles( // FIXME: Why is skipResourceScanDirs required at all? Shouldn't the module know it's resources RewriteResourceParser rp = new RewriteResourceParser( baseDir, - new Slf4jToMavenLoggerAdapter(log), parserProperties.getIgnoredPathPatterns(), parserProperties.getPlainTextMasks(), parserProperties.getSizeThresholdMb(), diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/StyleDetector.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/StyleDetector.java index a6c7e0031..fd38c5383 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/StyleDetector.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/StyleDetector.java @@ -15,15 +15,20 @@ */ package org.springframework.sbm.parsers; -import org.apache.maven.plugin.MojoExecutionException; -import org.apache.maven.plugin.MojoFailureException; import org.openrewrite.SourceFile; -import org.openrewrite.maven.AbstractRewriteMojo; -import org.springframework.stereotype.Component; +import org.openrewrite.Tree; +import org.openrewrite.internal.ListUtils; +import org.openrewrite.java.style.Autodetect; +import org.openrewrite.java.tree.JavaSourceFile; +import org.openrewrite.marker.Marker; +import org.openrewrite.style.NamedStyles; +import org.openrewrite.xml.tree.Xml; import org.springframework.util.ReflectionUtils; import java.lang.reflect.Method; -import java.util.List; +import java.util.*; +import java.util.function.UnaryOperator; +import java.util.stream.Collectors; import java.util.stream.Stream; /** @@ -31,18 +36,49 @@ */ class StyleDetector { - public List sourcesWithAutoDetectedStyles(Stream sourceFilesStream) { - OpenedRewriteMojo m = new OpenedRewriteMojo(); - Method method = ReflectionUtils.findMethod(OpenedRewriteMojo.class, "sourcesWithAutoDetectedStyles", Stream.class); - ReflectionUtils.makeAccessible(method); - return (List) ReflectionUtils.invokeMethod(method, m, sourceFilesStream); + + List sourcesWithAutoDetectedStyles(Stream sourceFiles) { + org.openrewrite.java.style.Autodetect.Detector javaDetector = org.openrewrite.java.style.Autodetect.detector(); + org.openrewrite.xml.style.Autodetect.Detector xmlDetector = org.openrewrite.xml.style.Autodetect.detector(); + List sourceFileList = sourceFiles + .peek(javaDetector::sample) + .peek(xmlDetector::sample) + .toList(); + + Map, NamedStyles> stylesByType = new HashMap<>(); + stylesByType.put(JavaSourceFile.class, javaDetector.build()); + stylesByType.put(Xml.Document.class, xmlDetector.build()); + + return ListUtils.map(sourceFileList, applyAutodetectedStyle(stylesByType)); } - static class OpenedRewriteMojo extends AbstractRewriteMojo { + private UnaryOperator applyAutodetectedStyle(Map, NamedStyles> stylesByType) { + return (before) -> { + Iterator var2 = stylesByType.entrySet().iterator(); - @Override - public void execute() throws MojoExecutionException, MojoFailureException { - throw new UnsupportedOperationException(); - } + while(var2.hasNext()) { + Map.Entry, NamedStyles> styleTypeEntry = (Map.Entry)var2.next(); + if (((Class)styleTypeEntry.getKey()).isAssignableFrom(before.getClass())) { + before = (SourceFile)before.withMarkers(before.getMarkers().add((Marker)styleTypeEntry.getValue())); + } + } + + return before; + }; } + +// public List sourcesWithAutoDetectedStyles(Stream sourceFilesStream) { +// OpenedRewriteMojo m = new OpenedRewriteMojo(); +// Method method = ReflectionUtils.findMethod(OpenedRewriteMojo.class, "sourcesWithAutoDetectedStyles", Stream.class); +// ReflectionUtils.makeAccessible(method); +// return (List) ReflectionUtils.invokeMethod(method, m, sourceFilesStream); +// } +// +// static class OpenedRewriteMojo extends AbstractRewriteMojo { +// +// @Override +// public void execute() throws MojoExecutionException, MojoFailureException { +// throw new UnsupportedOperationException(); +// } +// } } diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/recipes/RewriteRecipeDiscovery.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/recipes/RewriteRecipeDiscovery.java index ffd0cabf2..008b53e5f 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/recipes/RewriteRecipeDiscovery.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/recipes/RewriteRecipeDiscovery.java @@ -17,9 +17,6 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.apache.maven.plugin.MojoExecutionException; -import org.apache.maven.plugin.MojoFailureException; -import org.apache.maven.project.MavenProject; import org.openrewrite.Recipe; import org.openrewrite.Validated; import org.openrewrite.config.ClasspathScanningLoader; @@ -27,10 +24,8 @@ import org.openrewrite.config.RecipeDescriptor; import org.openrewrite.config.ResourceLoader; import org.openrewrite.internal.lang.Nullable; -import org.openrewrite.maven.AbstractRewriteMojo; import org.springframework.sbm.parsers.RecipeValidationErrorException; import org.springframework.sbm.parsers.ParserProperties; -import org.springframework.stereotype.Component; import java.nio.file.Path; import java.util.ArrayList; @@ -101,41 +96,41 @@ public List discoverFilteredRecipes(List activeRecipes, Properti return recipes; } - public List discoverFilteredRecipes(List activeRecipes, MavenProject mavenProject) { - if (activeRecipes.isEmpty()) { - log.warn("No active recipes were provided."); - return emptyList(); - } - - List recipes = new ArrayList<>(); - - AbstractRewriteMojoHelper helper = new AbstractRewriteMojoHelper(mavenProject); - - Environment env =helper.environment(getClass().getClassLoader()); - Recipe recipe = env.activateAll(); -// Recipe recipe = env.activateRecipes(activeRecipes); - - if (recipe.getRecipeList().isEmpty()) { - log.warn("No recipes were activated. None of the provided 'activeRecipes' matched any of the applicable recipes."); - return emptyList(); - } - - Collection> validated = recipe.validateAll(); - List> failedValidations = validated.stream().map(Validated::failures) - .flatMap(Collection::stream).collect(toList()); - if (!failedValidations.isEmpty()) { - failedValidations.forEach(failedValidation -> log.error( - "Recipe validation error in " + failedValidation.getProperty() + ": " + - failedValidation.getMessage(), failedValidation.getException())); - if (parserProperties.isFailOnInvalidActiveRecipes()) { - throw new RecipeValidationErrorException("Recipe validation errors detected as part of one or more activeRecipe(s). Please check error logs."); - } else { - log.error("Recipe validation errors detected as part of one or more activeRecipe(s). Execution will continue regardless."); - } - } - - return recipes; - } +// public List discoverFilteredRecipes(List activeRecipes, MavenProject mavenProject) { +// if (activeRecipes.isEmpty()) { +// log.warn("No active recipes were provided."); +// return emptyList(); +// } +// +// List recipes = new ArrayList<>(); +// +// AbstractRewriteMojoHelper helper = new AbstractRewriteMojoHelper(mavenProject); +// +// Environment env = helper.environment(getClass().getClassLoader()); +// Recipe recipe = env.activateAll(); +//// Recipe recipe = env.activateRecipes(activeRecipes); +// +// if (recipe.getRecipeList().isEmpty()) { +// log.warn("No recipes were activated. None of the provided 'activeRecipes' matched any of the applicable recipes."); +// return emptyList(); +// } +// +// Collection> validated = recipe.validateAll(); +// List> failedValidations = validated.stream().map(Validated::failures) +// .flatMap(Collection::stream).collect(toList()); +// if (!failedValidations.isEmpty()) { +// failedValidations.forEach(failedValidation -> log.error( +// "Recipe validation error in " + failedValidation.getProperty() + ": " + +// failedValidation.getMessage(), failedValidation.getException())); +// if (parserProperties.isFailOnInvalidActiveRecipes()) { +// throw new RecipeValidationErrorException("Recipe validation errors detected as part of one or more activeRecipe(s). Please check error logs."); +// } else { +// log.error("Recipe validation errors detected as part of one or more activeRecipe(s). Execution will continue regardless."); +// } +// } +// +// return recipes; +// } public RecipeDescriptor findRecipeDescriptor(String anotherDummyRecipe) { ResourceLoader resourceLoader = new ClasspathScanningLoader(new Properties(), new String[]{"io.example"}); @@ -166,69 +161,73 @@ public List findRecipesByTags(String tag) { } - class AbstractRewriteMojoHelper extends AbstractRewriteMojo { - - public AbstractRewriteMojoHelper(MavenProject mavenProject) { - super.project = mavenProject; - } - - @Override - public void execute() throws MojoExecutionException, MojoFailureException { - throw new UnsupportedOperationException(); - } - - @Override - public Environment environment(@Nullable ClassLoader recipeClassLoader) { - Environment.Builder env = Environment.builder(this.project.getProperties()); - if (recipeClassLoader == null) { - env.scanRuntimeClasspath(new String[0]).scanUserHome(); - } else { - env.load(new ClasspathScanningLoader(this.project.getProperties(), recipeClassLoader)); - } - - - /*env.load(new ResourceLoader() { - @Override - public Collection listRecipes() { - return List.of(); - } - - @Override - public Collection listRecipeDescriptors() { - return List.of(); - } - - @Override - public Collection listStyles() { - return List.of(); - } - - @Override - public Collection listCategoryDescriptors() { - return List.of(); - } - - @Override - public Map> listContributors() { - return Map.of(); - } - - @Override - public Map> listRecipeExamples() { - return Map.of(); - } - });*/ - return env.build(); - } - - @Override - protected Environment environment() throws MojoExecutionException { - return super.environment(); - } - - @Override - public Path repositoryRoot() { - return super.repositoryRoot(); - } - } +// class AbstractRewriteMojoHelper extends AbstractRewriteMojo { +// +// public AbstractRewriteMojoHelper(MavenProject mavenProject) { +// super.project = mavenProject; +// } +// +// @Override +// public void execute() throws MojoExecutionException, MojoFailureException { +// throw new UnsupportedOperationException(); +// } +// +// @Override +// public Environment environment(@Nullable ClassLoader recipeClassLoader) { +// Environment.Builder env = Environment.builder(this.project.getProperties()); +// if (recipeClassLoader == null) { +// env.scanRuntimeClasspath(new String[0]).scanUserHome(); +// } else { +// env.load(new ClasspathScanningLoader(this.project.getProperties(), recipeClassLoader)); +// } +// +// +// /*env.load(new ResourceLoader() { +// @Override +// public Collection listRecipes() { +// return List.of(); +// } +// +// @Override +// public Collection listRecipeDescriptors() { +// return List.of(); +// } +// +// @Override +// public Collection listStyles() { +// return List.of(); +// } +// +// @Override +// public Collection listCategoryDescriptors() { +// return List.of(); +// } +// +// @Override +// public Map> listContributors() { +// return Map.of(); +// } +// +// @Override +// public Map> listRecipeExamples() { +// return Map.of(); +// } +// });*/ +// return env.build(); +// } +// +//// @Override +//// protected Environment environment() { +//// try { +//// return super.environment(); +//// } catch (MojoExecutionException e) { +//// throw new RuntimeException(e); +//// } +//// } +// +// @Override +// public Path repositoryRoot() { +// return super.repositoryRoot(); +// } +// } } diff --git a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/BuildFileParserTest.java b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/BuildFileParserTest.java index 4fe9254f4..197436dd8 100644 --- a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/BuildFileParserTest.java +++ b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/BuildFileParserTest.java @@ -15,7 +15,8 @@ */ package org.springframework.sbm.parsers; -import org.apache.maven.project.MavenProject; +import org.apache.commons.cli.*; +import org.apache.maven.cli.CleanArgument; import org.intellij.lang.annotations.Language; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenExecutionRequestFactory.java b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/MavenExecutionRequestFactory.java similarity index 98% rename from sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenExecutionRequestFactory.java rename to sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/MavenExecutionRequestFactory.java index 7d25a82df..988591c60 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenExecutionRequestFactory.java +++ b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/MavenExecutionRequestFactory.java @@ -15,6 +15,7 @@ */ package org.springframework.sbm.parsers; +import org.sonatype.plexus.components.sec.dispatcher.SecDispatcher; import lombok.RequiredArgsConstructor; import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.artifact.repository.ArtifactRepositoryFactory; diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenExecutionResultException.java b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/MavenExecutionResultException.java similarity index 100% rename from sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenExecutionResultException.java rename to sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/MavenExecutionResultException.java diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenExecutor.java b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/MavenExecutor.java similarity index 100% rename from sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenExecutor.java rename to sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/MavenExecutor.java diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenMojoProjectParserFactory.java b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/MavenMojoProjectParserFactory.java similarity index 100% rename from sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenMojoProjectParserFactory.java rename to sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/MavenMojoProjectParserFactory.java diff --git a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/MavenMojoProjectParserPrivateMethods.java b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/MavenMojoProjectParserPrivateMethods.java new file mode 100644 index 000000000..7eadc5a1a --- /dev/null +++ b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/MavenMojoProjectParserPrivateMethods.java @@ -0,0 +1,64 @@ +/* + * Copyright 2021 - 2023 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 + * + * https://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.sbm.parsers; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.maven.rtinfo.internal.DefaultRuntimeInformation; +import org.apache.maven.settings.crypto.DefaultSettingsDecrypter; +import org.jetbrains.annotations.NotNull; +import org.openrewrite.ExecutionContext; +import org.openrewrite.Parser; +import org.openrewrite.SourceFile; +import org.openrewrite.Tree; +import org.openrewrite.internal.lang.Nullable; +import org.openrewrite.java.JavaParser; +import org.openrewrite.java.internal.JavaTypeCache; +import org.openrewrite.java.marker.JavaSourceSet; +import org.openrewrite.marker.Generated; +import org.openrewrite.marker.Marker; +import org.openrewrite.marker.Markers; +import org.openrewrite.maven.MavenMojoProjectParser; +import org.openrewrite.maven.ResourceParser; +import org.openrewrite.maven.tree.ResolvedDependency; +import org.openrewrite.maven.utilities.MavenArtifactDownloader; +import org.openrewrite.xml.tree.Xml; +import org.sonatype.plexus.components.cipher.DefaultPlexusCipher; +import org.sonatype.plexus.components.cipher.PlexusCipherException; +import org.sonatype.plexus.components.sec.dispatcher.DefaultSecDispatcher; +import org.springframework.core.io.Resource; +import org.springframework.sbm.utils.ResourceUtil; + +import java.nio.file.*; +import java.util.*; +import java.util.function.Predicate; +import java.util.function.UnaryOperator; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * @author Fabian Krüger + */ +@Slf4j +@RequiredArgsConstructor +class MavenMojoProjectParserPrivateMethods { + + private final MavenMojoProjectParserFactory mavenMojoProjectParserFactory; + private final MavenArtifactDownloader artifactDownloader; + + + +} diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenPlexusContainer.java b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/MavenPlexusContainer.java similarity index 100% rename from sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/MavenPlexusContainer.java rename to sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/MavenPlexusContainer.java diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteMavenProjectParser.java b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteMavenProjectParser.java similarity index 100% rename from sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/RewriteMavenProjectParser.java rename to sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteMavenProjectParser.java diff --git a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteMavenProjectParserIntegrationTest.java b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteMavenProjectParserIntegrationTest.java index de0ca36f3..b9531e261 100644 --- a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteMavenProjectParserIntegrationTest.java +++ b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteMavenProjectParserIntegrationTest.java @@ -22,6 +22,7 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.TestConfiguration; import org.springframework.context.event.EventListener; +import org.springframework.sbm.boot.autoconfigure.SbmSupportRewriteConfiguration; import org.springframework.sbm.boot.autoconfigure.ScannerConfiguration; import org.springframework.sbm.parsers.events.FinishedParsingResourceEvent; @@ -34,7 +35,7 @@ /** * @author Fabian Krüger */ -@SpringBootTest(classes = {ScannerConfiguration.class, RewriteMavenProjectParserIntegrationTest.TestEventListener.class}) +@SpringBootTest(classes = {SbmSupportRewriteConfiguration.class, SbmTestConfiguration.class}) public class RewriteMavenProjectParserIntegrationTest { @Autowired diff --git a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteMavenProjectParserTest.java b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteMavenProjectParserTest.java index 36917ee34..097668d07 100644 --- a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteMavenProjectParserTest.java +++ b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteMavenProjectParserTest.java @@ -276,14 +276,13 @@ void parseMultiModule1_WithCustomParser() { MavenArtifactCache mavenArtifactCache = new LocalMavenArtifactCache(Paths.get(System.getProperty("user.home"), ".m2", "repository")); @Nullable MavenSettings mavenSettings = null; Consumer onError = (t) -> {throw new RuntimeException(t);}; - MavenMojoProjectParserPrivateMethods mavenMojoParserPrivateMethods = new MavenMojoProjectParserPrivateMethods(mavenMojoProjectParserFactory, new RewriteMavenArtifactDownloader(mavenArtifactCache, mavenSettings, onError)); + HelperWithoutAGoodName helperWithoutAGoodName = new HelperWithoutAGoodName(); JavaParserBuilder javaParserBuilder = new JavaParserBuilder(); RewriteProjectParser rpp = new RewriteProjectParser( - new MavenExecutor(new MavenExecutionRequestFactory(new MavenConfigFileParser()), new MavenPlexusContainer()), new ProvenanceMarkerFactory(new MavenProvenanceMarkerFactory()), new BuildFileParser(), - new SourceFileParser(parserProperties, mavenMojoParserPrivateMethods, javaParserBuilder), + new SourceFileParser(parserProperties, helperWithoutAGoodName), new StyleDetector(), parserProperties, mock(ParsingEventListener.class), diff --git a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteProjectParserIntegrationTest.java b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteProjectParserIntegrationTest.java index 70bcd4abb..b2aa8f7d6 100644 --- a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteProjectParserIntegrationTest.java +++ b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteProjectParserIntegrationTest.java @@ -22,7 +22,9 @@ import org.openrewrite.java.tree.J; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.TestConfiguration; import org.springframework.core.io.Resource; +import org.springframework.sbm.boot.autoconfigure.SbmSupportRewriteConfiguration; import org.springframework.sbm.boot.autoconfigure.ScannerConfiguration; import org.springframework.sbm.parsers.events.FinishedParsingResourceEvent; import org.springframework.sbm.parsers.events.StartedParsingProjectEvent; @@ -39,7 +41,7 @@ /** * @author Fabian Krüger */ -@SpringBootTest(classes = {ScannerConfiguration.class}) +@SpringBootTest(classes = {SbmSupportRewriteConfiguration.class, SbmTestConfiguration.class}) public class RewriteProjectParserIntegrationTest { @Autowired diff --git a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteProjectParserTest.java b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteProjectParserTest.java index 08197e3c9..32792270b 100644 --- a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteProjectParserTest.java +++ b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/RewriteProjectParserTest.java @@ -101,13 +101,12 @@ void parseSimpleMavenProject(@TempDir Path tempDir) { Consumer onError = (t) -> { throw new RuntimeException(t); }; - MavenMojoProjectParserPrivateMethods mavenMojoParserPrivateMethods = new MavenMojoProjectParserPrivateMethods(mavenMojoProjectParserFactory, new RewriteMavenArtifactDownloader(mavenArtifactCache, mavenSettings, onError)); + HelperWithoutAGoodName mavenMojoParserPrivateMethods = new HelperWithoutAGoodName(); ExecutionContext executionContext = new InMemoryExecutionContext(t -> {throw new RuntimeException(t);}); RewriteProjectParser projectParser = new RewriteProjectParser( - new MavenExecutor(new MavenExecutionRequestFactory(new MavenConfigFileParser()), new MavenPlexusContainer()), new ProvenanceMarkerFactory(new MavenProvenanceMarkerFactory()), new BuildFileParser(), - new SourceFileParser(parserProperties, mavenMojoParserPrivateMethods, new JavaParserBuilder()), + new SourceFileParser(parserProperties, mavenMojoParserPrivateMethods), new StyleDetector(), parserProperties, mock(ParsingEventListener.class), diff --git a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/SbmTestConfiguration.java b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/SbmTestConfiguration.java new file mode 100644 index 000000000..c1b2ad37d --- /dev/null +++ b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/SbmTestConfiguration.java @@ -0,0 +1,90 @@ +/* + * Copyright 2021 - 2023 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 + * + * https://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.sbm.parsers; + +import lombok.extern.slf4j.Slf4j; +import org.openrewrite.ExecutionContext; +import org.openrewrite.maven.utilities.MavenArtifactDownloader; +import org.openrewrite.tree.ParsingEventListener; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Import; +import org.springframework.sbm.scopes.ScanScope; + +import static org.mockito.Mockito.mock; + +/** + * @author Fabian Krüger + */ +@TestConfiguration +@Slf4j +@Import(RewriteParserConfiguration.class) +public class SbmTestConfiguration { + + @Autowired + private ParserProperties parserProperties; + + @Bean + MavenMojoProjectParserPrivateMethods mavenMojoProjectParserPrivateMethods(MavenMojoProjectParserFactory parserFactory, MavenArtifactDownloader artifactDownloader) { + return new MavenMojoProjectParserPrivateMethods(parserFactory, artifactDownloader); + } + + + @Bean + MavenConfigFileParser configFileParser() { + return new MavenConfigFileParser(); + } + + @Bean + MavenExecutionRequestFactory requestFactory(MavenConfigFileParser configFileParser) { + return new MavenExecutionRequestFactory(configFileParser); + } + + @Bean + MavenExecutor mavenExecutor(MavenExecutionRequestFactory requestFactory, MavenPlexusContainer plexusContainer) { + return new MavenExecutor(requestFactory, plexusContainer); + } + + @Bean + MavenMojoProjectParserFactory projectParserFactory() { + return new MavenMojoProjectParserFactory(parserProperties); + } + + @Bean + MavenPlexusContainer plexusContainer() { + return new MavenPlexusContainer(); + } + + @Bean + MavenModelReader modelReader() { + return new MavenModelReader(); + } + + @Bean + RewriteMavenProjectParser rewriteMavenProjectParser(MavenPlexusContainer plexusContainer, ParsingEventListener parsingEventListenerAdapter, MavenExecutor mavenExecutor, MavenMojoProjectParserFactory mavenMojoProjectParserFactory, ScanScope scanScope, ConfigurableListableBeanFactory beanFactory, ExecutionContext executionContext) { + return new RewriteMavenProjectParser( + plexusContainer, + parsingEventListenerAdapter, + mavenExecutor, + mavenMojoProjectParserFactory, + scanScope, + beanFactory, + executionContext + ); + } +} diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/Slf4jToMavenLoggerAdapter.java b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/Slf4jToMavenLoggerAdapter.java similarity index 100% rename from sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/Slf4jToMavenLoggerAdapter.java rename to sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/Slf4jToMavenLoggerAdapter.java From 8d983378d2ef3c27ab52351e7f6b1c05f06b81f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Kr=C3=BCger?= Date: Thu, 28 Sep 2023 23:22:53 +0200 Subject: [PATCH 12/14] Remove conflicting deps and add missing ones * Adjust code to missing dependencies previously transitively available --- .../project/parser/MavenProjectParser.java | 21 +------- .../java/impl/ProjectJavaSourcesImplTest.java | 1 - .../project/resource/TestProjectContext.java | 11 ++-- components/sbm-openrewrite/pom.xml | 15 ++++++ components/test-helper/pom.xml | 20 ++++---- pom.xml | 51 ++++++++++--------- 6 files changed, 58 insertions(+), 61 deletions(-) diff --git a/components/sbm-core/src/main/java/org/springframework/sbm/project/parser/MavenProjectParser.java b/components/sbm-core/src/main/java/org/springframework/sbm/project/parser/MavenProjectParser.java index 3b3e9378c..48ea62a2c 100644 --- a/components/sbm-core/src/main/java/org/springframework/sbm/project/parser/MavenProjectParser.java +++ b/components/sbm-core/src/main/java/org/springframework/sbm/project/parser/MavenProjectParser.java @@ -18,37 +18,18 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.openrewrite.ExecutionContext; -import org.openrewrite.Parser; import org.openrewrite.SourceFile; -import org.openrewrite.internal.ListUtils; -import org.openrewrite.internal.lang.Nullable; import org.openrewrite.java.JavaParser; -import org.openrewrite.java.marker.JavaSourceSet; -import org.openrewrite.java.tree.J; -import org.openrewrite.marker.GitProvenance; -import org.openrewrite.marker.Marker; -import org.openrewrite.marker.ci.BuildEnvironment; -import org.openrewrite.maven.MavenExecutionContextView; -import org.openrewrite.maven.MavenSettings; -import org.openrewrite.maven.tree.*; import org.openrewrite.maven.utilities.MavenArtifactDownloader; -import org.openrewrite.xml.tree.Xml; import org.springframework.context.ApplicationEventPublisher; import org.springframework.core.io.Resource; -import org.springframework.sbm.build.impl.MavenBuildFileUtil; import org.springframework.sbm.build.impl.RewriteMavenParser; -import org.springframework.sbm.engine.events.*; -import org.springframework.sbm.parsers.RewriteMavenProjectParser; import org.springframework.sbm.parsers.RewriteProjectParser; import org.springframework.sbm.scopes.ProjectMetadata; import org.springframework.stereotype.Component; -import java.io.IOException; -import java.io.InputStream; import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.*; -import java.util.stream.Collectors; +import java.util.List; /** * Parse a Maven project on disk into a list of {@link org.openrewrite.SourceFile} including diff --git a/components/sbm-core/src/test/java/org/springframework/sbm/java/impl/ProjectJavaSourcesImplTest.java b/components/sbm-core/src/test/java/org/springframework/sbm/java/impl/ProjectJavaSourcesImplTest.java index 1b09ba9dc..3b421dc5a 100644 --- a/components/sbm-core/src/test/java/org/springframework/sbm/java/impl/ProjectJavaSourcesImplTest.java +++ b/components/sbm-core/src/test/java/org/springframework/sbm/java/impl/ProjectJavaSourcesImplTest.java @@ -20,7 +20,6 @@ import org.springframework.beans.factory.UnsatisfiedDependencyException; import org.springframework.sbm.engine.context.ProjectContext; import org.springframework.sbm.java.api.JavaSourceAndType; -import org.springframework.sbm.parsers.MavenExecutionResultException; import org.springframework.sbm.project.resource.TestProjectContext; import java.util.List; diff --git a/components/sbm-core/src/test/java/org/springframework/sbm/project/resource/TestProjectContext.java b/components/sbm-core/src/test/java/org/springframework/sbm/project/resource/TestProjectContext.java index 81d0424a9..52b130190 100644 --- a/components/sbm-core/src/test/java/org/springframework/sbm/project/resource/TestProjectContext.java +++ b/components/sbm-core/src/test/java/org/springframework/sbm/project/resource/TestProjectContext.java @@ -16,7 +16,6 @@ package org.springframework.sbm.project.resource; import freemarker.template.Configuration; -import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.RandomStringUtils; import org.jetbrains.annotations.NotNull; import org.openrewrite.ExecutionContext; @@ -31,7 +30,6 @@ import org.springframework.sbm.build.impl.OpenRewriteMavenBuildFile; import org.springframework.sbm.engine.context.ProjectContext; import org.springframework.sbm.engine.context.ProjectContextSerializer; -import org.springframework.sbm.java.impl.RewriteJavaParser; import org.springframework.sbm.java.util.JavaSourceUtil; import org.springframework.sbm.project.TestDummyResource; import org.springframework.sbm.project.parser.DependencyHelper; @@ -190,7 +188,7 @@ private static Path createProjectRoot() { Path sbm = tempDirectory.resolve("sbm"); // FileUtils.cleanDirectory(sbm.toFile()); Path randDir = sbm.resolve(RandomStringUtils.randomAlphanumeric(5)); - FileUtils.forceMkdir(randDir.toFile()); + Files.createDirectories(randDir); return randDir; } catch (IOException e) { throw new RuntimeException(e); @@ -596,9 +594,12 @@ public ProjectContext build() { executionContext); */ - // Writing to filesystem and parsing again changes th eresource order + // Writing to filesystem and parsing again changes the resource order try { - FileUtils.cleanDirectory(projectRoot.toFile()); + Files.walk(projectRoot) + .sorted(Comparator.reverseOrder()) + .map(Path::toFile) + .forEach(File::delete); } catch (IOException e) { throw new RuntimeException(e); } diff --git a/components/sbm-openrewrite/pom.xml b/components/sbm-openrewrite/pom.xml index f99e326eb..f7107386b 100644 --- a/components/sbm-openrewrite/pom.xml +++ b/components/sbm-openrewrite/pom.xml @@ -37,6 +37,21 @@ sbm-support-rewrite 0.1.0-SNAPSHOT + + org.openrewrite + rewrite-java-17 + ${openrewrite.version} + + + org.rocksdb + rocksdbjni + 8.3.2 + + + javax.xml.bind + jaxb-api + 2.3.1 + org.projectlombok lombok diff --git a/components/test-helper/pom.xml b/components/test-helper/pom.xml index a3da7b87b..53089f1d9 100644 --- a/components/test-helper/pom.xml +++ b/components/test-helper/pom.xml @@ -40,12 +40,6 @@ spring-core - - org.apache.maven.resolver - maven-resolver-spi - 1.9.15 - - org.jboss.shrinkwrap.resolver @@ -77,11 +71,17 @@ shrinkwrap-resolver-impl-maven-archive ${shrinkwrap.resolvers.version} + + + + + + + - org.jboss.shrinkwrap.resolver - shrinkwrap-resolver-bom - ${shrinkwrap.resolvers.version} - pom + org.apache.maven.resolver + maven-resolver-spi + 1.9.15 \ No newline at end of file diff --git a/pom.xml b/pom.xml index 72c1e5190..28f1cf545 100644 --- a/pom.xml +++ b/pom.xml @@ -64,26 +64,26 @@ - - org.apache.maven.wagon - wagon-http - 3.5.3 - - - org.apache.maven.resolver - maven-resolver-transport-http - 1.9.14 - - - org.apache.maven.resolver - maven-resolver-api - 1.9.14 - - - org.apache.maven.resolver - maven-resolver-impl - 1.9.14 - + + + + + + + + + + + + + + + + + + + + org.projectlombok @@ -131,11 +131,12 @@ - - org.apache.maven.shared - maven-invoker - ${maven-invoker.version} - + + + + + + org.openrewrite rewrite-core From a10cc189e24fb340c1e1bfaef89fab3e072fe243 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Kr=C3=BCger?= Date: Thu, 28 Sep 2023 23:22:53 +0200 Subject: [PATCH 13/14] Remove conflicting deps and add missing ones * Adjust code to missing dependencies previously transitively available --- components/recipe-test-support/pom.xml | 5 +++++ .../sbm/test/ProjectContextFileSystemTestSupport.java | 1 - .../sbm/test/RecipeIntegrationTestSupport.java | 2 +- components/sbm-core/pom.xml | 8 +++++++- components/sbm-recipes-jee-to-boot/pom.xml | 5 +++++ 5 files changed, 18 insertions(+), 3 deletions(-) diff --git a/components/recipe-test-support/pom.xml b/components/recipe-test-support/pom.xml index c425cafca..e3f6d31d7 100644 --- a/components/recipe-test-support/pom.xml +++ b/components/recipe-test-support/pom.xml @@ -66,6 +66,11 @@ test-jar compile + + commons-io + commons-io + 2.13.0 + \ No newline at end of file diff --git a/components/recipe-test-support/src/main/java/org/springframework/sbm/test/ProjectContextFileSystemTestSupport.java b/components/recipe-test-support/src/main/java/org/springframework/sbm/test/ProjectContextFileSystemTestSupport.java index 35512fad3..3094c2a29 100644 --- a/components/recipe-test-support/src/main/java/org/springframework/sbm/test/ProjectContextFileSystemTestSupport.java +++ b/components/recipe-test-support/src/main/java/org/springframework/sbm/test/ProjectContextFileSystemTestSupport.java @@ -21,7 +21,6 @@ import org.springframework.core.io.Resource; import org.springframework.sbm.engine.commands.ScanCommand; import org.springframework.sbm.engine.context.ProjectContext; -import org.springframework.sbm.parsers.RewriteExecutionContext; import org.springframework.sbm.project.parser.ProjectContextInitializer; import java.io.IOException; diff --git a/components/recipe-test-support/src/main/java/org/springframework/sbm/test/RecipeIntegrationTestSupport.java b/components/recipe-test-support/src/main/java/org/springframework/sbm/test/RecipeIntegrationTestSupport.java index 3b868ecba..fa73e5452 100644 --- a/components/recipe-test-support/src/main/java/org/springframework/sbm/test/RecipeIntegrationTestSupport.java +++ b/components/recipe-test-support/src/main/java/org/springframework/sbm/test/RecipeIntegrationTestSupport.java @@ -15,6 +15,7 @@ */ package org.springframework.sbm.test; +import org.apache.commons.io.FileUtils; import org.springframework.sbm.engine.commands.ApplicableRecipeListCommand; import org.springframework.sbm.engine.commands.ApplyCommand; import org.springframework.sbm.engine.commands.ScanCommand; @@ -26,7 +27,6 @@ import freemarker.template.Configuration; import lombok.AccessLevel; import lombok.Setter; -import org.apache.commons.io.FileUtils; import org.springframework.core.io.FileSystemResource; import org.springframework.core.io.Resource; diff --git a/components/sbm-core/pom.xml b/components/sbm-core/pom.xml index 574cb33e0..8127d0e55 100644 --- a/components/sbm-core/pom.xml +++ b/components/sbm-core/pom.xml @@ -173,7 +173,13 @@ tests test - + + commons-io + commons-io + 2.13.0 + test + + com.fasterxml.jackson.dataformat jackson-dataformat-xml 2.14.1 diff --git a/components/sbm-recipes-jee-to-boot/pom.xml b/components/sbm-recipes-jee-to-boot/pom.xml index 2ce02fa4b..b892d94e9 100644 --- a/components/sbm-recipes-jee-to-boot/pom.xml +++ b/components/sbm-recipes-jee-to-boot/pom.xml @@ -44,6 +44,11 @@ sbm-support-jee 0.15.2-SNAPSHOT + + commons-io + commons-io + 2.13.0 + From 312a39a78a574846499df7e524f10ac47c71dcb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Kr=C3=BCger?= Date: Thu, 28 Sep 2023 23:40:16 +0200 Subject: [PATCH 14/14] Fix build action --- .github/workflows/build-sbm-revamp.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-sbm-revamp.yml b/.github/workflows/build-sbm-revamp.yml index 4049b2640..30599208f 100644 --- a/.github/workflows/build-sbm-revamp.yml +++ b/.github/workflows/build-sbm-revamp.yml @@ -53,10 +53,10 @@ jobs: run: mvn -DskipTests --batch-mode install --projects :sbm-support-weblogic - name: sbm-recipes-jee-to-boot (build) - run: mvn -DskipTests --batch-mode --projects :sbm-recipes-jee-to-boot + run: mvn -DskipTests --batch-mode install --projects :sbm-recipes-jee-to-boot - name: sbm-recipes-spring-cloud (build) - run: mvn -DskipTests --batch-mode --projects :sbm-recipes-spring-cloud + run: mvn -DskipTests --batch-mode install --projects :sbm-recipes-spring-cloud - name: sbm-recipes-boot-upgrade (build) - run: mvn -DskipTests --batch-mode --projects :sbm-recipes-boot-upgrade \ No newline at end of file + run: mvn -DskipTests --batch-mode install --projects :sbm-recipes-boot-upgrade \ No newline at end of file