diff --git a/components/sbm-openrewrite/src/test/java/org/springframework/sbm/java/OpenRewriteTestSupport.java b/components/sbm-openrewrite/src/test/java/org/springframework/sbm/java/OpenRewriteTestSupport.java index 03d3cbbbf..4b4af4af0 100644 --- a/components/sbm-openrewrite/src/test/java/org/springframework/sbm/java/OpenRewriteTestSupport.java +++ b/components/sbm-openrewrite/src/test/java/org/springframework/sbm/java/OpenRewriteTestSupport.java @@ -23,6 +23,8 @@ import org.openrewrite.java.JavaVisitor; import org.openrewrite.java.tree.J; import org.openrewrite.maven.cache.LocalMavenArtifactCache; +import org.openrewrite.maven.tree.Dependency; +import org.openrewrite.maven.tree.GroupArtifactVersion; import org.openrewrite.maven.tree.ResolvedDependency; import org.openrewrite.maven.tree.ResolvedGroupArtifactVersion; import org.openrewrite.maven.utilities.MavenArtifactDownloader; @@ -250,9 +252,12 @@ public static List getClasspathFiles(String... gav) { }); return Arrays.stream(gav) .map(g -> g.split(":")) - .map(g -> new ResolvedGroupArtifactVersion(null, g[0], g[1], g.length == 3 ? g[2] : null, null)) .map(g -> ResolvedDependency.builder() - .gav(g) + .gav(new ResolvedGroupArtifactVersion(null, g[0], g[1], g.length == 3 ? g[2] : null, null)) + .requested(Dependency.builder() + .gav(new GroupArtifactVersion(g[0], g[1], g.length == 3 ? g[2] : null)) + .build() + ) .build() ) .map(g -> { diff --git a/sbm-support-rewrite-integration-test/.gitignore b/sbm-support-rewrite-integration-test/.gitignore new file mode 100644 index 000000000..5ff6309b7 --- /dev/null +++ b/sbm-support-rewrite-integration-test/.gitignore @@ -0,0 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/sbm-support-rewrite-integration-test/pom.xml b/sbm-support-rewrite-integration-test/pom.xml new file mode 100644 index 000000000..a08aa08d9 --- /dev/null +++ b/sbm-support-rewrite-integration-test/pom.xml @@ -0,0 +1,117 @@ + + + + + 4.0.0 + + org.example + sbm-support-rewrite-integration-test + 1.0-SNAPSHOT + + + 17 + 17 + UTF-8 + 3.1.3 + + + + + + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} + pom + import + + + + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.experimental + sbm-support-rewrite + 0.1.0-SNAPSHOT + + + org.openrewrite.recipe + rewrite-spring + 5.0.10 + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 3.1.3 + + + + repackage + + + + + + + org.apache.maven.wagon + wagon-http + + + org.apache.maven.resolver + maven-resolver-transport-wagon + + + org.apache.maven.resolver + maven-resolver-connector-basic + + + org.apache.maven + maven-compat + + + org.apache.maven + maven-embedder + + + org.codehaus.plexus + plexus-cipher + + + org.eclipse.sisu + org.eclipse.sisu.plexus + + + + + + com.acme.example.SpringBoot3Upgrade + + + + + + + \ No newline at end of file diff --git a/sbm-support-rewrite-integration-test/src/main/java/com/acme/example/SpringBoot3Upgrade.java b/sbm-support-rewrite-integration-test/src/main/java/com/acme/example/SpringBoot3Upgrade.java new file mode 100644 index 000000000..115c6e711 --- /dev/null +++ b/sbm-support-rewrite-integration-test/src/main/java/com/acme/example/SpringBoot3Upgrade.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 com.acme.example; + +import org.openrewrite.InMemoryExecutionContext; +import org.openrewrite.Recipe; +import org.openrewrite.internal.InMemoryLargeSourceSet; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.Resource; +import org.springframework.sbm.boot.autoconfigure.DiscoveryConfiguration; +import org.springframework.sbm.parsers.ProjectScanner; +import org.springframework.sbm.parsers.RewriteProjectParser; +import org.springframework.sbm.parsers.RewriteProjectParsingResult; +import org.springframework.sbm.recipes.RewriteRecipeDiscovery; + +import java.nio.file.Path; +import java.util.List; +import java.util.Optional; + +/** + * @author Fabian Krüger + */ +@SpringBootApplication +public class SpringBoot3Upgrade implements CommandLineRunner { + public static void main(String[] args) { + SpringApplication.run(SpringBoot3Upgrade.class, args); + } + + @Autowired + RewriteProjectParser parser; + @Autowired + ProjectScanner scanner; + @Autowired + RewriteRecipeDiscovery discovery; + + @Override + public void run(String... args) throws Exception { + Path baseDir = Path.of("/Users/fkrueger/projects/sbm-projects/spring-restbucks"); + List resources = scanner.scan(baseDir); + InMemoryExecutionContext executionContext = new InMemoryExecutionContext(); + RewriteProjectParsingResult parsingResult = parser.parse(baseDir, resources, executionContext); + String recipeName = "org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1"; + List recipes = discovery.discoverRecipes(); + Optional recipe = recipes.stream().filter(r -> recipeName.equals(r.getName())).findFirst(); + recipe.ifPresent(r -> r.run(new InMemoryLargeSourceSet(parsingResult.sourceFiles()), executionContext)); + } +} diff --git a/sbm-support-rewrite-integration-test/src/main/resources/application.properties b/sbm-support-rewrite-integration-test/src/main/resources/application.properties new file mode 100644 index 000000000..96cd9beef --- /dev/null +++ b/sbm-support-rewrite-integration-test/src/main/resources/application.properties @@ -0,0 +1,2 @@ +logging.level.root=warn +logging.level.org.springframework.sbm=debug \ No newline at end of file diff --git a/sbm-support-rewrite-maven/.gitignore b/sbm-support-rewrite-maven/.gitignore new file mode 100644 index 000000000..5ff6309b7 --- /dev/null +++ b/sbm-support-rewrite-maven/.gitignore @@ -0,0 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/sbm-support-rewrite-maven/pom.xml b/sbm-support-rewrite-maven/pom.xml new file mode 100644 index 000000000..8810fd2e4 --- /dev/null +++ b/sbm-support-rewrite-maven/pom.xml @@ -0,0 +1,191 @@ + + + 4.0.0 + + org.example + sbm-support-rewrite-maven + 1.0-SNAPSHOT + + + 17 + 17 + UTF-8 + 3.9.1 + 1.9.7 + 1.8 + 3.5.3 + 8.5.1 + 5.5.2 + + + + + org.openrewrite + rewrite-maven + ${rewrite.version} + + + org.openrewrite + rewrite-java + ${rewrite.version} + + + org.openrewrite + rewrite-json + ${rewrite.version} + + + org.openrewrite + rewrite-yaml + ${rewrite.version} + + + org.openrewrite + rewrite-hcl + ${rewrite.version} + + + org.openrewrite + rewrite-protobuf + ${rewrite.version} + + + org.openrewrite + rewrite-xml + ${rewrite.version} + + + org.openrewrite.maven + rewrite-maven-plugin + ${rewrite-maven-plugin.version} + + + + io.micrometer + micrometer-core + + + + org.openrewrite + rewrite-java + + + + org.openrewrite + rewrite-hcl + + + + org.openrewrite + rewrite-json + + + + org.openrewrite + rewrite-maven + + + + org.openrewrite + rewrite-protobuf + + + + org.openrewrite + rewrite-properties + + + + org.openrewrite + rewrite-xml + + + + org.openrewrite + rewrite-yaml + + + + org.openrewrite + rewrite-python + + + + + + org.apache.maven.wagon + wagon-http + ${maven-wagon-http.version} + + + org.apache.maven.resolver + maven-resolver-transport-wagon + ${maven-resolver.version} + + + org.apache.maven.resolver + maven-resolver-connector-basic + ${maven-resolver.version} + + + org.apache.maven + maven-compat + ${maven.version} + + + org.apache.commons + commons-lang3 + + + javax.annotation + javax.annotation-api + + + + + org.apache.maven + maven-embedder + ${maven.version} + + + org.sonatype.plexus + plexus-cipher + + + + + org.codehaus.plexus + plexus-cipher + ${plexus-cypher.version} + + + + org.eclipse.sisu + org.eclipse.sisu.plexus + 0.3.5 + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.4 + + + + true + /Users/fkrueger/.m2/repository + repository + com.example.PlexusContainerApp + + + + + + + \ No newline at end of file diff --git a/sbm-support-rewrite-maven/src/main/java/com/example/PlexusContainerApp.java b/sbm-support-rewrite-maven/src/main/java/com/example/PlexusContainerApp.java new file mode 100644 index 000000000..3811734e5 --- /dev/null +++ b/sbm-support-rewrite-maven/src/main/java/com/example/PlexusContainerApp.java @@ -0,0 +1,67 @@ +package com.example;/* + * Copyright 2021 - 2022 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. + */ + +import org.apache.maven.Maven; +import org.apache.maven.repository.RepositorySystem; +import org.apache.maven.repository.legacy.LegacyRepositorySystem; +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 java.net.URL; + +/** + * @author Fabian Krüger + */ +public class PlexusContainerApp { + public static void main(String[] args) throws ComponentLookupException { + PlexusContainer plexusContainer = create(); + Maven maven = plexusContainer.lookup(Maven.class); + System.out.println(maven); + RepositorySystem lookup = plexusContainer.lookup(RepositorySystem.class); + System.out.println(lookup); + } + + public static PlexusContainer create() { + try { + ClassLoader parent = null; + boolean isContainerAutoWiring = false; + String containerClassPathScanning = "on"; + String containerComponentVisibility = null; + URL overridingComponentsXml = null; //getClass().getClassLoader().getResource("META-INF/**/components.xml"); + + ContainerConfiguration configuration = new DefaultContainerConfiguration(); + configuration.setAutoWiring(isContainerAutoWiring) + .setClassPathScanning(containerClassPathScanning) + .setComponentVisibility(containerComponentVisibility) + .setContainerConfigurationURL(overridingComponentsXml); + + // inspired from https://github.com/jenkinsci/lib-jenkins-maven-embedder/blob/master/src/main/java/hudson/maven/MavenEmbedderUtils.java#L141 + ClassWorld classWorld = new ClassWorld(); + ClassRealm classRealm = new ClassRealm(classWorld, "maven", PlexusContainer.class.getClassLoader()); + classRealm.setParentRealm(new ClassRealm(classWorld, "maven-parent", + parent == null ? Thread.currentThread().getContextClassLoader() + : parent)); + configuration.setRealm(classRealm); + + configuration.setClassWorld(classWorld); + return new DefaultPlexusContainer(configuration); + } catch (PlexusContainerException e) { + throw new RuntimeException(e); + } + } +} diff --git a/sbm-support-rewrite/pom.xml b/sbm-support-rewrite/pom.xml index 2b7cdae61..d88c9c50c 100644 --- a/sbm-support-rewrite/pom.xml +++ b/sbm-support-rewrite/pom.xml @@ -21,7 +21,7 @@ 17 UTF-8 3.1.3 - 8.4.2 + 8.5.1 5.0.5 0.15.0-SNAPSHOT 5.3.2 @@ -94,6 +94,15 @@ + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-configuration-processor + true + com.squareup.okhttp3 okhttp @@ -138,15 +147,6 @@ rewrite-maven-plugin ${rewrite-maven-plugin.version} - - org.springframework.boot - spring-boot-starter - - - org.springframework.boot - spring-boot-configuration-processor - true - org.projectlombok lombok @@ -167,21 +167,6 @@ maven-resolver-connector-basic ${maven-resolver.version} - - org.apache.maven - maven-resolver-provider - ${maven.version} - - - org.apache.maven - maven-core - ${maven.version} - - - org.apache.maven - maven-artifact - ${maven.version} - org.apache.maven maven-compat @@ -203,20 +188,11 @@ plexus-cipher ${plexus-cypher.version} - - org.apache.maven - maven-model - ${maven.version} - - - org.apache.maven - maven-model-builder - ${maven.version} - org.apache.maven.shared maven-invoker ${maven-invoker.version} + test javax.xml.bind @@ -434,19 +410,6 @@ limitations under the License. true - - org.apache.maven.plugins - maven-source-plugin - 3.3.0 - - - attach-sources - - jar - - - - org.codehaus.mojo flatten-maven-plugin diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/boot/autoconfigure/SbmSupportRewriteConfiguration.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/boot/autoconfigure/SbmSupportRewriteConfiguration.java index 1baf190c3..e45c901dd 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/boot/autoconfigure/SbmSupportRewriteConfiguration.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/boot/autoconfigure/SbmSupportRewriteConfiguration.java @@ -22,6 +22,6 @@ * @author Fabian Krüger */ @AutoConfiguration -@Import(DiscoveryConfiguration.class) +@Import({DiscoveryConfiguration.class, ScannerConfiguration.class}) public class SbmSupportRewriteConfiguration { } 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..de4a7a4d1 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 @@ -39,112 +39,39 @@ */ class MavenConfigFileParser { - /** Constant ALTERNATE_POM_FILE='f' */ private static final char ALTERNATE_POM_FILE = 'f'; - - /** Constant BATCH_MODE='B' */ private static final char BATCH_MODE = 'B'; - - /** Constant SET_USER_PROPERTY='D' */ private static final char SET_USER_PROPERTY = 'D'; - - /** - * @deprecated Use {@link #SET_USER_PROPERTY} - */ - @Deprecated - private static final char SET_SYSTEM_PROPERTY = SET_USER_PROPERTY; - - /** Constant OFFLINE='o' */ private static final char OFFLINE = 'o'; - - /** Constant QUIET='q' */ private static final char QUIET = 'q'; - - /** Constant DEBUG='X' */ private static final char DEBUG = 'X'; - - /** Constant ERRORS='e' */ private static final char ERRORS = 'e'; - - /** Constant HELP='h' */ private static final char HELP = 'h'; - - /** Constant VERSION='v' */ private static final char VERSION = 'v'; - - /** Constant SHOW_VERSION='V' */ private static final char SHOW_VERSION = 'V'; - - /** Constant NON_RECURSIVE='N' */ private static final char NON_RECURSIVE = 'N'; - - /** Constant UPDATE_SNAPSHOTS='U' */ private static final char UPDATE_SNAPSHOTS = 'U'; - - /** Constant ACTIVATE_PROFILES='P' */ private static final char ACTIVATE_PROFILES = 'P'; - - /** Constant SUPRESS_SNAPSHOT_UPDATES="nsu" */ private static final String SUPRESS_SNAPSHOT_UPDATES = "nsu"; - - /** Constant CHECKSUM_FAILURE_POLICY='C' */ private static final char CHECKSUM_FAILURE_POLICY = 'C'; - - /** Constant CHECKSUM_WARNING_POLICY='c' */ private static final char CHECKSUM_WARNING_POLICY = 'c'; - - /** Constant ALTERNATE_USER_SETTINGS='s' */ private static final char ALTERNATE_USER_SETTINGS = 's'; - - /** Constant ALTERNATE_GLOBAL_SETTINGS="gs" */ private static final String ALTERNATE_GLOBAL_SETTINGS = "gs"; - - /** Constant ALTERNATE_USER_TOOLCHAINS='t' */ private static final char ALTERNATE_USER_TOOLCHAINS = 't'; - - /** Constant ALTERNATE_GLOBAL_TOOLCHAINS="gt" */ private static final String ALTERNATE_GLOBAL_TOOLCHAINS = "gt"; - - /** Constant FAIL_FAST="ff" */ private static final String FAIL_FAST = "ff"; - - /** Constant FAIL_AT_END="fae" */ private static final String FAIL_AT_END = "fae"; - - /** Constant FAIL_NEVER="fn" */ private static final String FAIL_NEVER = "fn"; - - /** Constant RESUME_FROM="rf" */ private static final String RESUME_FROM = "rf"; - - /** Constant PROJECT_LIST="pl" */ private static final String PROJECT_LIST = "pl"; - - /** Constant ALSO_MAKE="am" */ private static final String ALSO_MAKE = "am"; - - /** Constant ALSO_MAKE_DEPENDENTS="amd" */ private static final String ALSO_MAKE_DEPENDENTS = "amd"; - - /** Constant LOG_FILE="l" */ private static final String LOG_FILE = "l"; - - /** Constant ENCRYPT_MASTER_PASSWORD="emp" */ private static final String ENCRYPT_MASTER_PASSWORD = "emp"; - - /** Constant ENCRYPT_PASSWORD="ep" */ private static final String ENCRYPT_PASSWORD = "ep"; - - /** Constant THREADS="T" */ private static final String THREADS = "T"; - - /** Constant BUILDER="b" */ private static final String BUILDER = "b"; - - /** Constant NO_TRANSFER_PROGRESS="ntp" */ private static final String NO_TRANSFER_PROGRESS = "ntp"; - - /** Constant COLOR="color" */ private static final String COLOR = "color"; private static final String MVN_MAVEN_CONFIG = ".mvn/maven.config"; public List getActivatedProfiles(Path baseDir) { 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 036cc393e..f39ea56f8 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 @@ -70,7 +70,7 @@ public void projectSucceeded(ExecutionEvent event) { @Override public void mojoSucceeded(ExecutionEvent event) { super.mojoSucceeded(event); - System.out.println("Mojo succeeded: " + event.getMojoExecution().getGoal()); + log.info("Mojo succeeded: " + event.getMojoExecution().getGoal()); } @Override 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..ba11755e9 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,6 +15,8 @@ */ package org.springframework.sbm.parsers; +import jakarta.annotation.PostConstruct; +import lombok.extern.slf4j.Slf4j; import org.apache.maven.graph.GraphBuilder; import org.codehaus.plexus.*; import org.codehaus.plexus.classworlds.ClassWorld; @@ -25,53 +27,61 @@ import java.net.URL; -@Lazy +@Slf4j class MavenPlexusContainer { - public GraphBuilder lookup(Class aClass) { - try { - return ContainerHolder.INSTANCE.lookup(aClass); - } catch (ComponentLookupException e) { - throw new RuntimeException(e); - } - } + private PlexusContainer plexusContainer; - private static class ContainerHolder { - private static final PlexusContainer INSTANCE = create(); - public static PlexusContainer create() { - try { - ClassLoader parent = null; - boolean isContainerAutoWiring = false; - String containerClassPathScanning = "on"; - String containerComponentVisibility = null; - URL overridingComponentsXml = null; //getClass().getClassLoader().getResource("META-INF/**/components.xml"); + public MavenPlexusContainer() { - ContainerConfiguration configuration = new DefaultContainerConfiguration(); - configuration.setAutoWiring(isContainerAutoWiring) - .setClassPathScanning(containerClassPathScanning) - .setComponentVisibility(containerComponentVisibility) - .setContainerConfigurationURL(overridingComponentsXml); + } - // inspired from https://github.com/jenkinsci/lib-jenkins-maven-embedder/blob/master/src/main/java/hudson/maven/MavenEmbedderUtils.java#L141 - ClassWorld classWorld = new ClassWorld(); - ClassRealm classRealm = new ClassRealm(classWorld, "maven", PlexusContainer.class.getClassLoader()); - classRealm.setParentRealm(new ClassRealm(classWorld, "maven-parent", - parent == null ? Thread.currentThread().getContextClassLoader() - : parent)); - configuration.setRealm(classRealm); + @PostConstruct + public void postConstruct() { + plexusContainer = create(); + } - configuration.setClassWorld(classWorld); - return new DefaultPlexusContainer(configuration); - } catch (PlexusContainerException e) { - throw new RuntimeException(e); - } + public GraphBuilder lookup(Class aClass) { + try { + return plexusContainer.lookup(aClass); + } catch (ComponentLookupException e) { + throw new RuntimeException(e); } } @Deprecated public PlexusContainer get() { - return ContainerHolder.INSTANCE; + return plexusContainer; } + public PlexusContainer create() { + try { + ClassLoader parent = null; + boolean isContainerAutoWiring = false; + String containerClassPathScanning = PlexusConstants.SCANNING_ON; + String containerComponentVisibility = PlexusConstants.GLOBAL_VISIBILITY; + URL overridingComponentsXml = getClass().getClassLoader().getResource("META-INF/**/components.xml"); + + ContainerConfiguration configuration = new DefaultContainerConfiguration(); + configuration.setAutoWiring(isContainerAutoWiring) + .setClassPathScanning(containerClassPathScanning) + .setComponentVisibility(containerComponentVisibility) + .setContainerConfigurationURL(overridingComponentsXml); + // inspired from https://github.com/jenkinsci/lib-jenkins-maven-embedder/blob/master/src/main/java/hudson/maven/MavenEmbedderUtils.java#L141 + ClassWorld classWorld = new ClassWorld(); + + log.debug("ClassLoader for Plexus ClassRealm: " + PlexusContainer.class.getClassLoader().getClass().getName()); + ClassRealm classRealm = new ClassRealm(classWorld, "maven", PlexusContainer.class.getClassLoader()); + ClassLoader effectiveParent = parent == null ? Thread.currentThread().getContextClassLoader() : parent; + log.debug("Effective parent: " + effectiveParent.getClass().getName()); + ClassRealm parentRealm = new ClassRealm(classWorld, "maven-parent", effectiveParent); + classRealm.setParentRealm(parentRealm); + configuration.setRealm(classRealm); + configuration.setClassWorld(classWorld); + return new DefaultPlexusContainer(configuration); + } catch (PlexusContainerException e) { + throw new RuntimeException(e); + } + } } diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/ProjectScanner.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/ProjectScanner.java index 199d30b08..894d6b748 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/ProjectScanner.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/parsers/ProjectScanner.java @@ -17,6 +17,7 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.jetbrains.annotations.NotNull; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; import org.springframework.core.io.support.ResourcePatternUtils; @@ -27,8 +28,11 @@ import java.io.IOException; import java.nio.file.Path; import java.nio.file.PathMatcher; +import java.util.HashSet; import java.util.List; import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; import java.util.stream.Stream; /** @@ -41,33 +45,52 @@ class ProjectScanner { private final ResourceLoader resourceLoader; private final ParserProperties parserProperties; - public List scan(Path baseDir) { - if(!baseDir.isAbsolute()) { - baseDir = baseDir.toAbsolutePath().normalize(); + public List scan(Path givenBaseDir) { + if(!givenBaseDir.isAbsolute()) { + givenBaseDir = givenBaseDir.toAbsolutePath().normalize(); } - if(!baseDir.toFile().exists()) { - throw new IllegalArgumentException("Provided path does not exist: " + baseDir); + if(!givenBaseDir.toFile().exists()) { + throw new IllegalArgumentException("Provided path does not exist: " + givenBaseDir); } + final Path baseDir = givenBaseDir; String unifiedPath = new LinuxWindowsPathUnifier().unifyPath(baseDir.toString() + "/**"); String pattern = "file:" + unifiedPath; try { Resource[] resources = ResourcePatternUtils.getResourcePatternResolver(resourceLoader).getResources(pattern); - List pathMatchers = parserProperties.getIgnoredPathPatterns().stream() - .map(p -> p.startsWith("glob:") ? p : "glob:" + p) - .map(baseDir.getFileSystem()::getPathMatcher) - .toList(); + log.debug("Scanned %d resources in dir: '%s'".formatted(resources.length, baseDir.toString())); - return Stream.of(resources) - .filter(r -> isAccepted(r, pathMatchers)) - .toList(); + List resultingResources = filterIgnoredResources(baseDir, resources); + int numResulting = resultingResources.size(); + int numIgnored = resources.length - numResulting; + log.debug("Scan returns %s resources, %d resources were ignored.".formatted(numResulting, numIgnored)); + log.trace("Resources resulting from scan: %s".formatted(resultingResources.stream().map(r -> baseDir.relativize(ResourceUtil.getPath(r)).toString()).collect(Collectors.joining(", ")))); + + return resultingResources; } catch (IOException e) { throw new RuntimeException("Can't get resources for pattern '" + pattern + "'", e); } } - private boolean isAccepted(Resource r, List pathMatchers) { + @NotNull + private List filterIgnoredResources(Path baseDir, Resource[] resources) { + Set effectivePathMatcherPatterns = new HashSet<>(); + List pathMatchers = parserProperties.getIgnoredPathPatterns().stream() + .map(p -> p.startsWith("glob:") ? p : "glob:" + p) + .peek(p -> effectivePathMatcherPatterns.add(p)) + .map(baseDir.getFileSystem()::getPathMatcher) + .toList(); + + log.trace("Ignore resources matching any of these PathMatchers: %s".formatted(effectivePathMatcherPatterns.stream().collect(Collectors.joining(", ")))); + + List resultingResources = Stream.of(resources) + .filter(r -> isAccepted(baseDir, r, pathMatchers)) + .toList(); + return resultingResources; + } + + private boolean isAccepted(Path baseDir, Resource r, List pathMatchers) { if(ResourceUtil.getPath(r).toFile().isDirectory()) { return false; } @@ -76,14 +99,11 @@ private boolean isAccepted(Resource r, List pathMatchers) { .filter(matcher -> { Path resourcePath = ResourceUtil.getPath(r); boolean matches = matcher.matches(resourcePath); - if(matches && log.isInfoEnabled()) { - log.info("Resource '%s' matches ignore pattern '%s'".formatted(resourcePath, matcher)); - } return matches; }) .findFirst(); if(isIgnored.isPresent() && log.isInfoEnabled()) { - log.info("Ignoring scanned resource '%s'.".formatted(ResourceUtil.getPath(r))); + log.info("Ignoring resource '%s'.".formatted(baseDir.relativize(ResourceUtil.getPath(r)))); } return isIgnored.isEmpty(); } 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 3dfe72928..ae1f9dd84 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 @@ -28,7 +28,9 @@ import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; +import org.springframework.context.annotation.Lazy; 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.scopes.ProjectMetadata; import org.springframework.sbm.scopes.ScanScope; @@ -47,7 +49,7 @@ * @author Fabian Krüger */ @Slf4j -@AutoConfiguration(after = ScopeConfiguration.class) +@AutoConfiguration(after = {ScopeConfiguration.class}) @EnableConfigurationProperties(ParserProperties.class) @Import({ScanScope.class, ScopeConfiguration.class}) public class RewriteParserConfiguration { @@ -56,6 +58,7 @@ public class RewriteParserConfiguration { private ParserProperties parserProperties; @Bean + @Lazy MavenPlexusContainer plexusContainer() { return new MavenPlexusContainer(); } 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 035903e6d..34ed8895d 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 @@ -135,7 +135,9 @@ public RewriteProjectParsingResult parse(Path givenBaseDir, List resou AtomicReference atomicReference = new AtomicReference<>(); withMavenSession(baseDir, mavenSession -> { + // Get the ordered list of projects List sortedProjectsList = mavenSession.getProjectDependencyGraph().getSortedProjects(); + // SortedProjects makes downstream components independent of Maven classes SortedProjects mavenInfos = new SortedProjects(resources, sortedProjectsList, List.of("default")); // List sortedBuildFileResources = buildFileParser.filterAndSortBuildFiles(resources); @@ -150,6 +152,7 @@ public RewriteProjectParsingResult parse(Path givenBaseDir, List resou .map(r -> resourceToDocumentMap.get(ResourceUtil.getPath(r))) .map(SourceFile.class::cast) .toList(); + // 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,7 +176,9 @@ private void clearScanScopedBeans() { } private void withMavenSession(Path baseDir, Consumer consumer) { - mavenExecutor.onProjectSucceededEvent(baseDir, List.of("clean", "install"), event -> consumer.accept(event.getSession())); + List goals = List.of("clean", "install"); + log.debug("Successfully finished goals %s".formatted(goals)); + mavenExecutor.onProjectSucceededEvent(baseDir, goals, event -> consumer.accept(event.getSession())); } @org.jetbrains.annotations.Nullable 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 7f1b148ff..046b580db 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 @@ -45,66 +45,66 @@ public void debug(CharSequence charSequence, Throwable throwable) { @Override public void debug(Throwable throwable) { - + log.debug("", throwable); } @Override public boolean isInfoEnabled() { - return false; + return log.isInfoEnabled(); } @Override public void info(CharSequence charSequence) { - + log.info(charSequence.toString()); } @Override public void info(CharSequence charSequence, Throwable throwable) { - + log.info(charSequence.toString(), throwable); } @Override public void info(Throwable throwable) { - + log.info("", throwable); } @Override public boolean isWarnEnabled() { - return false; + return log.isWarnEnabled(); } @Override public void warn(CharSequence charSequence) { - + log.warn(charSequence.toString()); } @Override public void warn(CharSequence charSequence, Throwable throwable) { - + log.warn(charSequence.toString(), throwable); } @Override public void warn(Throwable throwable) { - + log.warn("", throwable); } @Override public boolean isErrorEnabled() { - return false; + return log.isErrorEnabled(); } @Override public void error(CharSequence charSequence) { - + log.error(charSequence.toString()); } @Override public void error(CharSequence charSequence, Throwable throwable) { - + log.error(charSequence.toString(), throwable); } @Override public void error(Throwable throwable) { - + log.error("", throwable); } } 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 26c6c6dcc..18193ce86 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 @@ -57,7 +57,7 @@ public List parseOtherSourceFiles( List styles, ExecutionContext executionContext) { - List parsedSourceFiles = new ArrayList<>(); + Set parsedSourceFiles = new LinkedHashSet<>(); mavenProject.getSortedProjects().forEach(currentMavenProject -> { Resource moduleBuildFileResource = mavenProject.getMatchingBuildFileResource(currentMavenProject); @@ -70,7 +70,7 @@ public List parseOtherSourceFiles( parsedSourceFiles.addAll(sourceFiles); }); - return parsedSourceFiles; + return new ArrayList<>(parsedSourceFiles); } /** @@ -99,6 +99,7 @@ private List parseModuleSourceFiles( .logCompilationWarningsAndErrors(false); Path buildFilePath = mavenProject.getBasedir().toPath().resolve(moduleBuildFile.getSourcePath()); + // these paths will be ignored by ResourceParser Set pathsToOtherModules = pathsToOtherMavenProjects(mavenProject, buildFilePath); ResourceParser rp = new ResourceParser( baseDir, @@ -116,6 +117,7 @@ private List parseModuleSourceFiles( List mainSources = parseMainSources(baseDir, mavenProject, moduleBuildFile, javaParserBuilder.clone(), rp, provenanceMarkers, alreadyParsed, executionContext); List testSources = parseTestSources(baseDir, mavenProject, moduleBuildFile, javaParserBuilder.clone(), rp, provenanceMarkers, alreadyParsed, executionContext); + alreadyParsed.addAll(pathsToOtherModules); // 171:175 Stream parsedResourceFiles = rp.parse(baseDir.resolve(moduleBuildFile.getSourcePath()).getParent(), alreadyParsed ) // FIXME: handle generated sources diff --git a/sbm-support-rewrite/src/main/java/org/springframework/sbm/scopes/AbstractBaseScope.java b/sbm-support-rewrite/src/main/java/org/springframework/sbm/scopes/AbstractBaseScope.java index f902c4502..5bf7be5b4 100644 --- a/sbm-support-rewrite/src/main/java/org/springframework/sbm/scopes/AbstractBaseScope.java +++ b/sbm-support-rewrite/src/main/java/org/springframework/sbm/scopes/AbstractBaseScope.java @@ -32,7 +32,11 @@ public class AbstractBaseScope implements Scope { private final Map scopedBeans = new ConcurrentHashMap<>(); public void clear(ConfigurableListableBeanFactory beanFactory) { - scopedBeans.keySet().stream().forEach(beanName -> beanFactory.destroyScopedBean(beanName)); + log.trace("Clearing %d beans from scope %s.".formatted(scopedBeans.keySet().size(), this.getClass().getName())); + scopedBeans.keySet().stream().forEach(beanName -> { + beanFactory.destroyScopedBean(beanName); + log.trace("Removed bean '%s' from scan scope.".formatted(beanName)); + }); } public Object get(String name, ObjectFactory objectFactory) { diff --git a/sbm-support-rewrite/src/main/resources/META-INF/sbm-support-rewrite.properties b/sbm-support-rewrite/src/main/resources/META-INF/sbm-support-rewrite.properties index 40b3150db..0d564fd91 100644 --- a/sbm-support-rewrite/src/main/resources/META-INF/sbm-support-rewrite.properties +++ b/sbm-support-rewrite/src/main/resources/META-INF/sbm-support-rewrite.properties @@ -27,4 +27,4 @@ parser.sizeThresholdMb=10 parser.runPerSubmodule=false parser.failOnInvalidActiveRecipes=true parser.activeProfiles=default -parser.ignoredPathPatterns=**.idea,**.git +parser.ignoredPathPatterns=**.idea,**.git,**/target/**,target/** diff --git a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/ParserPropertiesTest.java b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/ParserPropertiesTest.java index 66ee33e6d..c79d570f0 100644 --- a/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/ParserPropertiesTest.java +++ b/sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/ParserPropertiesTest.java @@ -36,57 +36,57 @@ public class GivenDefaultProperties { @Test @DisplayName("parser.pomCacheEnabled") - void validPomCacheEnabled() { + void defaultPomCacheEnabled() { assertThat(parserProperties.isPomCacheEnabled()).isFalse(); } @Test @DisplayName("parser.pomCacheDirectory") - void validPomCacheDirectory() { + void defaultPomCacheDirectory() { assertThat(parserProperties.getPomCacheDirectory()).isEqualTo("~/.rewrite-cache"); } @Test @DisplayName("parser.skipMavenParsing") - void validSkipMavenParsing() { + void defaultSkipMavenParsing() { assertThat(parserProperties.isSkipMavenParsing()).isFalse(); } @Test @DisplayName("parser.plainTextMasks") - void validPlainTextMasks() { + void defaultPlainTextMasks() { assertThat(parserProperties.getPlainTextMasks()).containsExactlyInAnyOrder("*.txt"); } @Test @DisplayName("parser.sizeThresholdMb") - void validSizeThresholdMb() { + void defaultSizeThresholdMb() { assertThat(parserProperties.getSizeThresholdMb()).isEqualTo(10); } @Test @DisplayName("parser.runPerSubmodule") - void validRunPerSubmodule() { + void defaultRunPerSubmodule() { assertThat(parserProperties.isRunPerSubmodule()).isFalse(); } @Test @DisplayName("parser.failOnInvalidActiveRecipes") - void validFailOnInvalidActiveRecipes() { + void defaultFailOnInvalidActiveRecipes() { assertThat(parserProperties.isFailOnInvalidActiveRecipes()).isTrue(); } @Test @DisplayName("parser.activeProfiles") - void validActiveProfiles() { + void defaultActiveProfiles() { assertThat(parserProperties.getActiveProfiles()).containsExactlyInAnyOrder("default"); } @Test @DisplayName("parser.ignoredPathPatterns") - void validIgnoredPathPatterns() { - assertThat(parserProperties.getIgnoredPathPatterns()).containsExactlyInAnyOrder("**.idea","**.git"); + void defaultIgnoredPathPatterns() { + assertThat(parserProperties.getIgnoredPathPatterns()).containsExactlyInAnyOrder("target/**", "**.git", "**/target/**", "**.idea"); } } 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 006f4ca79..b8111777e 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,8 +22,11 @@ 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.ProjectScanner; + import org.springframework.sbm.parsers.RewriteProjectParser; + import org.springframework.sbm.parsers.RewriteProjectParsingResult; -import java.nio.file.Path; + import java.nio.file.Path; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; @@ -50,6 +53,18 @@ void parseCheckstyle() { assertThat(parsingResult.sourceFiles().stream().map(sf -> sf.getSourcePath().toString()).toList()).contains("checkstyle/suppressions.xml"); } + @Test + @DisplayName("parse4Modules") + void parse4Modules() { + Path baseDir = getMavenProject("4-modules"); + List resources = projectScanner.scan(baseDir); + + assertThat(resources).hasSize(4); + + RewriteProjectParsingResult parsingResult = sut.parse(baseDir, resources, new InMemoryExecutionContext(t -> {throw new RuntimeException(t);})); + assertThat(parsingResult.sourceFiles()).hasSize(4); + } + private Path getMavenProject(String s) { return Path.of("./testcode/maven-projects/").resolve(s).toAbsolutePath().normalize(); }