diff --git a/pom.xml b/pom.xml
index 4092d5b..7a00c97 100644
--- a/pom.xml
+++ b/pom.xml
@@ -17,7 +17,7 @@
spring-rewrite-commons-examples
spring-rewrite-commons-starters
spring-rewrite-commons-gradle
- spring-rewrite-commons-maven-invoker
+ spring-rewrite-commons-plugin-invoker
@@ -37,13 +37,15 @@
1.8.11
5.20.0
2.3.1
+ 8.4
+ 3.9.1
+ 3.2.0
+ 3.4.2
- 3.9.1
1.9.13
3.5.3
1.8
- 3.2.0
2.1.0
@@ -117,6 +119,16 @@
${junit-pioneer.version}
test
+
+ org.gradle
+ gradle-tooling-api
+ ${gradle-tooling-api.version}
+
+
+ org.openrewrite
+ rewrite-core
+ ${rewrite.version}
+
diff --git a/spring-rewrite-commons-docs/src/main/antora/modules/ROOT/pages/index.adoc b/spring-rewrite-commons-docs/src/main/antora/modules/ROOT/pages/index.adoc
index a601980..05c7427 100644
--- a/spring-rewrite-commons-docs/src/main/antora/modules/ROOT/pages/index.adoc
+++ b/spring-rewrite-commons-docs/src/main/antora/modules/ROOT/pages/index.adoc
@@ -9,16 +9,15 @@ Fabian Krüger
== Overview
Spring Rewrite Commons provides abstractions and parsers for https://github.com/openrewrite/[OpenRewrite].
-The project can parse Java projects using Maven and apply OpenRewrite recipes without the need of a build tool plugin.
-It aims to become the foundation for Spring Boot applications using OpenRewrite.
-https://github.com/openrewrite/[OpenRewrite] is a code refactoring, remediation, and modernization automation tool providing a rich https://docs.openrewrite.org/recipes[catalog of recipes] for tasks like automated code transformations.
+https://github.com/openrewrite/[OpenRewrite] is a code refactoring, remediation, and modernization automation tool providing a rich https://docs.openrewrite.org/recipes[catalog of recipes] for task like automated code transformations.
These are the main components offered by Spring Rewrite Commons:
-* `xref:concepts.adoc#_rewriteprojectparser[RewriteProjectParser]` - Parse a project to an OpenRewrite https://docs.openrewrite.org/concepts-explanations/lossless-semantic-trees[Lossless Semantic Tree] (LST).
-* `xref:concepts.adoc#_recipediscovery[RewriteRecipeDiscovery]` - Discover recipes on the classpath.
+* `xref:concepts.adoc#:_plugininvoker[RewritePlugin]` - Helper to execute OpenRewrite's Gradle or Maven plugin through Java
+* `xref:concepts.adoc#_rewriteprojectparser[RewriteProjectParser]` - Parse a project to an OpenRewrite https://docs.openrewrite.org/concepts-explanations/lossless-semantic-trees[LST] outside a build tool plugin.
* `xref:concepts.adoc#_projectresourceset[ProjectResourceSet]` - Encapsulates the LST to run https://github.com/openrewrite/[OpenRewrite] recipes sequentially.
+* `xref:concepts.adoc#_recipediscovery[RewriteRecipeDiscovery]` - Discover recipes on the classpath.
* `xref:concepts.adoc#_projectresourcesetserializer[ProjectResourceSetSerializer]` - Serialize the current state of the `ProjectResourceSet` to the filesystem.
* Some helpers for xref:testing.adoc[testíng] also exist
diff --git a/spring-rewrite-commons-launcher/pom.xml b/spring-rewrite-commons-launcher/pom.xml
index 654ab74..b1ceb08 100644
--- a/spring-rewrite-commons-launcher/pom.xml
+++ b/spring-rewrite-commons-launcher/pom.xml
@@ -149,6 +149,18 @@
${maven-invoker.version}
test
+
+
+ org.springframework.rewrite
+ spring-rewrite-commons-plugin-invoker-maven
+ 0.1.0-SNAPSHOT
+
+
+ org.springframework.rewrite
+ spring-rewrite-commons-plugin-invoker-gradle
+ 0.1.0-SNAPSHOT
+
+
org.springframework.boot
spring-boot-starter-test
diff --git a/spring-rewrite-commons-maven-invoker/src/main/java/org/springframework/rewrite/maven/MavenInvocationRewriteRecipeLauncher.java b/spring-rewrite-commons-maven-invoker/src/main/java/org/springframework/rewrite/maven/MavenInvocationRewriteRecipeLauncher.java
deleted file mode 100644
index 2283dfc..0000000
--- a/spring-rewrite-commons-maven-invoker/src/main/java/org/springframework/rewrite/maven/MavenInvocationRewriteRecipeLauncher.java
+++ /dev/null
@@ -1,379 +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.rewrite.maven;
-
-import org.apache.maven.shared.invoker.*;
-
-import javax.swing.text.html.Option;
-import java.io.File;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.function.Consumer;
-import java.util.stream.Collectors;
-
-/**
- * Executes OpenRewrite recipes by invoking local Maven installation. It requires
- * MAVEN_HOME or M2_HOME to be set!
- *
- * @author Fabian Krüger
- */
-public class MavenInvocationRewriteRecipeLauncher {
-
- private MavenInvocationRequestFactory mavenInvocationRequestFactory = new MavenInvocationRequestFactory();
-
- // private Invoker invoker = new DefaultInvoker();
-
- public static Builders.OnDirBuilder applyRecipes(String... recipeNames) {
- MavenInvokerRewriteRecipeLauncherBuilder builders = new MavenInvokerRewriteRecipeLauncherBuilder();
- return builders.applyRecipes(recipeNames);
- }
-
- public static Builders.OnDirBuilder applyRecipes(List recipeNames) {
- MavenInvokerRewriteRecipeLauncherBuilder builders = new MavenInvokerRewriteRecipeLauncherBuilder();
- return builders.applyRecipes(recipeNames);
- }
-
- private InvocationResult invokeRewritePlugin(Invoker invoker, Path baseDir, List recipeNames,
- List dependencies, DebugConfig debugConfig, BuildConfig buildConfig, Consumer lineConsumer,
- RewritePluginGoals rewritePluginGoals) {
- validateBaseDir(baseDir);
-
- if (recipeNames.isEmpty()) {
- throw new IllegalArgumentException("No recipe names provided.");
- }
-
- String openRewriteCommand = renderOpenRewriteCommand(recipeNames, dependencies, rewritePluginGoals);
- return invokeMaven(invoker, baseDir, debugConfig, buildConfig, lineConsumer, openRewriteCommand);
- }
-
- public InvocationResult invokeRewritePlugin(Path baseDir, List recipeNames, List dependencies,
- DebugConfig debugConfig, BuildConfig buildConfig, Consumer lineConsumer,
- RewritePluginGoals rewritePluginGoals) {
-
- validateBaseDir(baseDir);
-
- if (recipeNames.isEmpty()) {
- throw new IllegalArgumentException("No recipe names provided.");
- }
-
- String openRewriteCommand = renderOpenRewriteCommand(recipeNames, dependencies, rewritePluginGoals);
- return invokeMaven(new DefaultInvoker(), baseDir, debugConfig, buildConfig, lineConsumer, openRewriteCommand);
- }
-
- private void validateBaseDir(Path baseDir) {
- if (baseDir == null) {
- throw new IllegalArgumentException("Given baseDir was null.");
- }
- else if (!Files.exists(baseDir)) {
- throw new IllegalArgumentException("Given baseDir '%s' does not exist.".formatted(baseDir));
- }
- }
-
- private InvocationResult invokeMaven(Invoker invoker, Path baseDir, DebugConfig debugConfig,
- BuildConfig buildConfig, Consumer lineConsumer, String openRewriteCommand) {
- List goals = new ArrayList<>();
- goals.add("clean");
- goals.add("package");
- goals.add("--fail-at-end");
- goals.add(openRewriteCommand);
-
- InvocationRequest request = mavenInvocationRequestFactory.createMavenInvocationRequest(baseDir, debugConfig,
- buildConfig, goals, lineConsumer);
-
- try {
- return invoker.execute(request);
- }
- catch (MavenInvocationException e) {
- throw new RuntimeException(e);
- }
- }
-
- // public static InvocationResult invokeMaven(Path baseDir, BuildConfig buildConfig,
- // DebugConfig debugConfig,
- // Consumer lineConsumer, List providedGoals) {
- // List goals = new ArrayList<>(providedGoals);
- //
- // InvocationRequest mavenInvocationRequest = new
- // MavenInvocationRequestFactory().createMavenInvocationRequest(baseDir, debugConfig,
- // buildConfig, providedGoals, lineConsumer);
- //
- // String mavenHome = System.getenv("MAVEN_HOME");
- // if (mavenHome == null) {
- // mavenHome = System.getenv("M2_HOME");
- // if (mavenHome == null) {
- // throw new IllegalStateException(
- // "MAVEN_HOME or M2_HOME must be set but System.getenv(\"MAVEN_HOME\") and
- // System.getenv(\"M2_HOME\") returned null.");
- // }
- // }
- //
- // if (buildConfig.isSkipTests()) {
- // goals.add("-DskipTests");
- // }
- //
- // Invoker invoker = new DefaultInvoker();
- // InvocationRequest request = new DefaultInvocationRequest();
- // request.setGoals(goals);
- // request.setBatchMode(true);
- // request.setMavenHome(new File(mavenHome));
- // request.setBaseDirectory(baseDir.toFile());
- // request.setOutputHandler(s -> lineConsumer.accept(s));
- //
- // StringBuilder mavenOpts = new StringBuilder();
- // mavenOpts.append("-Xms1G -Xmx6G ");
- // if (debugConfig != null && debugConfig.isDebugEnabled()) {
- // mavenOpts.append(" -Xdebug
- // -Xrunjdwp:transport=dt_socket,server=y,suspend=%s,address=%s "
- // .formatted(debugConfig.isSuspend(), debugConfig.getPort()));
- // }
- // request.setMavenOpts(mavenOpts.toString());
- //
- // try {
- // InvocationResult result = invoker.execute(request);
- // return result;
- // }
- // catch (MavenInvocationException e) {
- // throw new RuntimeException(e);
- // }
- // }
-
- private static String renderOpenRewriteCommand(List recipeNames, List dependencies,
- RewritePluginGoals rewritePluginGoal) {
- StringBuilder sb = new StringBuilder();
- sb.append("org.openrewrite.maven:rewrite-maven-plugin:").append(rewritePluginGoal.getGoalName()).append(" ");
- String recipesList = recipeNames.stream().collect(Collectors.joining(","));
- sb.append("-Drewrite.activeRecipes=").append(recipesList);
- if (!dependencies.isEmpty()) {
- String dependenciesList = dependencies.stream().collect(Collectors.joining(","));
- sb.append(" ").append("-Drewrite.recipeArtifactCoordinates=").append(dependenciesList);
- }
- return sb.toString();
- }
-
- public class Builders {
-
- public interface StartBuilder {
-
- OnDirBuilder applyRecipes(String... recipeNames);
-
- OnDirBuilder applyRecipes(List recipeNames);
-
- }
-
- public interface OnDirBuilder {
-
- OptionalBuilder onDir(Path baseDir);
-
- }
-
- public interface OptionalBuilder {
-
- OptionalBuilder withDebugConfig(DebugConfig debugConfig);
-
- OptionalBuilder withDependencies(String... dependencyGavs);
-
- OptionalBuilder withDependencies(List dependencyGavs);
-
- OptionalBuilder withBuildConfig(BuildConfig buildConfig);
-
- OptionalBuilder withOutputListener(Consumer outputListener);
-
- OptionalBuilder withInvoker(Invoker invoker);
-
- InvocationResult run();
-
- InvocationResult runNoFork();
-
- InvocationResult dryRun();
-
- InvocationResult dryRunNoFork();
-
- InvocationResult discover();
-
- InvocationResult cyclonedx();
-
- }
-
- }
-
- public static class MavenInvokerRewriteRecipeLauncherBuilder
- implements Builders.StartBuilder, Builders.OnDirBuilder, Builders.OptionalBuilder {
-
- private Path baseDir;
-
- private List recipes = new ArrayList<>();
-
- private List dependencies = new ArrayList<>();
-
- private BuildConfig buildConfig = BuildConfig.defaultConfig();
-
- private DebugConfig debugConfig = DebugConfig.disabled();
-
- private Consumer outputListener = line -> System.out.println(line);
-
- private Invoker invoker = new DefaultInvoker();
-
- public Builders.OptionalBuilder onDir(String baseDir) {
- this.baseDir = Path.of(baseDir).toAbsolutePath().normalize();
- return this;
- }
-
- @Override
- public Builders.OnDirBuilder applyRecipes(String... recipeNames) {
- validateRecipeNames(Arrays.asList(recipeNames));
- return this.applyRecipes(Arrays.asList(recipeNames));
- }
-
- @Override
- public Builders.OnDirBuilder applyRecipes(List recipeNames) {
- validateRecipeNames(recipeNames);
- this.recipes = recipeNames;
- return this;
- }
-
- @Override
- public Builders.OptionalBuilder onDir(Path baseDir) {
- this.baseDir = baseDir.toAbsolutePath().normalize();
- return this;
- }
-
- @Override
- public Builders.OptionalBuilder withOutputListener(Consumer outputListener) {
- this.outputListener = outputListener;
- return this;
- }
-
- @Override
- public Builders.OptionalBuilder withInvoker(Invoker invoker) {
- this.invoker = invoker;
- return this;
- }
-
- /**
- * mvn rewrite:run - RunBuilder the configured recipes and apply the changes
- * locally.
- */
- @Override
- public InvocationResult run() {
- return executeRewriteGoal(invoker, baseDir, recipes, dependencies, debugConfig, buildConfig, outputListener,
- RewritePluginGoals.RUN);
- }
-
- /**
- * mvn rewrite:runNoFork - RunBuilder the configured recipes and apply the changes
- * locally. This variant does not fork the Maven life cycle and can be a more
- * efficient choice when using Rewrite within a CI workflow when combined with
- * other Maven goals.
- */
- @Override
- public InvocationResult runNoFork() {
- return executeRewriteGoal(invoker, baseDir, recipes, dependencies, debugConfig, buildConfig, outputListener,
- RewritePluginGoals.RUN_NO_FORK);
- }
-
- /**
- * mvn rewrite:dryRun - Generate warnings to the console for any recipe that would
- * make changes and generates a diff file in each maven modules' target folder.
- */
- @Override
- public InvocationResult dryRun() {
- return executeRewriteGoal(invoker, baseDir, recipes, dependencies, debugConfig, buildConfig, outputListener,
- RewritePluginGoals.DRY_RUN);
- }
-
- /**
- * mvn rewrite:dryRunNoFork - Generate warnings to the console for any recipe that
- * would make changes and generates a diff file in each maven modules' target
- * folder. This variant does not fork the Maven life cycle and can be a more
- * efficient choice when using Rewrite within a CI workflow when combined with
- * other Maven goals.
- */
- @Override
- public InvocationResult dryRunNoFork() {
- return executeRewriteGoal(invoker, baseDir, recipes, dependencies, debugConfig, buildConfig, outputListener,
- RewritePluginGoals.DRY_RUN_NO_FORK);
- }
-
- /**
- * mvn rewrite:discover - Generate a report of available recipes found on the
- * classpath.
- */
- @Override
- public InvocationResult discover() {
- return executeRewriteGoal(invoker, baseDir, recipes, dependencies, debugConfig, buildConfig, outputListener,
- RewritePluginGoals.DISCOVER);
- }
-
- /**
- * mvn rewrite:cyclonedx - Generate a CycloneDx bill of materials outlining the
- * project's dependencies, including transitive dependencies.
- *
- * @see CycloneDx
- */
- @Override
- public InvocationResult cyclonedx() {
- return executeRewriteGoal(invoker, baseDir, recipes, dependencies, debugConfig, buildConfig, outputListener,
- RewritePluginGoals.CYCLONEDX);
- }
-
- private InvocationResult executeRewriteGoal(Invoker invoker, Path baseDir, List recipeNames,
- List dependencies, DebugConfig debugConfig, BuildConfig buildConfig,
- Consumer lineConsumer, RewritePluginGoals rewritePluginGoals) {
- MavenInvocationRewriteRecipeLauncher launcher = new MavenInvocationRewriteRecipeLauncher();
- InvocationResult result = launcher.invokeRewritePlugin(invoker, baseDir, recipeNames, dependencies,
- debugConfig, buildConfig, lineConsumer, rewritePluginGoals);
- return result;
- }
-
- private void validateRecipeNames(List recipeNames) {
- if (recipeNames.isEmpty()) {
- throw new IllegalArgumentException("At least one recipe name must be provided.");
- }
-
- if (recipeNames.stream().anyMatch(String::isBlank)) {
- throw new IllegalArgumentException("At least one recipe name was blank.");
- }
- }
-
- @Override
- public Builders.OptionalBuilder withDependencies(String... dependencyGavs) {
- return withDependencies(Arrays.asList(dependencyGavs));
- }
-
- @Override
- public Builders.OptionalBuilder withDependencies(List dependencyGavs) {
- this.dependencies = dependencyGavs;
- return this;
- }
-
- @Override
- public Builders.OptionalBuilder withBuildConfig(BuildConfig buildConfig) {
- this.buildConfig = buildConfig;
- return this;
- }
-
- @Override
- public Builders.OptionalBuilder withDebugConfig(DebugConfig debugConfig) {
- this.debugConfig = debugConfig;
- return this;
- }
-
- }
-
-}
diff --git a/spring-rewrite-commons-maven-invoker/src/test/java/org/springframework/rewrite/maven/MavenInvocationRewriteRecipeLauncherIntegrationTest.java b/spring-rewrite-commons-maven-invoker/src/test/java/org/springframework/rewrite/maven/MavenInvocationRewriteRecipeLauncherIntegrationTest.java
deleted file mode 100644
index 0e6c74d..0000000
--- a/spring-rewrite-commons-maven-invoker/src/test/java/org/springframework/rewrite/maven/MavenInvocationRewriteRecipeLauncherIntegrationTest.java
+++ /dev/null
@@ -1,156 +0,0 @@
-package org.springframework.rewrite.maven;
-
-/*
- * 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.
- */
-
-import org.apache.maven.shared.invoker.*;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.io.TempDir;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.function.Consumer;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.mockito.Mockito.*;
-
-/**
- * @author Fabian Krüger
- */
-class MavenInvocationRewriteRecipeLauncherIntegrationTest {
-
- @Mock
- private Path baseDir = Path.of("./testcode/maven-projects/simple").toAbsolutePath().normalize();
-
- @Test
- @DisplayName("invokeRewritePlugin() method test")
- void invokeRewritePluginMethodTest() {
- List capturedLines = new ArrayList<>();
- MavenInvocationRewriteRecipeLauncher sut = new MavenInvocationRewriteRecipeLauncher();
- sut.invokeRewritePlugin(Path.of("./testcode/maven-projects/simple"),
- List.of("org.openrewrite.java.RemoveUnusedImports"), new ArrayList<>(), DebugConfig.from(9090, false),
- BuildConfig.builder().skipTests(true).withMemory("64M", "256M").build(), capturedLines::add,
- RewritePluginGoals.DRY_RUN);
- assertThat(capturedLines).contains("Listening for transport dt_socket at address: 9090",
- "[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ simple ---", "[INFO] Tests are skipped.",
- "[INFO] Using active recipe(s) [org.openrewrite.java.RemoveUnusedImports]",
- "[INFO] Using active styles(s) []", "[INFO] BUILD SUCCESS");
- }
-
- @Test
- @DisplayName("mavenInvocationRequestBuilder success")
- void mavenInvoker() {
- List capturedLines = new ArrayList<>();
- Path baseDir = Path.of("./testcode/maven-projects/simple").toAbsolutePath().normalize();
-
- InvocationResult result = MavenInvocationRewriteRecipeLauncher
- .applyRecipes("org.openrewrite.java.RemoveUnusedImports", "org.openrewrite.java.format.AutoFormat")
- .onDir(baseDir)
- .withOutputListener(capturedLines::add)
- .dryRun();
-
- assertThat(result.getExitCode()).isEqualTo(0);
- assertThat(capturedLines).contains("[INFO] Scanning for projects...",
- "[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ simple ---",
- "[INFO] Using active recipe(s) [org.openrewrite.java.RemoveUnusedImports, org.openrewrite.java.format.AutoFormat]",
- "[INFO] BUILD SUCCESS");
- }
-
- @Test
- @DisplayName("with debug enabled")
- void withDebugEnabled() {
- List capturedLines = new ArrayList<>();
-
- InvocationResult result = MavenInvocationRewriteRecipeLauncher
- .applyRecipes("org.openrewrite.java.RemoveUnusedImports")
- .onDir(Path.of("./testcode/maven-projects/simple").toAbsolutePath().normalize())
- .withOutputListener(capturedLines::add)
- .withDebugConfig(DebugConfig.fromDefault())
- .withBuildConfig(BuildConfig.builder().withMemory("1G", "6G").build())
- .run();
- assertThat(capturedLines).contains("Listening for transport dt_socket at address: 5005");
- assertThat(result.getExitCode()).isEqualTo(0);
- }
-
- @Test
- @DisplayName("cyclonedx")
- void cyclonedx() {
- List lines = new ArrayList<>();
- MavenInvocationRewriteRecipeLauncher.Builders.OptionalBuilder builder = getBuilder(lines);
- InvocationResult result = builder.cyclonedx();
- assertThat(result.getExitCode()).isEqualTo(0);
- assertThat(lines.stream().anyMatch(l -> l.endsWith(":cyclonedx (default-cli) @ simple ---"))).isTrue();
- assertThat(baseDir.resolve("target/simple-0.1.0-SNAPSHOT-cyclonedx.xml")).exists();
- }
-
- @Test
- @DisplayName("dryRun")
- void dryRun() {
- List lines = new ArrayList<>();
- MavenInvocationRewriteRecipeLauncher.Builders.OptionalBuilder builder = getBuilder(lines);
- InvocationResult result = builder.dryRun();
- assertThat(result.getExitCode()).isEqualTo(0);
- assertThat(lines.stream().anyMatch(l -> l.endsWith(":dryRun (default-cli) @ simple ---"))).isTrue();
- }
-
- @Test
- @DisplayName("dryRunNoFork")
- void dryRunNoFork() {
- List lines = new ArrayList<>();
- MavenInvocationRewriteRecipeLauncher.Builders.OptionalBuilder builder = getBuilder(lines);
- InvocationResult result = builder.dryRunNoFork();
- assertThat(result.getExitCode()).isEqualTo(0);
- assertThat(lines.stream().anyMatch(l -> l.endsWith(":dryRunNoFork (default-cli) @ simple ---"))).isTrue();
- }
-
- @Test
- @DisplayName("runNoFork")
- void runNoFork() {
- List lines = new ArrayList<>();
- MavenInvocationRewriteRecipeLauncher.Builders.OptionalBuilder builder = getBuilder(lines);
- InvocationResult result = builder.dryRunNoFork();
- assertThat(result.getExitCode()).isEqualTo(0);
- assertThat(lines.stream().anyMatch(l -> l.endsWith(":dryRunNoFork (default-cli) @ simple ---"))).isTrue();
- }
-
- @Test
- @DisplayName("discover")
- void discover() {
- List lines = new ArrayList<>();
- MavenInvocationRewriteRecipeLauncher.Builders.OptionalBuilder builder = getBuilder(lines);
- InvocationResult result = builder.discover();
- assertThat(result.getExitCode()).isEqualTo(0);
- assertThat(lines).contains("[INFO] Available Recipes:", "[INFO] org.openrewrite.FindSourceFiles");
- assertThat(lines.stream().anyMatch(l -> l.endsWith(":discover (default-cli) @ simple ---"))).isTrue();
- }
-
- private static MavenInvocationRewriteRecipeLauncher.Builders.OptionalBuilder getBuilder(List lines) {
- Path baseDir = Path.of("./testcode/maven-projects/simple").toAbsolutePath().normalize();
- MavenInvocationRewriteRecipeLauncher.Builders.OptionalBuilder builder = MavenInvocationRewriteRecipeLauncher
- .applyRecipes("org.openrewrite.java.RemoveUnusedImports")
- .onDir(baseDir)
- .withOutputListener(lines::add);
- return builder;
- }
-
-}
\ No newline at end of file
diff --git a/spring-rewrite-commons-maven-invoker/src/test/java/org/springframework/rewrite/maven/MavenInvocationRewriteRecipeLauncherTest.java b/spring-rewrite-commons-maven-invoker/src/test/java/org/springframework/rewrite/maven/MavenInvocationRewriteRecipeLauncherTest.java
deleted file mode 100644
index 72546cb..0000000
--- a/spring-rewrite-commons-maven-invoker/src/test/java/org/springframework/rewrite/maven/MavenInvocationRewriteRecipeLauncherTest.java
+++ /dev/null
@@ -1,192 +0,0 @@
-package org.springframework.rewrite.maven;
-
-/*
- * 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.
- */
-
-import org.apache.maven.shared.invoker.*;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.io.TempDir;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.springframework.test.util.ReflectionTestUtils;
-
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.function.Consumer;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.mockito.Mockito.*;
-
-/**
- * @author Fabian Krüger
- */
-class MavenInvocationRewriteRecipeLauncherTest {
-
- private static final int SUCCESS = 0;
-
- private MavenInvocationRewriteRecipeLauncher.Builders.OptionalBuilder invokerBuilder;
-
- @Mock
- Invoker mavenInvoker = mock(Invoker.class);
-
- private Path baseDir = Path.of("./testcode/maven-projects/simple").toAbsolutePath().normalize();
-
- private List capturedLines = new ArrayList<>();
-
- private Consumer outputListener = capturedLines::add;
-
- @BeforeEach
- void beforeEach() throws MavenInvocationException {
- outputListener = capturedLines::add;
- invokerBuilder = MavenInvocationRewriteRecipeLauncher
- .applyRecipes("org.openrewrite.java.RemoveUnusedImports", "org.openrewrite.java.format.AutoFormat")
- .onDir(baseDir)
- .withInvoker(mavenInvoker)
- .withOutputListener(outputListener);
-
- InvocationResult result = new DummyInvocationResult();
- when(mavenInvoker.execute(any(InvocationRequest.class))).thenReturn(result);
- }
-
- @Test
- @DisplayName("minimal")
- void minimal() throws MavenInvocationException {
- InvocationResult actualResult = invokerBuilder.run();
-
- assertThat(actualResult.getExitCode()).isEqualTo(0);
- String[] expectedGoals = { "clean", "package", "--fail-at-end",
- "org.openrewrite.maven:rewrite-maven-plugin:run -Drewrite.activeRecipes=org.openrewrite.java.RemoveUnusedImports,org.openrewrite.java.format.AutoFormat" };
- verifyCallToMaven(expectedGoals);
- }
-
- @Test
- @DisplayName("with dependencies")
- void withDependencies() throws MavenInvocationException {
- InvocationResult actualResult = invokerBuilder
- .withDependencies("com.example:some-dep:1.0.0", "com.example:another-dep:1.0.0")
- .run();
- assertThat(actualResult.getExitCode()).isEqualTo(0);
- String[] expectedGoals = { "clean", "package", "--fail-at-end",
- "org.openrewrite.maven:rewrite-maven-plugin:run -Drewrite.activeRecipes=org.openrewrite.java.RemoveUnusedImports,org.openrewrite.java.format.AutoFormat -Drewrite.recipeArtifactCoordinates=com.example:some-dep:1.0.0,com.example:another-dep:1.0.0" };
- verifyCallToMaven(expectedGoals);
- }
-
- @Test
- @DisplayName("with build tools config")
- void withBuildToolConfig() throws MavenInvocationException {
-
- InvocationResult actualResult = invokerBuilder
- .withBuildConfig(BuildConfig.builder().withMemory("64M", "256M").skipTests(true).build())
- .run();
- assertThat(actualResult.getExitCode()).isEqualTo(0);
- String[] expectedGoals = { "clean", "package", "--fail-at-end",
- "org.openrewrite.maven:rewrite-maven-plugin:run -Drewrite.activeRecipes=org.openrewrite.java.RemoveUnusedImports,org.openrewrite.java.format.AutoFormat" };
- verifyCallToMaven(expectedGoals, BuildConfig.builder().withMemory("64M", "256M").skipTests(true).build());
- }
-
- @Test
- @DisplayName("builder")
- void builder(@TempDir Path tempDir) {
- InvocationResult result = MavenInvocationRewriteRecipeLauncher.applyRecipes("recipe1").onDir(tempDir).run();
-
- MavenInvocationRewriteRecipeLauncher.applyRecipes("recipe1").onDir(tempDir).withDependencies("", "").run();
-
- MavenInvocationRewriteRecipeLauncher.applyRecipes(List.of("NoName")).onDir(tempDir).withDependencies("").run();
-
- // build tool config only
- MavenInvocationRewriteRecipeLauncher.applyRecipes(List.of("NoName"))
- .onDir(tempDir)
- .withDependencies("")
- .withBuildConfig(BuildConfig.defaultConfig())
- .run();
-
- // debug config only
- MavenInvocationRewriteRecipeLauncher.applyRecipes("NoName")
- .onDir(tempDir)
- .withDependencies("")
- .withDebugConfig(DebugConfig.disabled())
- .run();
-
- MavenInvocationRewriteRecipeLauncher.applyRecipes(List.of("NoName"))
- .onDir(tempDir)
- .withDependencies("")
- .withDebugConfig(DebugConfig.disabled())
- .dryRun();
-
- // build tool and debug config
- MavenInvocationRewriteRecipeLauncher.applyRecipes(List.of("NoName"))
- .onDir(tempDir)
- .withDependencies("")
- .withBuildConfig(BuildConfig.defaultConfig())
- .withDebugConfig(DebugConfig.disabled())
- .run();
-
- MavenInvocationRewriteRecipeLauncher.applyRecipes("NoName").onDir(tempDir).run();
- }
-
- @Test
- @DisplayName("missing recipeNames should throw exception")
- void missingRecipeNamesShouldThrowException() {
- assertThrows(IllegalArgumentException.class, () -> {
- MavenInvocationRewriteRecipeLauncher.applyRecipes("").onDir(Path.of("")).run();
- });
- }
-
- @Test
- @DisplayName("mavenInvocationRequestBuilder extra memory")
- void mavenInvokerExtraMemory() {
- List lines = new ArrayList<>();
- Path baseDir = Path.of("./testcode/maven-projects/simple").toAbsolutePath().normalize();
-
- InvocationResult result = MavenInvocationRewriteRecipeLauncher
- .applyRecipes("org.openrewrite.java.RemoveUnusedImports")
- .onDir(baseDir)
- .withBuildConfig(BuildConfig.builder().skipTests(false).withMemory("32M", "1G").build())
- .withOutputListener(lines::add)
- .dryRun();
-
- assertThat(result.getExitCode()).isEqualTo(SUCCESS);
- assertThat(lines).contains("[INFO] Scanning for projects...",
- "[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ simple ---", "[INFO] BUILD SUCCESS");
- }
-
- private void verifyCallToMaven(String[] expectedGoals) throws MavenInvocationException {
- BuildConfig buildConfig = BuildConfig.defaultConfig();
- verifyCallToMaven(expectedGoals, buildConfig, DebugConfig.disabled(), baseDir, outputListener,
- Arrays.asList(expectedGoals));
- }
-
- private void verifyCallToMaven(String[] expectedGoals, BuildConfig buildConfig) throws MavenInvocationException {
- verifyCallToMaven(expectedGoals, buildConfig, DebugConfig.disabled(), baseDir, outputListener,
- Arrays.asList(expectedGoals));
- }
-
- private void verifyCallToMaven(String[] expectedGoals, BuildConfig buildConfig, DebugConfig debugConfig,
- Path baseDir, Consumer lineConsumer, List givenGoals) throws MavenInvocationException {
- InvocationRequest mavenInvocationRequest = new MavenInvocationRequestFactory()
- .createMavenInvocationRequest(baseDir, debugConfig, buildConfig, givenGoals, lineConsumer);
- ArgumentCaptor captor = ArgumentCaptor.forClass(InvocationRequest.class);
- verify(mavenInvoker).execute(captor.capture());
- InvocationRequest request = captor.getValue();
- assertThat(request).usingRecursiveComparison().isEqualTo(mavenInvocationRequest);
- }
-
-}
\ No newline at end of file
diff --git a/spring-rewrite-commons-plugin-invoker/pom.xml b/spring-rewrite-commons-plugin-invoker/pom.xml
new file mode 100644
index 0000000..56cc8b6
--- /dev/null
+++ b/spring-rewrite-commons-plugin-invoker/pom.xml
@@ -0,0 +1,42 @@
+
+
+ 4.0.0
+
+ org.springframework.rewrite
+ spring-rewrite-commons
+ 0.1.0-SNAPSHOT
+
+
+ spring-rewrite-commons-plugin-invoker
+ pom
+
+
+ 17
+ 17
+ UTF-8
+
+
+
+ spring-rewrite-commons-plugin-invoker-shared
+ spring-rewrite-commons-plugin-invoker-maven
+ spring-rewrite-commons-plugin-invoker-gradle
+ spring-rewrite-commons-plugin-invoker-polyglot
+
+
+
+
+
+ org.springframework.rewrite
+ spring-rewrite-commons-plugin-invoker-maven
+ 0.1.0-SNAPSHOT
+
+
+ org.springframework.rewrite
+ spring-rewrite-commons-plugin-invoker-gradle
+ 0.1.0-SNAPSHOT
+
+
+
+
\ No newline at end of file
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/pom.xml b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/pom.xml
new file mode 100644
index 0000000..90b1bad
--- /dev/null
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/pom.xml
@@ -0,0 +1,47 @@
+
+
+ 4.0.0
+
+ org.springframework.rewrite
+ spring-rewrite-commons-plugin-invoker
+ 0.1.0-SNAPSHOT
+
+
+ spring-rewrite-commons-plugin-invoker-gradle
+
+
+ 17
+ 17
+ UTF-8
+
+
+
+
+ org.gradle
+ gradle-tooling-api
+
+
+ org.springframework.rewrite
+ spring-rewrite-commons-plugin-invoker-shared
+ ${project.version}
+
+
+ org.openrewrite
+ rewrite-core
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+ gradle
+ https://repo.gradle.org/gradle/libs-releases
+
+
+
\ No newline at end of file
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/src/main/java/org/springframework/rewrite/plugin/gradle/GradleInvocationResult.java b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/src/main/java/org/springframework/rewrite/plugin/gradle/GradleInvocationResult.java
new file mode 100644
index 0000000..31d16af
--- /dev/null
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/src/main/java/org/springframework/rewrite/plugin/gradle/GradleInvocationResult.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.rewrite.plugin.gradle;
+
+import org.openrewrite.marker.BuildTool;
+
+/**
+ * @author Fabian Krüger
+ */
+public class GradleInvocationResult {
+
+ private final String output;
+
+ private final String error;
+
+ public GradleInvocationResult(String output, String error) {
+ this.output = output;
+ this.error = error;
+ }
+
+ public String getOutput() {
+ return output;
+ }
+
+ public String getError() {
+ return error;
+ }
+
+}
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/src/main/java/org/springframework/rewrite/plugin/gradle/GradleInvoker.java b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/src/main/java/org/springframework/rewrite/plugin/gradle/GradleInvoker.java
new file mode 100644
index 0000000..ec09a6e
--- /dev/null
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/src/main/java/org/springframework/rewrite/plugin/gradle/GradleInvoker.java
@@ -0,0 +1,63 @@
+/*
+ * 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.rewrite.plugin.gradle;
+
+import org.gradle.tooling.BuildLauncher;
+import org.gradle.tooling.GradleConnector;
+import org.gradle.tooling.ProjectConnection;
+import org.gradle.tooling.internal.consumer.DefaultGradleConnector;
+
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+/**
+ * @author Fabian Krüger
+ */
+public class GradleInvoker {
+
+ private static BuildLauncher getBuildLauncher(Path baseDir, OutputStream os, String[] tasks) {
+ ProjectConnection connection = getProjectConnection(baseDir);
+ BuildLauncher buildLauncher = connection.newBuild().setStandardOutput(os).forTasks(tasks);
+ return buildLauncher;
+ }
+
+ public static GradleInvocationResult runTasks(Path baseDir, String[] args, String... tasks) {
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ ByteArrayOutputStream es = new ByteArrayOutputStream();
+ BuildLauncher buildLauncher = getBuildLauncher(baseDir, os, tasks);
+ buildLauncher.addArguments(args);
+ buildLauncher.setStandardError(es);
+ buildLauncher.run();
+ return new GradleInvocationResult(new String(os.toByteArray()), new String(es.toByteArray()));
+ }
+
+ protected static ProjectConnection getProjectConnection(Path projectDir) {
+ ProjectConnection connection;
+ var connector = (DefaultGradleConnector) GradleConnector.newConnector();
+ if (Files.exists(projectDir.resolve("gradle/wrapper/gradle-wrapper.properties"))) {
+ connector.useBuildDistribution();
+ }
+ else {
+ connector.useGradleVersion("8.4");
+ }
+
+ connection = connector.forProjectDirectory(projectDir.toFile()).connect();
+ return connection;
+ }
+
+}
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/src/main/java/org/springframework/rewrite/plugin/gradle/OpenRewriteGradlePluginBuilder.java b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/src/main/java/org/springframework/rewrite/plugin/gradle/OpenRewriteGradlePluginBuilder.java
new file mode 100644
index 0000000..5900c6b
--- /dev/null
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/src/main/java/org/springframework/rewrite/plugin/gradle/OpenRewriteGradlePluginBuilder.java
@@ -0,0 +1,56 @@
+/*
+ * 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.rewrite.plugin.gradle;
+
+import org.springframework.rewrite.plugin.shared.DebugConfig;
+import org.springframework.rewrite.plugin.shared.PluginInvocationResult;
+
+import java.nio.file.Path;
+
+/**
+ * @author Fabian Krüger
+ */
+public interface OpenRewriteGradlePluginBuilder {
+
+ public interface Recipes {
+
+ PluginVersion recipes(String... recipeNames);
+
+ }
+
+ public interface FinalizingBuilder {
+
+ FinalizingBuilder withDebugger(int port, boolean suspend);
+
+ FinalizingBuilder withDependencies(String... dependencies);
+
+ FinalizingBuilder withDebug();
+
+ FinalizingBuilder withMemory(String minMemory, String maxMemory);
+
+ FinalizingBuilder withDebugConfig(DebugConfig debugConfig);
+
+ PluginInvocationResult onDir(Path baseDir);
+
+ }
+
+ public interface PluginVersion {
+
+ FinalizingBuilder usingPluginVersion(String version);
+
+ }
+
+}
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/src/main/java/org/springframework/rewrite/plugin/gradle/RewriteGradlePlugin.java b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/src/main/java/org/springframework/rewrite/plugin/gradle/RewriteGradlePlugin.java
new file mode 100644
index 0000000..ce78d59
--- /dev/null
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/src/main/java/org/springframework/rewrite/plugin/gradle/RewriteGradlePlugin.java
@@ -0,0 +1,199 @@
+/*
+ * 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.rewrite.plugin.gradle;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.rewrite.plugin.shared.BuildConfig;
+import org.springframework.rewrite.plugin.shared.DebugConfig;
+import org.springframework.rewrite.plugin.shared.PluginInvocationResult;
+
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static org.springframework.rewrite.plugin.gradle.RewriteGradlePlugin.Task.*;
+
+/**
+ * @author Fabian Krüger
+ */
+public class RewriteGradlePlugin implements OpenRewriteGradlePluginBuilder.Recipes,
+ OpenRewriteGradlePluginBuilder.FinalizingBuilder, OpenRewriteGradlePluginBuilder.PluginVersion {
+
+ private static final Logger log = LoggerFactory.getLogger(RewriteGradlePlugin.class);
+
+ private Task task;
+
+ private List dependencies = new ArrayList<>();
+
+ private String pluginVersion;
+
+ private List recipes = new ArrayList<>();
+
+ private DebugConfig debugConfig = DebugConfig.disabled();
+
+ private String minMemory;
+
+ private String maxMemory;
+
+ private boolean debug = false;
+
+ public static OpenRewriteGradlePluginBuilder.Recipes run() {
+ return executeGradleRewritePlugin(RUN);
+ }
+
+ public static OpenRewriteGradlePluginBuilder.Recipes dryRun() {
+ return executeGradleRewritePlugin(DRY_RUN);
+ }
+
+ public static OpenRewriteGradlePluginBuilder.Recipes discover() {
+ return executeGradleRewritePlugin(DISCOVER);
+ }
+
+ private static OpenRewriteGradlePluginBuilder.Recipes executeGradleRewritePlugin(Task task) {
+ RewriteGradlePlugin plugin = new RewriteGradlePlugin();
+ plugin.task = task;
+ return plugin;
+ }
+
+ @Override
+ public OpenRewriteGradlePluginBuilder.PluginVersion recipes(String... recipeNames) {
+ this.recipes = Arrays.asList(recipeNames);
+ return this;
+ }
+
+ @Override
+ public OpenRewriteGradlePluginBuilder.FinalizingBuilder withDebugger(int port, boolean suspend) {
+ this.debugConfig = DebugConfig.from(port, suspend);
+ return this;
+ }
+
+ @Override
+ public OpenRewriteGradlePluginBuilder.FinalizingBuilder withDependencies(String... dependencies) {
+ this.dependencies = Arrays.asList(dependencies);
+ return this;
+ }
+
+ @Override
+ public OpenRewriteGradlePluginBuilder.FinalizingBuilder withDebug() {
+ this.debug = true;
+ return this;
+ }
+
+ @Override
+ public OpenRewriteGradlePluginBuilder.FinalizingBuilder withMemory(String minMemory, String maxMemory) {
+ this.minMemory = minMemory;
+ this.maxMemory = maxMemory;
+ return this;
+ }
+
+ @Override
+ public PluginInvocationResult onDir(Path baseDir) {
+ baseDir = baseDir.toAbsolutePath().normalize();
+ BuildConfig buildConfig = BuildConfig.defaultConfig();
+ if (minMemory != null && !minMemory.isBlank()) {
+ buildConfig = BuildConfig.builder().withMemory(minMemory, maxMemory).build();
+ }
+ GradleInvocationResult result = execute(baseDir, debug, debugConfig, buildConfig, task, dependencies,
+ pluginVersion, recipes.toArray(String[]::new));
+ boolean success = result.getError() == null || result.getError().isEmpty();
+ return new PluginInvocationResult(success, result.getOutput());
+ }
+
+ @Override
+ public OpenRewriteGradlePluginBuilder.FinalizingBuilder withDebugConfig(DebugConfig debugConfig) {
+ this.debugConfig = debugConfig;
+ return this;
+ }
+
+ /**
+ * Executes given OpenRewrite recipes using Gradle Tooling API.
+ * @param baseDir the dir getting parsed
+ * @param debug print debug output
+ * @param debugConfig set remote debug config to debug the recipe execution
+ */
+ static GradleInvocationResult execute(Path baseDir, boolean debug, DebugConfig debugConfig, BuildConfig buildConfig,
+ Task goal, List dependencies, String pluginVersion, String... recipes) {
+
+ try (TempGradleInitFile initFile = new TempGradleInitFile(baseDir, dependencies, pluginVersion)) {
+ String initFileLocation = initFile.getPath().toString();
+
+ List args = new ArrayList<>();
+
+ // provide init file location
+ args.add("-I%s".formatted(initFileLocation));
+ // the recipes
+ args.add("-Drewrite.activeRecipe=%s".formatted(Stream.of(recipes).collect(Collectors.joining(","))));
+ // debug outout
+ if (debug) {
+ args.add("-d");
+ }
+ // Remote debugging
+ if (debugConfig.isDebugEnabled()) {
+ args.add("-Dorg.gradle.logging.stacktrace=full");
+ args.add("-Dorg.gradle.debug=true");
+ args.add("-Dorg.gradle.debug.port=" + debugConfig.getPort());
+ args.add("-Dorg.gradle.debug.suspend=" + debugConfig.isSuspend());
+ }
+ // JVM Memory
+ List jvmArgs = new ArrayList<>();
+ if (buildConfig.hasMemorySettings()) {
+ String min = buildConfig.getMemorySettings().getMin();
+ String max = buildConfig.getMemorySettings().getMax();
+ jvmArgs.add("-Xms%s -Xmx%s".formatted(min, max));
+ String jvmArgsStr = jvmArgs.stream().collect(Collectors.joining(" "));
+ args.add("-Dorg.gradle.jvmargs=%s".formatted(jvmArgsStr));
+ }
+
+ if (log.isDebugEnabled()) {
+ log.debug("Command: ./gradlew %s %s".formatted(goal.getTask(),
+ args.stream().collect(Collectors.joining(" "))));
+ log.debug(initFileLocation + " \n" + initFile.getContent());
+ }
+
+ return GradleInvoker.runTasks(baseDir, args.toArray(String[]::new), goal.getTask());
+ }
+ finally {
+ TempGradleInitFile.clear(baseDir);
+ }
+ }
+
+ @Override
+ public OpenRewriteGradlePluginBuilder.FinalizingBuilder usingPluginVersion(String version) {
+ this.pluginVersion = version;
+ return this;
+ }
+
+ enum Task {
+
+ RUN("rewriteRun"), DRY_RUN("rewriteDryRun"), DISCOVER("rewriteDiscover");
+
+ private final String task;
+
+ Task(String task) {
+ this.task = task;
+ }
+
+ public String getTask() {
+ return task;
+ }
+
+ }
+
+}
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/src/main/java/org/springframework/rewrite/plugin/gradle/TempGradleInitFile.java b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/src/main/java/org/springframework/rewrite/plugin/gradle/TempGradleInitFile.java
new file mode 100644
index 0000000..247e1bb
--- /dev/null
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/src/main/java/org/springframework/rewrite/plugin/gradle/TempGradleInitFile.java
@@ -0,0 +1,107 @@
+/*
+ * 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.rewrite.plugin.gradle;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author Fabian Krüger
+ */
+public class TempGradleInitFile implements Closeable {
+
+ private static final String template = """
+ initscript {
+ repositories {
+ maven { url "https://plugins.gradle.org/m2" }
+ }
+ dependencies {
+ classpath("org.openrewrite:plugin:%s")
+ }
+ }
+
+ rootProject {
+ plugins.apply(org.openrewrite.gradle.RewritePlugin)
+ dependencies {
+ %s
+ }
+
+ afterEvaluate {
+ if (repositories.isEmpty()) {
+ repositories {
+ mavenCentral()
+ }
+ }
+ }
+ }
+ """;
+
+ private final Path gradleFile;
+
+ private final String initFileContent;
+
+ public TempGradleInitFile(Path baseDir, List dependencies, String pluginVersion) {
+ String dependenciesStr = dependencies.stream()
+ .map(d -> " rewrite(\"" + d + "\")")
+ .collect(Collectors.joining("\n"));
+ initFileContent = template.formatted(pluginVersion, dependenciesStr);
+ try {
+ gradleFile = baseDir.resolve("recipes.init.gradle").toAbsolutePath().normalize();
+ gradleFile.toFile().getParentFile().mkdirs();
+ Files.writeString(gradleFile, initFileContent);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static void clear(Path baseDir) {
+ Path gradleFile = baseDir.resolve("recipes.init.gradle");
+ if (Files.exists(gradleFile)) {
+ try {
+ Files.delete(gradleFile);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ public String getContent() {
+ return initFileContent;
+ }
+
+ public Path getPath() {
+ return gradleFile;
+ }
+
+ @Override
+ public void close() {
+ if (Files.exists(gradleFile)) {
+ try {
+ Files.delete(gradleFile);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+}
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/src/test/java/org/springframework/rewrite/plugin/gradle/RewriteGradlePluginTest.java b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/src/test/java/org/springframework/rewrite/plugin/gradle/RewriteGradlePluginTest.java
new file mode 100644
index 0000000..284665d
--- /dev/null
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/src/test/java/org/springframework/rewrite/plugin/gradle/RewriteGradlePluginTest.java
@@ -0,0 +1,145 @@
+/*
+ * 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.rewrite.plugin.gradle;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.springframework.rewrite.plugin.shared.PluginInvocationResult;
+import org.springframework.test.util.TestSocketUtils;
+
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * @author Fabian Krüger
+ */
+public class RewriteGradlePluginTest {
+
+ public static final String[] RECIPES = { "org.openrewrite.java.RemoveUnusedImports",
+ "org.openrewrite.java.format.NormalizeLineBreaks" };
+
+ public static final String[] EXTENDED_RECIPES = { "org.openrewrite.java.RemoveUnusedImports",
+ "org.openrewrite.java.format.NormalizeLineBreaks",
+ "org.openrewrite.java.migrate.jakarta.MaybeAddJakartaServletApi" };
+
+ public static final String[] DEFAULT_TASKS = new String[] { "compileJava", "processResources", "classes",
+ "compileTestJava", "rewriteResolveDependencies" };
+
+ public static final String EXTENDED_RECIPES_DEPS = "org.openrewrite.recipe:rewrite-migrate-java:2.9.0";
+
+ @Test
+ @DisplayName("simple project minimal setup")
+ void simpleProjectMinimalSetup() {
+ Path baseDir = Path.of("./testcode/gradle-projects/simple");
+ PluginInvocationResult result = RewriteGradlePlugin.dryRun()
+ .recipes(RECIPES)
+ .usingPluginVersion("6.10.0")
+ .onDir(baseDir);
+
+ String out = result.capturedOutput();
+ assertThat(result.success()).isTrue();
+ assertSuccessfulBuild(out);
+ assertTasksExecuted(out, DEFAULT_TASKS, "rewriteDryRun");
+ assertRecipesExecuted(out, RECIPES);
+ }
+
+ @Test
+ @DisplayName("simple project skip tests")
+ void simpleProjectSkipTests() {
+ Path baseDir = Path.of("./testcode/gradle-projects/simple");
+ PluginInvocationResult result = RewriteGradlePlugin.run()
+ .recipes(RECIPES)
+ .usingPluginVersion("6.10.0")
+ .withMemory("256M", "1G")
+ .onDir(baseDir);
+
+ String out = result.capturedOutput();
+ assertThat(result.success()).isTrue();
+ assertSuccessfulBuild(out);
+ assertTasksExecuted(out, DEFAULT_TASKS, "rewriteRun");
+ assertRecipesExecuted(out, RECIPES);
+ }
+
+ @Test
+ @DisplayName("simple project full config")
+ void simpleProjectFullConfig() {
+ Path baseDir = Path.of("./testcode/gradle-projects/simple");
+
+ int port = TestSocketUtils.findAvailableTcpPort();
+
+ PluginInvocationResult result = RewriteGradlePlugin.run()
+ .recipes(EXTENDED_RECIPES)
+ .usingPluginVersion("6.10.0")
+ .withDebugger(port, false)
+ .withDependencies(EXTENDED_RECIPES_DEPS)
+ .withDebug()
+ .withMemory("64M", "484M")
+ .onDir(baseDir);
+
+ assertThat(result.success()).isTrue();
+ String out = result.capturedOutput();
+ assertMemory(out, "64M", "484M");
+ assertDebugConfig(out, port, false);
+ assertRecipesExecuted(out, EXTENDED_RECIPES);
+ assertTasksExecuted(out, DEFAULT_TASKS, "rewriteRun");
+ }
+
+ private void assertDebugConfig(String out, int port, boolean suspend) {
+ assertThat(out).contains("-agentlib:jdwp=transport=dt_socket,server=y,suspend=%s,address=%s"
+ .formatted(suspend ? "y" : "n", port));
+ }
+
+ private void assertMemory(String out, String min, String max) {
+ assertThat(out).contains("-Xms%s".formatted(min));
+ assertThat(out).contains("-Xmx%s".formatted(max));
+ }
+
+ private void assertSuccessfulBuild(String out) {
+ assertThat(out).contains("BUILD SUCCESSFUL in");
+ }
+
+ private void assertTasksExecuted(String out, String[] defaultTasks, String rewriteTask) {
+ String[] tasks = tasksOf(defaultTasks, rewriteTask);
+ List tasksOutput = Stream.of(tasks).map(t -> "Task :" + t).toList();
+ assertThat(out).contains(tasksOutput);
+ }
+
+ private void assertRecipesExecuted(String out, String[] recipes) {
+ assertThat(out).containsIgnoringWhitespaces(
+ "All sources parsed, running active recipes: " + Stream.of(recipes).collect(Collectors.joining(",")));
+ }
+
+ private String[] tasksOf(String[] defaultTasks, String[] testTasks, String rewriteTask) {
+ List tasksList = new ArrayList<>();
+ tasksList.addAll(Arrays.asList(defaultTasks));
+ if (testTasks != null) {
+ tasksList.addAll(Arrays.asList(testTasks));
+ }
+ tasksList.add(rewriteTask);
+ return tasksList.toArray(String[]::new);
+ }
+
+ private String[] tasksOf(String[] defaultTasks, String rewriteTask) {
+ return tasksOf(defaultTasks, null, rewriteTask);
+ }
+
+}
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/src/test/java/org/springframework/rewrite/plugin/gradle/TempGradleInitFileTest.java b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/src/test/java/org/springframework/rewrite/plugin/gradle/TempGradleInitFileTest.java
new file mode 100644
index 0000000..f0a0260
--- /dev/null
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/src/test/java/org/springframework/rewrite/plugin/gradle/TempGradleInitFileTest.java
@@ -0,0 +1,122 @@
+/*
+ * 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.rewrite.plugin.gradle;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+import java.nio.file.Path;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * @author Fabian Krüger
+ */
+class TempGradleInitFileTest {
+
+ @Test
+ @DisplayName("should create and delete gradle init file")
+ void shouldCreateAndDeleteGradleInitFile(@TempDir Path temoDir) {
+ List depemdemcies = List.of("dep1", "dep2");
+ String pluginVersion = "x.y.z";
+
+ assertThat(temoDir.resolve("recipes.init.gradle")).doesNotExist();
+
+ try (TempGradleInitFile initFile = new TempGradleInitFile(temoDir, depemdemcies, pluginVersion)) {
+
+ assertThat(temoDir.resolve("recipes.init.gradle")).exists();
+
+ assertThat(initFile.getContent()).isEqualTo("""
+ initscript {
+ repositories {
+ maven { url "https://plugins.gradle.org/m2" }
+ }
+ dependencies {
+ classpath("org.openrewrite:plugin:x.y.z")
+ }
+ }
+
+ rootProject {
+ plugins.apply(org.openrewrite.gradle.RewritePlugin)
+ dependencies {
+ rewrite("dep1")
+ rewrite("dep2")
+ }
+
+ afterEvaluate {
+ if (repositories.isEmpty()) {
+ repositories {
+ mavenCentral()
+ }
+ }
+ }
+ }
+ """);
+ }
+
+ assertThat(temoDir.resolve("recipes.init.gradle")).doesNotExist();
+ }
+
+ @Test
+ @DisplayName("should create and delete gradle init file on exception")
+ void shouldCreateAndDeleteGradleInitFileOnException(@TempDir Path temoDir) {
+ List depemdemcies = List.of("dep1", "dep2");
+ String pluginVersion = "x.y.z";
+
+ assertThat(temoDir.resolve("recipes.init.gradle")).doesNotExist();
+ try {
+
+ try (TempGradleInitFile initFile = new TempGradleInitFile(temoDir, depemdemcies, pluginVersion)) {
+
+ assertThat(temoDir.resolve("recipes.init.gradle")).exists();
+
+ assertThat(initFile.getContent()).isEqualTo("""
+ initscript {
+ repositories {
+ maven { url "https://plugins.gradle.org/m2" }
+ }
+ dependencies {
+ classpath("org.openrewrite:plugin:x.y.z")
+ }
+ }
+
+ rootProject {
+ plugins.apply(org.openrewrite.gradle.RewritePlugin)
+ dependencies {
+ rewrite("dep1")
+ rewrite("dep2")
+ }
+
+ afterEvaluate {
+ if (repositories.isEmpty()) {
+ repositories {
+ mavenCentral()
+ }
+ }
+ }
+ }
+ """);
+ throw new RuntimeException();
+ }
+ }
+ catch (Exception e) {
+ assertThat(temoDir.resolve("recipes.init.gradle")).doesNotExist();
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/testcode/gradle-projects/simple/.gitignore b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/testcode/gradle-projects/simple/.gitignore
new file mode 100644
index 0000000..b63da45
--- /dev/null
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/testcode/gradle-projects/simple/.gitignore
@@ -0,0 +1,42 @@
+.gradle
+build/
+!gradle/wrapper/gradle-wrapper.jar
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### IntelliJ IDEA ###
+.idea/modules.xml
+.idea/jarRepositories.xml
+.idea/compiler.xml
+.idea/libraries/
+*.iws
+*.iml
+*.ipr
+out/
+!**/src/main/**/out/
+!**/src/test/**/out/
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+bin/
+!**/src/main/**/bin/
+!**/src/test/**/bin/
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store
\ No newline at end of file
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/testcode/gradle-projects/simple/build.gradle.kts b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/testcode/gradle-projects/simple/build.gradle.kts
new file mode 100644
index 0000000..a6c5d7d
--- /dev/null
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/testcode/gradle-projects/simple/build.gradle.kts
@@ -0,0 +1,19 @@
+plugins {
+ id("java")
+}
+
+group = "org.example"
+version = "1.0-SNAPSHOT"
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ testImplementation(platform("org.junit:junit-bom:5.9.1"))
+ testImplementation("org.junit.jupiter:junit-jupiter")
+}
+
+tasks.test {
+ useJUnitPlatform()
+}
\ No newline at end of file
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/testcode/gradle-projects/simple/gradle/wrapper/gradle-wrapper.jar b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/testcode/gradle-projects/simple/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..249e583
Binary files /dev/null and b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/testcode/gradle-projects/simple/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/testcode/gradle-projects/simple/gradle/wrapper/gradle-wrapper.properties b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/testcode/gradle-projects/simple/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..f027096
--- /dev/null
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/testcode/gradle-projects/simple/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Wed Mar 13 15:37:19 CET 2024
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/testcode/gradle-projects/simple/gradlew b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/testcode/gradle-projects/simple/gradlew
new file mode 100755
index 0000000..1b6c787
--- /dev/null
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/testcode/gradle-projects/simple/gradlew
@@ -0,0 +1,234 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original 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.
+#
+
+##############################################################################
+#
+# Gradle start up script for POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
+done
+
+APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
+
+APP_NAME="Gradle"
+APP_BASE_NAME=${0##*/}
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+ echo "$*"
+} >&2
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in #(
+ CYGWIN* ) cygwin=true ;; #(
+ Darwin* ) darwin=true ;; #(
+ MSYS* | MINGW* ) msys=true ;; #(
+ NONSTOP* ) nonstop=true ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD=$JAVA_HOME/jre/sh/java
+ else
+ JAVACMD=$JAVA_HOME/bin/java
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD=java
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
+ esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
+ fi
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
+ done
+fi
+
+# Collect all arguments for the java command;
+# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
+# shell script including quotes and variable substitutions, so put them in
+# double quotes to make sure that they get re-expanded; and
+# * put everything else in single quotes, so that it's not re-expanded.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ org.gradle.wrapper.GradleWrapperMain \
+ "$@"
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/testcode/gradle-projects/simple/gradlew.bat b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/testcode/gradle-projects/simple/gradlew.bat
new file mode 100644
index 0000000..107acd3
--- /dev/null
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/testcode/gradle-projects/simple/gradlew.bat
@@ -0,0 +1,89 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/testcode/gradle-projects/simple/settings.gradle.kts b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/testcode/gradle-projects/simple/settings.gradle.kts
new file mode 100644
index 0000000..474bc17
--- /dev/null
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/testcode/gradle-projects/simple/settings.gradle.kts
@@ -0,0 +1,2 @@
+rootProject.name = "simple"
+
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/testcode/gradle-projects/simple/src/main/java/org/example/Main.java b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/testcode/gradle-projects/simple/src/main/java/org/example/Main.java
new file mode 100644
index 0000000..9f3c33a
--- /dev/null
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-gradle/testcode/gradle-projects/simple/src/main/java/org/example/Main.java
@@ -0,0 +1,10 @@
+package org.example;
+
+/**
+ * @author Fabian Krüger
+ */
+public class Main {
+ public static void main(String[] args) {
+ System.out.println("Hello world!");
+ }
+}
\ No newline at end of file
diff --git a/spring-rewrite-commons-maven-invoker/pom.xml b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-maven/pom.xml
similarity index 89%
rename from spring-rewrite-commons-maven-invoker/pom.xml
rename to spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-maven/pom.xml
index 0684cf8..bc945aa 100644
--- a/spring-rewrite-commons-maven-invoker/pom.xml
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-maven/pom.xml
@@ -5,11 +5,11 @@
4.0.0
org.springframework.rewrite
- spring-rewrite-commons
+ spring-rewrite-commons-plugin-invoker
0.1.0-SNAPSHOT
- spring-rewrite-commons-maven-invoker
+ spring-rewrite-commons-plugin-invoker-maven
17
@@ -25,9 +25,8 @@
org.apache.maven.shared
maven-shared-utils
- 3.4.2
+ ${maven-shared-utils.version}
-
org.apache.maven.shared
maven-invoker
@@ -85,6 +84,12 @@
${maven.version}
+
+ org.springframework.rewrite
+ spring-rewrite-commons-plugin-invoker-shared
+ 0.1.0-SNAPSHOT
+
+
org.springframework.boot
spring-boot-starter-test
diff --git a/spring-rewrite-commons-maven-invoker/src/main/java/org/springframework/rewrite/maven/MavenInvocationRequestFactory.java b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-maven/src/main/java/org/springframework/rewrite/plugin/maven/MavenInvocationRequestFactory.java
similarity index 85%
rename from spring-rewrite-commons-maven-invoker/src/main/java/org/springframework/rewrite/maven/MavenInvocationRequestFactory.java
rename to spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-maven/src/main/java/org/springframework/rewrite/plugin/maven/MavenInvocationRequestFactory.java
index a0ce961..160f3d8 100644
--- a/spring-rewrite-commons-maven-invoker/src/main/java/org/springframework/rewrite/maven/MavenInvocationRequestFactory.java
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-maven/src/main/java/org/springframework/rewrite/plugin/maven/MavenInvocationRequestFactory.java
@@ -13,10 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.springframework.rewrite.maven;
+package org.springframework.rewrite.plugin.maven;
import org.apache.maven.shared.invoker.*;
import org.jetbrains.annotations.NotNull;
+import org.springframework.rewrite.plugin.shared.BuildConfig;
+import org.springframework.rewrite.plugin.shared.DebugConfig;
import java.io.File;
import java.nio.file.Path;
@@ -30,7 +32,7 @@ import java.util.function.Consumer;
public class MavenInvocationRequestFactory {
@NotNull
- public InvocationRequest createMavenInvocationRequest(Path baseDir, DebugConfig debugConfig,
+ public InvocationRequest createMavenInvocationRequest(Path baseDir, DebugConfig debugConfig, boolean debug,
BuildConfig buildConfig, List givenGoals, Consumer lineConsumer) {
List goals = new ArrayList<>(givenGoals);
String mavenHome = System.getenv("MAVEN_HOME");
@@ -52,15 +54,18 @@ public class MavenInvocationRequestFactory {
request.setMavenHome(new File(mavenHome));
request.setBaseDirectory(baseDir.toFile());
request.setOutputHandler(s -> lineConsumer.accept(s));
+ if (debug) {
+ request.setDebug(true);
+ }
StringBuilder mavenOpts = new StringBuilder();
- if (buildConfig.getMemorySettings() != null) {
+ if (buildConfig.hasMemorySettings()) {
mavenOpts.append("-Xms%s -Xmx%s ".formatted(buildConfig.getMemorySettings().getMin(),
buildConfig.getMemorySettings().getMax()));
}
if (debugConfig != null && debugConfig.isDebugEnabled()) {
mavenOpts.append(" -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=%s,address=%s "
- .formatted(debugConfig.isSuspend(), debugConfig.getPort()));
+ .formatted(debugConfig.isSuspendEnabled(), debugConfig.getPort()));
}
request.setMavenOpts(mavenOpts.toString());
return request;
diff --git a/spring-rewrite-commons-maven-invoker/src/test/java/org/springframework/rewrite/maven/DummyInvocationResult.java b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-maven/src/main/java/org/springframework/rewrite/plugin/maven/MavenInvocationResult.java
similarity index 62%
rename from spring-rewrite-commons-maven-invoker/src/test/java/org/springframework/rewrite/maven/DummyInvocationResult.java
rename to spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-maven/src/main/java/org/springframework/rewrite/plugin/maven/MavenInvocationResult.java
index daa010e..651faf0 100644
--- a/spring-rewrite-commons-maven-invoker/src/test/java/org/springframework/rewrite/maven/DummyInvocationResult.java
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-maven/src/main/java/org/springframework/rewrite/plugin/maven/MavenInvocationResult.java
@@ -13,21 +13,28 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.springframework.rewrite.maven;
+package org.springframework.rewrite.plugin.maven;
-import org.apache.maven.shared.invoker.InvocationResult;
-import org.apache.maven.shared.utils.cli.CommandLineException;
+/**
+ * @author Fabian Krüger
+ */
+public class MavenInvocationResult {
-public class DummyInvocationResult implements InvocationResult {
+ private final int exitCode;
- @Override
- public CommandLineException getExecutionException() {
- return null;
+ private final String capturedLines;
+
+ public MavenInvocationResult(int exitCode, String capturedLines) {
+ this.exitCode = exitCode;
+ this.capturedLines = capturedLines;
}
- @Override
public int getExitCode() {
- return 0;
+ return exitCode;
}
-}
\ No newline at end of file
+ public String getCapturedLines() {
+ return capturedLines;
+ }
+
+}
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-maven/src/main/java/org/springframework/rewrite/plugin/maven/MavenInvoker.java b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-maven/src/main/java/org/springframework/rewrite/plugin/maven/MavenInvoker.java
new file mode 100644
index 0000000..b68abf2
--- /dev/null
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-maven/src/main/java/org/springframework/rewrite/plugin/maven/MavenInvoker.java
@@ -0,0 +1,57 @@
+/*
+ * 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.rewrite.plugin.maven;
+
+import org.apache.maven.shared.invoker.*;
+import org.jetbrains.annotations.NotNull;
+import org.springframework.rewrite.plugin.shared.BuildConfig;
+import org.springframework.rewrite.plugin.shared.DebugConfig;
+import org.springframework.rewrite.plugin.shared.MemorySettings;
+
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Fabian Krüger
+ */
+public class MavenInvoker {
+
+ private static final Invoker invoker = new DefaultInvoker();
+
+ public static MavenInvocationResult runGoals(Path baseDir, DebugConfig debugConfig, boolean debug,
+ BuildConfig buildConfig, List goals) {
+ try {
+ StringBuilder sb = new StringBuilder();
+ InvocationRequest request = createInvocationRequest(baseDir, debugConfig, debug, buildConfig, goals, sb);
+ InvocationResult result = invoker.execute(request);
+ return new MavenInvocationResult(result.getExitCode(), sb.toString());
+ }
+ catch (MavenInvocationException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @NotNull
+ private static InvocationRequest createInvocationRequest(Path baseDir, DebugConfig debugConfig, boolean debug,
+ BuildConfig buildConfig, List goals, StringBuilder sb) {
+ return new MavenInvocationRequestFactory().createMavenInvocationRequest(baseDir, debugConfig, debug,
+ buildConfig, goals, line -> {
+ sb.append(line).append("\n");
+ });
+ }
+
+}
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-maven/src/main/java/org/springframework/rewrite/plugin/maven/RewriteMavenPlugin.java b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-maven/src/main/java/org/springframework/rewrite/plugin/maven/RewriteMavenPlugin.java
new file mode 100644
index 0000000..93eecf4
--- /dev/null
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-maven/src/main/java/org/springframework/rewrite/plugin/maven/RewriteMavenPlugin.java
@@ -0,0 +1,165 @@
+/*
+ * 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.rewrite.plugin.maven;
+
+import org.springframework.rewrite.plugin.shared.BuildConfig;
+import org.springframework.rewrite.plugin.shared.DebugConfig;
+import org.springframework.rewrite.plugin.shared.PluginInvocationResult;
+
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static org.springframework.rewrite.plugin.maven.RewriteMavenPlugin.Goal.*;
+
+public class RewriteMavenPlugin
+ implements RewriteMavenPluginBuilder.FinalizingBuilder, RewriteMavenPluginBuilder.Recipes {
+
+ private Goal goal;
+
+ private DebugConfig debugConfig;
+
+ private List recipes = new ArrayList<>();
+
+ private String minMemory;
+
+ private String maxMemory;
+
+ private MavenInvocationRequestFactory factory = new MavenInvocationRequestFactory();
+
+ private List dependencies = new ArrayList<>();
+
+ private boolean debug;
+
+ @Override
+ public RewriteMavenPluginBuilder.FinalizingBuilder withDependencies(String... dependencies) {
+ this.dependencies = Arrays.asList(dependencies);
+ return this;
+ }
+
+ public static RewriteMavenPluginBuilder.Recipes run() {
+ Goal run = RUN;
+ return executeMavenRewritePlugin(run);
+ }
+
+ public static RewriteMavenPluginBuilder.Recipes runNoFork() {
+ Goal run = RUN_NO_FORK;
+ return executeMavenRewritePlugin(run);
+ }
+
+ public static RewriteMavenPluginBuilder.Recipes dryRun() {
+ Goal run = DRY_RUN;
+ return executeMavenRewritePlugin(run);
+ }
+
+ public static RewriteMavenPluginBuilder.Recipes dryRunNoFork() {
+ Goal run = DRY_RUN_NO_FORK;
+ return executeMavenRewritePlugin(run);
+ }
+
+ public static RewriteMavenPluginBuilder.Recipes discover() {
+ Goal run = DISCOVER;
+ return executeMavenRewritePlugin(run);
+ }
+
+ public static RewriteMavenPluginBuilder.Recipes cyclonedx() {
+ Goal run = CYCLONEDX;
+ return executeMavenRewritePlugin(run);
+ }
+
+ private static RewriteMavenPlugin executeMavenRewritePlugin(Goal run) {
+ RewriteMavenPlugin rewriteMavenPlugin = new RewriteMavenPlugin();
+ rewriteMavenPlugin.goal = run;
+ return rewriteMavenPlugin;
+ }
+
+ @Override
+ public RewriteMavenPluginBuilder.FinalizingBuilder recipes(String... recipeNames) {
+ this.recipes = Arrays.asList(recipeNames);
+ return this;
+ }
+
+ @Override
+ public RewriteMavenPluginBuilder.FinalizingBuilder withDebugger(int port, boolean suspend) {
+ debugConfig = DebugConfig.from(port, suspend);
+ return this;
+ }
+
+ @Override
+ public RewriteMavenPluginBuilder.FinalizingBuilder withDebug() {
+ this.debug = true;
+ return this;
+ }
+
+ @Override
+ public PluginInvocationResult onDir(Path baseDir) {
+ BuildConfig.Builder builder = BuildConfig.builder();
+ if (minMemory != null) {
+ builder.withMemory(minMemory, maxMemory);
+ }
+ MavenInvocationResult result = execute(baseDir, debug, debugConfig, builder.build(), goal, recipes,
+ dependencies);
+
+ return new PluginInvocationResult(result.getExitCode() != 0 ? false : true, result.getCapturedLines());
+ }
+
+ static MavenInvocationResult execute(Path baseDir, boolean debug, DebugConfig debugConfig, BuildConfig buildConfig,
+ Goal openRewriteGoal, List recipes1, List dependencies1) {
+ String openRewriteCommand = renderOpenRewriteCommand(recipes1, dependencies1, openRewriteGoal);
+ List goals = List.of("--fail-at-end", openRewriteCommand);
+ return MavenInvoker.runGoals(baseDir, debugConfig, debug, buildConfig, goals);
+ }
+
+ private static String renderOpenRewriteCommand(List recipeNames, List dependencies,
+ Goal rewritePluginGoal) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("org.openrewrite.maven:rewrite-maven-plugin:").append(rewritePluginGoal.getMaven()).append(" ");
+ String recipesList = recipeNames.stream().collect(Collectors.joining(","));
+ sb.append("-Drewrite.activeRecipes=").append(recipesList);
+ if (!dependencies.isEmpty()) {
+ String dependenciesList = dependencies.stream().collect(Collectors.joining(","));
+ sb.append(" ").append("-Drewrite.recipeArtifactCoordinates=").append(dependenciesList);
+ }
+ return sb.toString();
+ }
+
+ @Override
+ public RewriteMavenPluginBuilder.FinalizingBuilder withMemory(String minMemory, String maxMemory) {
+ this.minMemory = minMemory;
+ this.maxMemory = maxMemory;
+ return this;
+ }
+
+ public enum Goal {
+
+ RUN("run"), RUN_NO_FORK("runNoFork"), DRY_RUN("dryRun"), DRY_RUN_NO_FORK("dryRunNoFork"), DISCOVER("discover"),
+ CYCLONEDX("cyclonedx");
+
+ private final String maven;
+
+ Goal(String maven) {
+ this.maven = maven;
+ }
+
+ public String getMaven() {
+ return maven;
+ }
+
+ }
+
+}
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-maven/src/main/java/org/springframework/rewrite/plugin/maven/RewriteMavenPluginBuilder.java b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-maven/src/main/java/org/springframework/rewrite/plugin/maven/RewriteMavenPluginBuilder.java
new file mode 100644
index 0000000..4672a14
--- /dev/null
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-maven/src/main/java/org/springframework/rewrite/plugin/maven/RewriteMavenPluginBuilder.java
@@ -0,0 +1,47 @@
+/*
+ * 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.rewrite.plugin.maven;
+
+import org.springframework.rewrite.plugin.shared.PluginInvocationResult;
+
+import java.nio.file.Path;
+
+/**
+ * @author Fabian Krüger
+ */
+public interface RewriteMavenPluginBuilder {
+
+ public interface Recipes {
+
+ FinalizingBuilder recipes(String... recipeNames);
+
+ }
+
+ interface FinalizingBuilder {
+
+ FinalizingBuilder withDependencies(String... dependencies);
+
+ FinalizingBuilder withDebugger(int port, boolean suspend);
+
+ FinalizingBuilder withDebug();
+
+ FinalizingBuilder withMemory(String s, String s1);
+
+ PluginInvocationResult onDir(Path baseDir);
+
+ }
+
+}
diff --git a/spring-rewrite-commons-maven-invoker/src/test/java/org/springframework/rewrite/maven/MavenInvocationRequestFactoryTest.java b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-maven/src/test/java/org/springframework/rewrite/plugin/maven/MavenInvocationRequestFactoryTest.java
similarity index 91%
rename from spring-rewrite-commons-maven-invoker/src/test/java/org/springframework/rewrite/maven/MavenInvocationRequestFactoryTest.java
rename to spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-maven/src/test/java/org/springframework/rewrite/plugin/maven/MavenInvocationRequestFactoryTest.java
index cc6e677..18d199f 100644
--- a/spring-rewrite-commons-maven-invoker/src/test/java/org/springframework/rewrite/maven/MavenInvocationRequestFactoryTest.java
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-maven/src/test/java/org/springframework/rewrite/plugin/maven/MavenInvocationRequestFactoryTest.java
@@ -13,12 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.springframework.rewrite.maven;
+package org.springframework.rewrite.plugin.maven;
import org.apache.maven.shared.invoker.InvocationRequest;
import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
+import org.springframework.rewrite.plugin.shared.BuildConfig;
+import org.springframework.rewrite.plugin.shared.DebugConfig;
import java.nio.file.Path;
import java.util.ArrayList;
@@ -41,7 +43,7 @@ public class MavenInvocationRequestFactoryTest {
};
Path baseDir = Path.of("./testcode/does-not-exist");
- InvocationRequest request = sut.createMavenInvocationRequest(baseDir, DebugConfig.disabled(),
+ InvocationRequest request = sut.createMavenInvocationRequest(baseDir, DebugConfig.disabled(), false,
BuildConfig.defaultConfig(), goals, lineConsumer);
assertThat(request.getGoals()).isEqualTo(goals);
@@ -59,7 +61,7 @@ public class MavenInvocationRequestFactoryTest {
};
Path baseDir = Path.of("./testcode/does-not-exist");
- InvocationRequest request = sut.createMavenInvocationRequest(baseDir, DebugConfig.from(1234, true),
+ InvocationRequest request = sut.createMavenInvocationRequest(baseDir, DebugConfig.from(1234, true), true,
BuildConfig.defaultConfig(), goals, lineConsumer);
assertThat(request.getMavenOpts())
@@ -73,7 +75,7 @@ public class MavenInvocationRequestFactoryTest {
List lines = new ArrayList<>();
Path baseDir = Path.of("./testcode/does-not-exist").toAbsolutePath().normalize();
@NotNull
- InvocationRequest result = sut.createMavenInvocationRequest(baseDir, DebugConfig.disabled(),
+ InvocationRequest result = sut.createMavenInvocationRequest(baseDir, DebugConfig.disabled(), false,
BuildConfig.defaultConfig(), List.of("clean"), lines::add);
}
@@ -87,7 +89,7 @@ public class MavenInvocationRequestFactoryTest {
};
Path baseDir = Path.of("./testcode/does-not-exist");
- InvocationRequest request = sut.createMavenInvocationRequest(baseDir, DebugConfig.disabled(),
+ InvocationRequest request = sut.createMavenInvocationRequest(baseDir, DebugConfig.disabled(), false,
BuildConfig.builder().withMemory("12M", "2G").skipTests(true).build(), goals, lineConsumer);
assertThat(request.getMavenOpts()).isEqualTo("-Xms12M -Xmx2G ");
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-maven/src/test/java/org/springframework/rewrite/plugin/maven/RewriteMavenPluginTest.java b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-maven/src/test/java/org/springframework/rewrite/plugin/maven/RewriteMavenPluginTest.java
new file mode 100644
index 0000000..ef8da13
--- /dev/null
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-maven/src/test/java/org/springframework/rewrite/plugin/maven/RewriteMavenPluginTest.java
@@ -0,0 +1,243 @@
+/*
+ * 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.rewrite.plugin.maven;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.springframework.rewrite.plugin.shared.BuildConfig;
+import org.springframework.rewrite.plugin.shared.DebugConfig;
+import org.springframework.rewrite.plugin.shared.PluginInvocationResult;
+import org.springframework.test.util.TestSocketUtils;
+
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.fail;
+
+/**
+ * @author Fabian Krüger
+ */
+class RewriteMavenPluginTest {
+
+ public static final String[] RECIPES = { "org.openrewrite.java.RemoveUnusedImports",
+ "org.openrewrite.java.format.NormalizeLineBreaks" };
+
+ public static final String[] EXTENDED_RECIPES = { "org.openrewrite.java.RemoveUnusedImports",
+ "org.openrewrite.java.format.NormalizeLineBreaks",
+ "org.openrewrite.java.migrate.jakarta.MaybeAddJakartaServletApi" };
+
+ public static final String EXTENDED_REFCIPES_DEPS = "org.openrewrite.recipe:rewrite-migrate-java:2.9.0";
+
+ public static final String[] DEFAULT_GOALS = new String[] { "resources", "compile", "testResources",
+ "testCompile" };
+
+ @Test
+ @DisplayName("simple project simple config")
+ void simpleProjectSimpleConfig() {
+ Path baseDir = Path.of("./testcode/maven-projects/simple").toAbsolutePath().normalize();
+
+ PluginInvocationResult result = RewriteMavenPlugin.run().recipes(RECIPES).onDir(baseDir);
+
+ String out = result.capturedOutput();
+ assertThat(result.success()).isTrue();
+ assertTasksExecuted(out, tasksOf(DEFAULT_GOALS, "run"));
+ assertRecipesExecuted(out, RECIPES);
+ }
+
+ @Test
+ @DisplayName("builder runNoFork")
+ void simpleProjectSimpleConfigRunNoFork() {
+ Path baseDir = Path.of("./testcode/maven-projects/simple").toAbsolutePath().normalize();
+ PluginInvocationResult result = RewriteMavenPlugin.runNoFork().recipes(RECIPES).onDir(baseDir);
+ String out = result.capturedOutput();
+ assertThat(result.success()).isTrue();
+ assertTasksExecuted(out, "runNoFork");
+ assertRecipesExecuted(out, RECIPES);
+ }
+
+ @Test
+ @DisplayName("builder dryRun")
+ void simpleProjectSimpleConfigDryRun() {
+ Path baseDir = Path.of("./testcode/maven-projects/simple").toAbsolutePath().normalize();
+ PluginInvocationResult result = RewriteMavenPlugin.dryRun().recipes(RECIPES).onDir(baseDir);
+ String out = result.capturedOutput();
+ assertThat(result.success()).isTrue();
+ assertTasksExecuted(out, tasksOf(DEFAULT_GOALS, "dryRun"));
+ assertRecipesExecuted(out, RECIPES);
+ }
+
+ @Test
+ @DisplayName("builder dryRunNoFork")
+ void simpleProjectSimpleConfigDryRunNoFork() {
+ Path baseDir = Path.of("./testcode/maven-projects/simple").toAbsolutePath().normalize();
+ PluginInvocationResult result = RewriteMavenPlugin.dryRunNoFork().recipes(RECIPES).onDir(baseDir);
+ String out = result.capturedOutput();
+ assertThat(result.success()).isTrue();
+ assertTasksExecuted(out, "dryRunNoFork");
+ assertRecipesExecuted(out, RECIPES);
+ }
+
+ @Test
+ @DisplayName("builder discover")
+ void simpleProjectSimpleConfigDiscover() {
+ Path baseDir = Path.of("./testcode/maven-projects/simple").toAbsolutePath().normalize();
+ PluginInvocationResult result = RewriteMavenPlugin.discover().recipes(RECIPES).onDir(baseDir);
+ String out = result.capturedOutput();
+ assertThat(result.success()).isTrue();
+ assertTasksExecuted(out, "discover");
+ assertThat(out).contains("[INFO] Available Recipes:");
+ }
+
+ @Test
+ @DisplayName("builder cyclonedx")
+ void simpleProjectSimpleConfigCyclonedx() {
+ Path baseDir = Path.of("./testcode/maven-projects/simple").toAbsolutePath().normalize();
+ PluginInvocationResult result = RewriteMavenPlugin.cyclonedx().recipes(RECIPES).onDir(baseDir);
+ String out = result.capturedOutput();
+ System.out.println(out);
+ assertThat(result.success()).isTrue();
+ assertTasksExecuted(out, "cyclonedx");
+ }
+
+ @Test
+ @DisplayName("simple project full config")
+ void simpleProjectFullConfig() {
+
+ int port = TestSocketUtils.findAvailableTcpPort();
+ Path baseDir = Path.of("./testcode/maven-projects/simple").toAbsolutePath().normalize();
+ PluginInvocationResult result = RewriteMavenPlugin.run()
+ .recipes(EXTENDED_RECIPES)
+ .withDependencies(EXTENDED_REFCIPES_DEPS)
+ .withDebugger(port, false)
+ .withDebug()
+ .withMemory("1G", "4G")
+ .onDir(baseDir);
+
+ String out = result.capturedOutput();
+ assertThat(result.success()).isTrue();
+ assertMemory(out, "1G", "4G");
+ assertDebugConfig(out, port, false);
+ assertTasksExecuted(out, tasksOf(DEFAULT_GOALS, "run"));
+ assertRecipesExecuted(out, EXTENDED_RECIPES);
+ }
+
+ @Test
+ @DisplayName("execute dryRun")
+ void executeDryRun() {
+
+ int port = TestSocketUtils.findAvailableTcpPort();
+ Path baseDir = Path.of("./testcode/maven-projects/simple").toAbsolutePath().normalize();
+ MavenInvocationResult result = RewriteMavenPlugin.execute(baseDir, true, DebugConfig.from(port, false),
+ BuildConfig.builder().withMemory("1G", "4G").build(), RewriteMavenPlugin.Goal.DRY_RUN,
+ Arrays.asList(RECIPES), List.of());
+ String out = result.getCapturedLines();
+ assertDebugConfig(out, port, false);
+ assertMemory(out, "1G", "4G");
+ assertTasksExecuted(out, "dryRun");
+ }
+
+ @Test
+ @DisplayName("execute dryRunNoFork")
+ void executeDryRunNoFork() {
+ Path baseDir = Path.of("./testcode/maven-projects/simple").toAbsolutePath().normalize();
+ verify(baseDir, RewriteMavenPlugin.Goal.DRY_RUN_NO_FORK, "dryRunNoFork");
+ }
+
+ @Test
+ @DisplayName("execute run")
+ void executeRun() {
+ Path baseDir = Path.of("./testcode/maven-projects/simple").toAbsolutePath().normalize();
+ verify(baseDir, RewriteMavenPlugin.Goal.RUN, "run");
+ }
+
+ @Test
+ @DisplayName("execute runNoFork")
+ void executeRunNoFork() {
+ Path baseDir = Path.of("./testcode/maven-projects/simple").toAbsolutePath().normalize();
+ verify(baseDir, RewriteMavenPlugin.Goal.RUN_NO_FORK, "runNoFork");
+ }
+
+ @Test
+ @DisplayName("execute discover")
+ void executeDiscover() {
+ Path baseDir = Path.of("./testcode/maven-projects/simple").toAbsolutePath().normalize();
+ MavenInvocationResult result = RewriteMavenPlugin.execute(baseDir, false, DebugConfig.disabled(),
+ BuildConfig.fromDefault(), RewriteMavenPlugin.Goal.DISCOVER, Arrays.asList(EXTENDED_RECIPES),
+ List.of(EXTENDED_REFCIPES_DEPS));
+ String out = result.getCapturedLines();
+ assertThat(result.getExitCode()).isEqualTo(0);
+ assertTasksExecuted(out, "discover");
+ assertThat(out).contains("[INFO] Available Recipes:");
+ }
+
+ @Test
+ @DisplayName("execute cylonedx")
+ void executeCyclonedx() {
+ Path baseDir = Path.of("./testcode/maven-projects/simple").toAbsolutePath().normalize();
+ MavenInvocationResult result = RewriteMavenPlugin.execute(baseDir, false, DebugConfig.disabled(),
+ BuildConfig.fromDefault(), RewriteMavenPlugin.Goal.CYCLONEDX, Arrays.asList(EXTENDED_RECIPES),
+ List.of(EXTENDED_REFCIPES_DEPS));
+ String out = result.getCapturedLines();
+ assertThat(result.getExitCode()).isEqualTo(0);
+ assertTasksExecuted(out, "cyclonedx");
+ }
+
+ private void verify(Path baseDir, RewriteMavenPlugin.Goal runNoFork, String expectedGoal) {
+ MavenInvocationResult result = RewriteMavenPlugin.execute(baseDir, false, DebugConfig.disabled(),
+ BuildConfig.fromDefault(), runNoFork, Arrays.asList(EXTENDED_RECIPES), List.of(EXTENDED_REFCIPES_DEPS));
+ String out = result.getCapturedLines();
+ assertThat(result.getExitCode()).isEqualTo(0);
+ assertRecipesExecuted(out, EXTENDED_RECIPES);
+ assertTasksExecuted(out, expectedGoal);
+ }
+
+ private void assertTasksExecuted(String out, String... goals) {
+ if (goals.length == 0) {
+ fail("No goals provided");
+ }
+ Stream.of(goals).forEach(goal -> assertThat(out).contains(":" + goal + " "));
+ }
+
+ private String[] tasksOf(String[] defaultTasks, String rewriteTask) {
+ List tasksList = new ArrayList<>();
+ tasksList.addAll(Arrays.asList(defaultTasks));
+ tasksList.add(rewriteTask);
+ return tasksList.toArray(String[]::new);
+ }
+
+ private void assertRecipesExecuted(String out, String... recipes) {
+ assertThat(out)
+ .contains("active recipe(s) [%s]".formatted(Stream.of(recipes).collect(Collectors.joining(", "))));
+ }
+
+ private void assertMemory(String out, String min, String max) {
+ // Setting memory fails in GH Actions under Windows
+ if (!System.getenv().containsKey("GITHUB_ACTIONS") && !System.getProperty("os.name").contains("Windows")) {
+ assertThat(out).contains("env.MAVEN_OPTS= -Xms%s -Xmx%s".formatted(min, max));
+ }
+ }
+
+ private void assertDebugConfig(String out, int port, boolean suspend) {
+ assertThat(out).contains("Listening for transport dt_socket at address: %s".formatted(port),
+ "-Xrunjdwp:transport=dt_socket,server=y,suspend=%s,address=%s".formatted(suspend ? "y" : "n", port));
+ }
+
+}
\ No newline at end of file
diff --git a/spring-rewrite-commons-maven-invoker/testcode/maven-projects/simple/pom.xml b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-maven/testcode/maven-projects/simple/pom.xml
similarity index 100%
rename from spring-rewrite-commons-maven-invoker/testcode/maven-projects/simple/pom.xml
rename to spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-maven/testcode/maven-projects/simple/pom.xml
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-maven/testcode/maven-projects/simple/src/main/java/com/example/TheClass.java b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-maven/testcode/maven-projects/simple/src/main/java/com/example/TheClass.java
new file mode 100644
index 0000000..456aaff
--- /dev/null
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-maven/testcode/maven-projects/simple/src/main/java/com/example/TheClass.java
@@ -0,0 +1,5 @@
+package com.example;
+
+public class TheClass {
+
+}
\ No newline at end of file
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-maven/testcode/maven-projects/simple/src/test/java/com/example/TheClassTest.java b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-maven/testcode/maven-projects/simple/src/test/java/com/example/TheClassTest.java
new file mode 100644
index 0000000..9cc2285
--- /dev/null
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-maven/testcode/maven-projects/simple/src/test/java/com/example/TheClassTest.java
@@ -0,0 +1,5 @@
+package com.example;
+
+public class TheClassTest {
+
+}
\ No newline at end of file
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/pom.xml b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/pom.xml
new file mode 100644
index 0000000..eb066f0
--- /dev/null
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/pom.xml
@@ -0,0 +1,35 @@
+
+
+ 4.0.0
+
+ org.springframework.rewrite
+ spring-rewrite-commons-plugin-invoker
+ 0.1.0-SNAPSHOT
+
+
+ spring-rewrite-commons-plugin-invoker-polyglot
+
+
+ 17
+ 17
+ UTF-8
+
+
+
+
+ org.springframework.rewrite
+ spring-rewrite-commons-plugin-invoker-maven
+
+
+ org.springframework.rewrite
+ spring-rewrite-commons-plugin-invoker-gradle
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
\ No newline at end of file
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/src/main/java/org/springframework/rewrite/plugin/polyglot/RewritePlugin.java b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/src/main/java/org/springframework/rewrite/plugin/polyglot/RewritePlugin.java
new file mode 100644
index 0000000..7735cb6
--- /dev/null
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/src/main/java/org/springframework/rewrite/plugin/polyglot/RewritePlugin.java
@@ -0,0 +1,252 @@
+/*
+ * 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.rewrite.plugin.polyglot;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.rewrite.plugin.gradle.RewriteGradlePlugin;
+import org.springframework.rewrite.plugin.gradle.OpenRewriteGradlePluginBuilder;
+import org.springframework.rewrite.plugin.maven.RewriteMavenPlugin;
+import org.springframework.rewrite.plugin.maven.RewriteMavenPluginBuilder;
+import org.springframework.rewrite.plugin.shared.DebugConfig;
+import org.springframework.rewrite.plugin.shared.PluginInvocationResult;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author Fabian Krüger
+ */
+public class RewritePlugin implements OpenRewritePluginBuilder.GradlePluginVersion, OpenRewritePluginBuilder.Recipes,
+ OpenRewritePluginBuilder.FinalizingBuilder {
+
+ private static final Logger log = LoggerFactory.getLogger(RewriteGradlePlugin.class);
+
+ private Action action;
+
+ private String gradlePluginVersion;
+
+ private List recipes = new ArrayList<>();
+
+ private boolean debug;
+
+ private DebugConfig debugConfig = DebugConfig.disabled();
+
+ private List dependencies = new ArrayList<>();
+
+ private boolean preferGradle = false;
+
+ private String minMemory;
+
+ private String maxMemory;
+
+ public static OpenRewritePluginBuilder.GradlePluginVersion dryRun() {
+ RewritePlugin plugin = new RewritePlugin();
+ plugin.action = Action.DRY_RUN;
+ return plugin;
+ }
+
+ public static OpenRewritePluginBuilder.GradlePluginVersion run() {
+ RewritePlugin plugin = new RewritePlugin();
+ plugin.action = Action.RUN;
+ return plugin;
+ }
+
+ public static OpenRewritePluginBuilder.GradlePluginVersion discover() {
+ RewritePlugin plugin = new RewritePlugin();
+ plugin.action = Action.DISCOVER;
+ return plugin;
+ }
+
+ @Override
+ public OpenRewritePluginBuilder.Recipes gradlePluginVersion(String pluginVersion) {
+ this.gradlePluginVersion = pluginVersion;
+ return this;
+ }
+
+ @Override
+ public OpenRewritePluginBuilder.FinalizingBuilder recipes(String... recipes) {
+ this.recipes = Arrays.asList(recipes);
+ return this;
+ }
+
+ @Override
+ public PluginInvocationResult onDir(Path baseDir) {
+ PluginInvocationResult result;
+ boolean mavenProject = isMavenProject(baseDir);
+ boolean gradleProject = isGradleProject(baseDir);
+
+ if (gradleProject && mavenProject && preferGradle) {
+ result = executeGradle(baseDir);
+ }
+ else if (mavenProject) {
+ result = executeMaven(baseDir);
+ }
+ else if (gradleProject) {
+ result = executeGradle(baseDir);
+ }
+ else {
+ throw new IllegalArgumentException(
+ "Neither pom.xml, build.gradle, nor build.gradle.kts was found in '%s'".formatted(baseDir));
+ }
+ return new PluginInvocationResult(true, result.capturedOutput());
+ }
+
+ private boolean isPolyglotProject(Path baseDir) {
+ return isMavenProject(baseDir) && isGradleProject(baseDir);
+ }
+
+ private PluginInvocationResult executeGradle(Path baseDir) {
+ PluginInvocationResult result;
+ OpenRewriteGradlePluginBuilder.Recipes builder;
+ switch (action) {
+ case DRY_RUN -> builder = RewriteGradlePlugin.dryRun();
+ case DISCOVER -> builder = RewriteGradlePlugin.discover();
+ default -> builder = RewriteGradlePlugin.run();
+ }
+ OpenRewriteGradlePluginBuilder.FinalizingBuilder finalizingBuilder = builder
+ .recipes(recipes.toArray(String[]::new))
+ .usingPluginVersion(gradlePluginVersion);
+
+ if (minMemory != null) {
+ finalizingBuilder = finalizingBuilder.withMemory(minMemory, maxMemory);
+ }
+
+ if (debug) {
+ finalizingBuilder = finalizingBuilder.withDebug();
+ }
+
+ if (!dependencies.isEmpty()) {
+ finalizingBuilder.withDependencies(this.dependencies.toArray(String[]::new));
+ }
+
+ finalizingBuilder = finalizingBuilder.withDebugConfig(debugConfig);
+
+ result = finalizingBuilder.onDir(baseDir);
+ return result;
+ }
+
+ private PluginInvocationResult executeMaven(Path baseDir) {
+ PluginInvocationResult result;
+ RewriteMavenPluginBuilder.Recipes builder;
+ switch (action) {
+ case DRY_RUN -> builder = RewriteMavenPlugin.dryRun();
+ case DISCOVER -> builder = RewriteMavenPlugin.discover();
+ default -> builder = RewriteMavenPlugin.run();
+ }
+ RewriteMavenPluginBuilder.FinalizingBuilder finalizingBuilder = builder
+ .recipes(this.recipes.toArray(String[]::new));
+ if (minMemory != null) {
+ finalizingBuilder = finalizingBuilder.withMemory(minMemory, maxMemory);
+ }
+ if (debug) {
+ finalizingBuilder = finalizingBuilder.withDebug();
+ }
+ if (debugConfig != null) {
+ finalizingBuilder = finalizingBuilder.withDebugger(debugConfig.getPort(), debugConfig.isSuspend());
+ }
+ result = finalizingBuilder.onDir(baseDir);
+ return result;
+ }
+
+ private boolean isGradleProject(Path baseDir) {
+ return Files.exists(baseDir.resolve("build.gradle")) || Files.exists(baseDir.resolve("build.gradle.kts"));
+ }
+
+ private boolean isMavenProject(Path baseDir) {
+ return Files.exists(baseDir.resolve("pom.xml"));
+ }
+
+ @Override
+ public OpenRewritePluginBuilder.FinalizingBuilder dependencies(String... dependencies) {
+ this.dependencies = Arrays.asList(dependencies);
+ return this;
+ }
+
+ @Override
+ public OpenRewritePluginBuilder.FinalizingBuilder withMemory(String minMemory, String maxMemory) {
+ this.minMemory = minMemory;
+ this.maxMemory = maxMemory;
+ return this;
+ }
+
+ @Override
+ public OpenRewritePluginBuilder.FinalizingBuilder withDebugging() {
+ return this;
+ }
+
+ @Override
+ public OpenRewritePluginBuilder.FinalizingBuilder withDebugging(int port, boolean suspend) {
+ this.debugConfig = DebugConfig.from(port, suspend);
+ return this;
+ }
+
+ @Override
+ public OpenRewritePluginBuilder.FinalizingBuilder withDebug() {
+ this.debug = true;
+ return this;
+ }
+
+ @Override
+ public OpenRewritePluginBuilder.FinalizingBuilder preferGradle() {
+ this.preferGradle = true;
+ return this;
+ }
+
+ public enum Action {
+
+ RUN, DRY_RUN, DISCOVER
+
+ }
+
+}
+
+class OpenRewritePluginBuilder {
+
+ public interface GradlePluginVersion {
+
+ Recipes gradlePluginVersion(String pluginVersion);
+
+ }
+
+ public interface Recipes {
+
+ OpenRewritePluginBuilder.FinalizingBuilder recipes(String... recipes);
+
+ }
+
+ public interface FinalizingBuilder {
+
+ PluginInvocationResult onDir(Path baseDir);
+
+ FinalizingBuilder dependencies(String... dependencies);
+
+ FinalizingBuilder withMemory(String min, String max);
+
+ FinalizingBuilder withDebugging();
+
+ FinalizingBuilder withDebugging(int port, boolean suspend);
+
+ FinalizingBuilder withDebug();
+
+ FinalizingBuilder preferGradle();
+
+ }
+
+}
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/src/test/java/org/springframework/rewrite/plugin/polyglot/RewritePluginTest.java b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/src/test/java/org/springframework/rewrite/plugin/polyglot/RewritePluginTest.java
new file mode 100644
index 0000000..a8f12eb
--- /dev/null
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/src/test/java/org/springframework/rewrite/plugin/polyglot/RewritePluginTest.java
@@ -0,0 +1,288 @@
+/*
+ * 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.rewrite.plugin.polyglot;
+
+import org.apache.commons.lang3.stream.Streams;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.springframework.rewrite.plugin.shared.PluginInvocationResult;
+import org.springframework.test.util.TestSocketUtils;
+
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.fail;
+
+/**
+ * @author Fabian Krüger
+ */
+public class RewritePluginTest {
+
+ public static final String[] RECIPES = { "org.openrewrite.java.RemoveUnusedImports",
+ "org.openrewrite.java.format.NormalizeLineBreaks" };
+
+ public static final String[] EXTENDED_RECIPES = Stream
+ .concat(Stream.of(RECIPES), Stream.of("org.openrewrite.java.migrate.jakarta.MaybeAddJakartaServletApi"))
+ .toList()
+ .toArray(String[]::new);
+
+ public static final String EXTENDED_RECIPES_DEPS = "org.openrewrite.recipe:rewrite-migrate-java:2.9.0";
+
+ @Nested
+ class PolyglotTests {
+
+ @Test
+ @DisplayName("should prefer Maven over Gradle by default")
+ void shouldPreferMavenOverGradle() {
+ Path baseDir = Path.of("./testcode/polyglot-projects/simple-polyglot").toAbsolutePath().normalize();
+ PluginInvocationResult result = RewritePlugin.run()
+ .gradlePluginVersion("6.10.0")
+ .recipes(RECIPES)
+ .onDir(baseDir);
+
+ assertThat(result.capturedOutput()).contains("[INFO] >>> rewrite-maven-plugin:");
+ }
+
+ @Test
+ @DisplayName("should prefer Gradle over Maven with flag")
+ void shouldPreferGradleOverMavenWithFlag() {
+ Path baseDir = Path.of("./testcode/polyglot-projects/simple-polyglot").toAbsolutePath().normalize();
+ PluginInvocationResult result = RewritePlugin.run()
+ .gradlePluginVersion("6.10.0")
+ .recipes(RECIPES)
+ .preferGradle()
+ .onDir(baseDir);
+
+ assertThat(result.capturedOutput()).contains("> Task :rewriteRun");
+ }
+
+ }
+
+ @Nested
+ class MavenTests {
+
+ public static final String[] DEFAULT_GOALS = new String[] { "resources", "compile", "testResources",
+ "testCompile" };
+
+ @Test
+ @DisplayName("simple Maven run")
+ void simpleMavenRun() {
+ Path baseDir = Path.of("./testcode/maven-projects/simple").toAbsolutePath().normalize();
+ verify(RewritePlugin.run(), baseDir, "run");
+ }
+
+ @Test
+ @DisplayName("simple Maven dryRun")
+ void simpleMavenDryRun() {
+ Path baseDir = Path.of("./testcode/maven-projects/simple").toAbsolutePath().normalize();
+ verify(RewritePlugin.dryRun(), baseDir, "dryRun");
+ }
+
+ @Test
+ @DisplayName("simple Maven discover")
+ void simpleMavenDiscover() {
+ Path baseDir = Path.of("./testcode/maven-projects/simple").toAbsolutePath().normalize();
+ PluginInvocationResult result = RewritePlugin.discover()
+ .gradlePluginVersion("1.2.3")
+ .recipes(RECIPES)
+ .onDir(baseDir);
+
+ assertBuildSuccessful(result);
+ String out = result.capturedOutput();
+ assertGoalsExecuted(out, "discover");
+ assertThat(out).contains("[INFO] Available Recipes:");
+ }
+
+ @Test
+ @DisplayName("simple Maven full api")
+ void simpleMavenFullApi() {
+ int port = TestSocketUtils.findAvailableTcpPort();
+ Path baseDir = Path.of("./testcode/maven-projects/simple").toAbsolutePath().normalize();
+ PluginInvocationResult result = RewritePlugin.run()
+ .gradlePluginVersion("6.10.0")
+ .recipes(EXTENDED_RECIPES)
+ .dependencies(EXTENDED_RECIPES_DEPS)
+ .withMemory("18M", "280M")
+ .withDebug()
+ .withDebugging(port, false)
+ .onDir(baseDir);
+ assertBuildSuccessful(result);
+ String out = result.capturedOutput();
+ assertGoalsExecuted(out, DEFAULT_GOALS, "run");
+ assertMemory(out, "18M", "280M");
+ assertDebugConfig(out, port, false);
+ assertRecipesExecuted(out, EXTENDED_RECIPES);
+ }
+
+ private void verify(OpenRewritePluginBuilder.GradlePluginVersion rewriteGoalExecution, Path baseDir,
+ String rewriteGoal) {
+ PluginInvocationResult result = rewriteGoalExecution.gradlePluginVersion("1.2.3")
+ .recipes(RECIPES)
+ .onDir(baseDir);
+
+ assertBuildSuccessful(result);
+ String out = result.capturedOutput();
+ assertGoalsExecuted(out, DEFAULT_GOALS, rewriteGoal);
+ assertRecipesExecuted(out, RECIPES);
+ }
+
+ private void assertMemory(String out, String min, String max) {
+ // Setting memory fails in GH Actions under Windows
+ if (!System.getenv().containsKey("GITHUB_ACTIONS") && !System.getProperty("os.name").contains("Windows")) {
+ assertThat(out).contains("env.MAVEN_OPTS= -Xms%s -Xmx%s".formatted(min, max));
+ }
+ }
+
+ private void assertDebugConfig(String out, int port, boolean suspend) {
+ assertThat(out).contains("Listening for transport dt_socket at address: %s".formatted(port),
+ "-Xrunjdwp:transport=dt_socket,server=y,suspend=%s,address=%s".formatted(suspend ? "y" : "n",
+ port));
+ }
+
+ private void assertBuildSuccessful(PluginInvocationResult result) {
+ assertThat(result.success()).isTrue();
+ }
+
+ private void assertGoalsExecuted(String out, String... goals) {
+ if (goals.length == 0) {
+ fail("No goals provided");
+ }
+ Stream.of(goals).forEach(goal -> assertThat(out).contains(":" + goal + " "));
+ }
+
+ private void assertGoalsExecuted(String out, String[] defaultTasks, String rewriteTask) {
+ String[] tasks = tasksOf(defaultTasks, rewriteTask);
+ Streams.of(tasks).forEach(t -> assertThat(out).contains(t));
+ }
+
+ private void assertRecipesExecuted(String out, String... recipes) {
+ assertThat(out)
+ .contains("active recipe(s) [%s]".formatted(Stream.of(recipes).collect(Collectors.joining(", "))));
+ }
+
+ }
+
+ @Nested
+ class GradleTests {
+
+ public static final Path BASE_DIR = Path.of("./testcode/gradle-projects/simple").toAbsolutePath().normalize();
+
+ public static final String[] DEFAULT_TASKS = new String[] { "compileJava", "processResources", "classes",
+ "compileTestJava", "rewriteResolveDependencies" };
+
+ @Test
+ @DisplayName("simple Gradle run")
+ void simpleGradleRun() {
+ verify(RewritePlugin.run(), "rewriteRun");
+ }
+
+ @Test
+ @DisplayName("simple Gradle dryRun")
+ void simpleGradleDryRun() {
+ verify(RewritePlugin.dryRun(), "rewriteDryRun");
+ }
+
+ @Test
+ @DisplayName("simple Gradle discover")
+ void simpleGradleDiscover() {
+ PluginInvocationResult result = RewritePlugin.discover()
+ .gradlePluginVersion("6.10.0")
+ .recipes(RECIPES)
+ .onDir(BASE_DIR);
+
+ String out = result.capturedOutput();
+ assertSuccessfulBuild(out);
+ assertTasksExecuted(out, "rewriteDiscover");
+ assertThat(out).contains("Available Recipes:");
+ }
+
+ @Test
+ @DisplayName("simple Gradle full API")
+ void simpleGradleFullApi() {
+ int port = TestSocketUtils.findAvailableTcpPort();
+ Path baseDir = Path.of("./testcode/gradle-projects/simple").toAbsolutePath().normalize();
+ PluginInvocationResult result = RewritePlugin.run()
+ .gradlePluginVersion("6.10.0")
+ .recipes(EXTENDED_RECIPES)
+ .dependencies(EXTENDED_RECIPES_DEPS)
+ .withDebug()
+ .withMemory("64M", "484M")
+ .withDebugging(port, false)
+ .onDir(baseDir);
+
+ assertThat(result.success()).isTrue();
+ String out = result.capturedOutput();
+ assertSuccessfulBuild(out);
+ assertMemory(out, "64M", "484M");
+ assertDebugConfig(out, port, false);
+ assertTasksExecuted(out, DEFAULT_TASKS, "rewriteRun");
+ assertRecipesExecuted(out, EXTENDED_RECIPES);
+ }
+
+ private void verify(OpenRewritePluginBuilder.GradlePluginVersion run, String run1) {
+ PluginInvocationResult result = run.gradlePluginVersion("6.10.0").recipes(RECIPES).onDir(BASE_DIR);
+
+ String out = result.capturedOutput();
+ assertSuccessfulBuild(out);
+ assertTasksExecuted(out, DEFAULT_TASKS, run1);
+ assertRecipesExecuted(out, RECIPES);
+ }
+
+ private void assertMemory(String out, String min, String max) {
+ assertThat(out).contains("-Xms%s".formatted(min));
+ assertThat(out).contains("-Xmx%s".formatted(max));
+ }
+
+ private void assertDebugConfig(String out, int port, boolean suspend) {
+ assertThat(out).contains("-agentlib:jdwp=transport=dt_socket,server=y,suspend=%s,address=%s"
+ .formatted(suspend ? "y" : "n", port));
+ }
+
+ private void assertSuccessfulBuild(String out) {
+ assertThat(out).contains("BUILD SUCCESSFUL in");
+ }
+
+ private void assertTasksExecuted(String out, String[] defaultTasks, String rewriteTask) {
+ String[] tasks = tasksOf(defaultTasks, rewriteTask);
+ assertTasksExecuted(out, tasks);
+ }
+
+ private static void assertTasksExecuted(String out, String... tasks) {
+ List tasksOutput = Stream.of(tasks).map(t -> "Task :" + t).toList();
+ assertThat(out).contains(tasksOutput);
+ }
+
+ private void assertRecipesExecuted(String out, String[] recipes) {
+ assertThat(out).containsIgnoringWhitespaces("All sources parsed, running active recipes: "
+ + Stream.of(recipes).collect(Collectors.joining(",")));
+ }
+
+ }
+
+ private String[] tasksOf(String[] defaultTasks, String rewriteTask) {
+ List tasksList = new ArrayList<>();
+ tasksList.addAll(Arrays.asList(defaultTasks));
+ tasksList.add(rewriteTask);
+ return tasksList.toArray(String[]::new);
+ }
+
+}
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/gradle-projects/simple/.gitignore b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/gradle-projects/simple/.gitignore
new file mode 100644
index 0000000..b63da45
--- /dev/null
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/gradle-projects/simple/.gitignore
@@ -0,0 +1,42 @@
+.gradle
+build/
+!gradle/wrapper/gradle-wrapper.jar
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### IntelliJ IDEA ###
+.idea/modules.xml
+.idea/jarRepositories.xml
+.idea/compiler.xml
+.idea/libraries/
+*.iws
+*.iml
+*.ipr
+out/
+!**/src/main/**/out/
+!**/src/test/**/out/
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+bin/
+!**/src/main/**/bin/
+!**/src/test/**/bin/
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store
\ No newline at end of file
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/gradle-projects/simple/build.gradle.kts b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/gradle-projects/simple/build.gradle.kts
new file mode 100644
index 0000000..a6c5d7d
--- /dev/null
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/gradle-projects/simple/build.gradle.kts
@@ -0,0 +1,19 @@
+plugins {
+ id("java")
+}
+
+group = "org.example"
+version = "1.0-SNAPSHOT"
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ testImplementation(platform("org.junit:junit-bom:5.9.1"))
+ testImplementation("org.junit.jupiter:junit-jupiter")
+}
+
+tasks.test {
+ useJUnitPlatform()
+}
\ No newline at end of file
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/gradle-projects/simple/gradle/wrapper/gradle-wrapper.jar b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/gradle-projects/simple/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..249e583
Binary files /dev/null and b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/gradle-projects/simple/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/gradle-projects/simple/gradle/wrapper/gradle-wrapper.properties b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/gradle-projects/simple/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..f027096
--- /dev/null
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/gradle-projects/simple/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Wed Mar 13 15:37:19 CET 2024
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/gradle-projects/simple/gradlew b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/gradle-projects/simple/gradlew
new file mode 100755
index 0000000..1b6c787
--- /dev/null
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/gradle-projects/simple/gradlew
@@ -0,0 +1,234 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original 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.
+#
+
+##############################################################################
+#
+# Gradle start up script for POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
+done
+
+APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
+
+APP_NAME="Gradle"
+APP_BASE_NAME=${0##*/}
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+ echo "$*"
+} >&2
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in #(
+ CYGWIN* ) cygwin=true ;; #(
+ Darwin* ) darwin=true ;; #(
+ MSYS* | MINGW* ) msys=true ;; #(
+ NONSTOP* ) nonstop=true ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD=$JAVA_HOME/jre/sh/java
+ else
+ JAVACMD=$JAVA_HOME/bin/java
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD=java
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
+ esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
+ fi
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
+ done
+fi
+
+# Collect all arguments for the java command;
+# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
+# shell script including quotes and variable substitutions, so put them in
+# double quotes to make sure that they get re-expanded; and
+# * put everything else in single quotes, so that it's not re-expanded.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ org.gradle.wrapper.GradleWrapperMain \
+ "$@"
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/gradle-projects/simple/gradlew.bat b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/gradle-projects/simple/gradlew.bat
new file mode 100644
index 0000000..107acd3
--- /dev/null
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/gradle-projects/simple/gradlew.bat
@@ -0,0 +1,89 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/gradle-projects/simple/settings.gradle.kts b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/gradle-projects/simple/settings.gradle.kts
new file mode 100644
index 0000000..474bc17
--- /dev/null
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/gradle-projects/simple/settings.gradle.kts
@@ -0,0 +1,2 @@
+rootProject.name = "simple"
+
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/gradle-projects/simple/src/main/java/org/example/Main.java b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/gradle-projects/simple/src/main/java/org/example/Main.java
new file mode 100644
index 0000000..9f3c33a
--- /dev/null
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/gradle-projects/simple/src/main/java/org/example/Main.java
@@ -0,0 +1,10 @@
+package org.example;
+
+/**
+ * @author Fabian Krüger
+ */
+public class Main {
+ public static void main(String[] args) {
+ System.out.println("Hello world!");
+ }
+}
\ No newline at end of file
diff --git a/spring-rewrite-commons-maven-invoker/testcode/maven-projects/resources/application/pom.xml b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/maven-projects/resources/application/pom.xml
similarity index 100%
rename from spring-rewrite-commons-maven-invoker/testcode/maven-projects/resources/application/pom.xml
rename to spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/maven-projects/resources/application/pom.xml
diff --git a/spring-rewrite-commons-maven-invoker/testcode/maven-projects/resources/application/src/main/resources/some-resource.properties b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/maven-projects/resources/application/src/main/resources/some-resource.properties
similarity index 100%
rename from spring-rewrite-commons-maven-invoker/testcode/maven-projects/resources/application/src/main/resources/some-resource.properties
rename to spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/maven-projects/resources/application/src/main/resources/some-resource.properties
diff --git a/spring-rewrite-commons-maven-invoker/testcode/maven-projects/resources/application/src/test/resources/some-resource.properties b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/maven-projects/resources/application/src/test/resources/some-resource.properties
similarity index 100%
rename from spring-rewrite-commons-maven-invoker/testcode/maven-projects/resources/application/src/test/resources/some-resource.properties
rename to spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/maven-projects/resources/application/src/test/resources/some-resource.properties
diff --git a/spring-rewrite-commons-maven-invoker/testcode/maven-projects/resources/component/pom.xml b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/maven-projects/resources/component/pom.xml
similarity index 100%
rename from spring-rewrite-commons-maven-invoker/testcode/maven-projects/resources/component/pom.xml
rename to spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/maven-projects/resources/component/pom.xml
diff --git a/spring-rewrite-commons-maven-invoker/testcode/maven-projects/resources/pom.xml b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/maven-projects/resources/pom.xml
similarity index 100%
rename from spring-rewrite-commons-maven-invoker/testcode/maven-projects/resources/pom.xml
rename to spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/maven-projects/resources/pom.xml
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/maven-projects/simple/pom.xml b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/maven-projects/simple/pom.xml
new file mode 100644
index 0000000..df899a0
--- /dev/null
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/maven-projects/simple/pom.xml
@@ -0,0 +1,16 @@
+
+
+ 4.0.0
+ com.example.maven
+ simple
+ 0.1.0-SNAPSHOT
+
+
+ 17
+ 17
+ UTF-8
+
+
+
\ No newline at end of file
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/maven-projects/simple/src/main/java/com/example/TheClass.java b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/maven-projects/simple/src/main/java/com/example/TheClass.java
new file mode 100644
index 0000000..456aaff
--- /dev/null
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/maven-projects/simple/src/main/java/com/example/TheClass.java
@@ -0,0 +1,5 @@
+package com.example;
+
+public class TheClass {
+
+}
\ No newline at end of file
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/maven-projects/simple/src/test/java/com/example/TheClassTest.java b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/maven-projects/simple/src/test/java/com/example/TheClassTest.java
new file mode 100644
index 0000000..9cc2285
--- /dev/null
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/maven-projects/simple/src/test/java/com/example/TheClassTest.java
@@ -0,0 +1,5 @@
+package com.example;
+
+public class TheClassTest {
+
+}
\ No newline at end of file
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/polyglot-projects/simple-polyglot/.gitignore b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/polyglot-projects/simple-polyglot/.gitignore
new file mode 100644
index 0000000..eff4362
--- /dev/null
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/polyglot-projects/simple-polyglot/.gitignore
@@ -0,0 +1,43 @@
+.gradle
+build/
+!gradle/wrapper/gradle-wrapper.jar
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### IntelliJ IDEA ###
+.idea/modules.xml
+.idea/jarRepositories.xml
+.idea/compiler.xml
+.idea/libraries/
+*.iws
+*.iml
+*.ipr
+out/
+!**/src/main/**/out/
+!**/src/test/**/out/
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+bin/
+!**/src/main/**/bin/
+!**/src/test/**/bin/
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store
+/target/
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/polyglot-projects/simple-polyglot/build.gradle.kts b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/polyglot-projects/simple-polyglot/build.gradle.kts
new file mode 100644
index 0000000..b6e5cd3
--- /dev/null
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/polyglot-projects/simple-polyglot/build.gradle.kts
@@ -0,0 +1,19 @@
+plugins {
+ id("java")
+}
+
+group = "org.example"
+version = "1.0.0-SNAPSHOT"
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ testImplementation(platform("org.junit:junit-bom:5.9.1"))
+ testImplementation("org.junit.jupiter:junit-jupiter")
+}
+
+tasks.test {
+ useJUnitPlatform()
+}
\ No newline at end of file
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/polyglot-projects/simple-polyglot/gradle/wrapper/gradle-wrapper.jar b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/polyglot-projects/simple-polyglot/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..249e583
Binary files /dev/null and b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/polyglot-projects/simple-polyglot/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/polyglot-projects/simple-polyglot/gradle/wrapper/gradle-wrapper.properties b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/polyglot-projects/simple-polyglot/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..1116658
--- /dev/null
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/polyglot-projects/simple-polyglot/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Fri Mar 15 13:11:41 CET 2024
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/polyglot-projects/simple-polyglot/gradlew b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/polyglot-projects/simple-polyglot/gradlew
new file mode 100755
index 0000000..1b6c787
--- /dev/null
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/polyglot-projects/simple-polyglot/gradlew
@@ -0,0 +1,234 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original 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.
+#
+
+##############################################################################
+#
+# Gradle start up script for POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
+done
+
+APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
+
+APP_NAME="Gradle"
+APP_BASE_NAME=${0##*/}
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+ echo "$*"
+} >&2
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in #(
+ CYGWIN* ) cygwin=true ;; #(
+ Darwin* ) darwin=true ;; #(
+ MSYS* | MINGW* ) msys=true ;; #(
+ NONSTOP* ) nonstop=true ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD=$JAVA_HOME/jre/sh/java
+ else
+ JAVACMD=$JAVA_HOME/bin/java
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD=java
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
+ esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
+ fi
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
+ done
+fi
+
+# Collect all arguments for the java command;
+# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
+# shell script including quotes and variable substitutions, so put them in
+# double quotes to make sure that they get re-expanded; and
+# * put everything else in single quotes, so that it's not re-expanded.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ org.gradle.wrapper.GradleWrapperMain \
+ "$@"
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/polyglot-projects/simple-polyglot/gradlew.bat b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/polyglot-projects/simple-polyglot/gradlew.bat
new file mode 100644
index 0000000..107acd3
--- /dev/null
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/polyglot-projects/simple-polyglot/gradlew.bat
@@ -0,0 +1,89 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/polyglot-projects/simple-polyglot/pom.xml b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/polyglot-projects/simple-polyglot/pom.xml
new file mode 100644
index 0000000..f0496dd
--- /dev/null
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/polyglot-projects/simple-polyglot/pom.xml
@@ -0,0 +1,16 @@
+
+
+ 4.0.0
+ org.example
+ simple-ployglot
+ 1.0-SNAPSHOT
+
+
+ 17
+ 17
+ UTF-8
+
+
+
\ No newline at end of file
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/polyglot-projects/simple-polyglot/settings.gradle.kts b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/polyglot-projects/simple-polyglot/settings.gradle.kts
new file mode 100644
index 0000000..40b3f3f
--- /dev/null
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/polyglot-projects/simple-polyglot/settings.gradle.kts
@@ -0,0 +1,2 @@
+rootProject.name = "simple-polyglot"
+
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/polyglot-projects/simple-polyglot/src/main/java/org/example/Main.java b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/polyglot-projects/simple-polyglot/src/main/java/org/example/Main.java
new file mode 100644
index 0000000..9f3c33a
--- /dev/null
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-polyglot/testcode/polyglot-projects/simple-polyglot/src/main/java/org/example/Main.java
@@ -0,0 +1,10 @@
+package org.example;
+
+/**
+ * @author Fabian Krüger
+ */
+public class Main {
+ public static void main(String[] args) {
+ System.out.println("Hello world!");
+ }
+}
\ No newline at end of file
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-shared/pom.xml b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-shared/pom.xml
new file mode 100644
index 0000000..af88635
--- /dev/null
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-shared/pom.xml
@@ -0,0 +1,20 @@
+
+
+ 4.0.0
+
+ org.springframework.rewrite
+ spring-rewrite-commons-plugin-invoker
+ 0.1.0-SNAPSHOT
+
+
+ spring-rewrite-commons-plugin-invoker-shared
+
+
+ 17
+ 17
+ UTF-8
+
+
+
\ No newline at end of file
diff --git a/spring-rewrite-commons-maven-invoker/src/main/java/org/springframework/rewrite/maven/BuildConfig.java b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-shared/src/main/java/org/springframework/rewrite/plugin/shared/BuildConfig.java
similarity index 82%
rename from spring-rewrite-commons-maven-invoker/src/main/java/org/springframework/rewrite/maven/BuildConfig.java
rename to spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-shared/src/main/java/org/springframework/rewrite/plugin/shared/BuildConfig.java
index 3567aa6..048074f 100644
--- a/spring-rewrite-commons-maven-invoker/src/main/java/org/springframework/rewrite/maven/BuildConfig.java
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-shared/src/main/java/org/springframework/rewrite/plugin/shared/BuildConfig.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.springframework.rewrite.maven;
+package org.springframework.rewrite.plugin.shared;
/**
* @author Fabian Krüger
@@ -46,7 +46,11 @@ public class BuildConfig {
return new Builder();
}
- boolean isSkipTests() {
+ public static BuildConfig fromDefault() {
+ return new BuildConfig(true, MemorySettings.noop());
+ }
+
+ public boolean isSkipTests() {
return skipTests;
}
@@ -54,11 +58,15 @@ public class BuildConfig {
return memorySettings;
}
+ public boolean hasMemorySettings() {
+ return memorySettings != null && memorySettings.getMin() != null;
+ }
+
public static class Builder {
private boolean skipTests;
- private MemorySettings memorySettings = MemorySettings.of("31M", "256M");
+ private MemorySettings memorySettings = MemorySettings.of("256M", "1024M");
public Builder skipTests(boolean b) {
this.skipTests = b;
diff --git a/spring-rewrite-commons-maven-invoker/src/main/java/org/springframework/rewrite/maven/MavenInvoker.java b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-shared/src/main/java/org/springframework/rewrite/plugin/shared/BuildTool.java
similarity index 65%
rename from spring-rewrite-commons-maven-invoker/src/main/java/org/springframework/rewrite/maven/MavenInvoker.java
rename to spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-shared/src/main/java/org/springframework/rewrite/plugin/shared/BuildTool.java
index 3b1f278..a58f783 100644
--- a/spring-rewrite-commons-maven-invoker/src/main/java/org/springframework/rewrite/maven/MavenInvoker.java
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-shared/src/main/java/org/springframework/rewrite/plugin/shared/BuildTool.java
@@ -13,24 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.springframework.rewrite.maven;
-
-import org.apache.maven.shared.invoker.*;
+package org.springframework.rewrite.plugin.shared;
/**
* @author Fabian Krüger
*/
-public class MavenInvoker {
+public enum BuildTool {
- private Invoker invoker = new DefaultInvoker();
-
- public InvocationResult invoke(InvocationRequest request) {
- try {
- return invoker.execute(request);
- }
- catch (MavenInvocationException e) {
- throw new RuntimeException(e);
- }
- }
+ GRADLE, MAVEN
}
diff --git a/spring-rewrite-commons-maven-invoker/src/main/java/org/springframework/rewrite/maven/DebugConfig.java b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-shared/src/main/java/org/springframework/rewrite/plugin/shared/DebugConfig.java
similarity index 91%
rename from spring-rewrite-commons-maven-invoker/src/main/java/org/springframework/rewrite/maven/DebugConfig.java
rename to spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-shared/src/main/java/org/springframework/rewrite/plugin/shared/DebugConfig.java
index 08d968b..61dbc3c 100644
--- a/spring-rewrite-commons-maven-invoker/src/main/java/org/springframework/rewrite/maven/DebugConfig.java
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-shared/src/main/java/org/springframework/rewrite/plugin/shared/DebugConfig.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.springframework.rewrite.maven;
+package org.springframework.rewrite.plugin.shared;
/**
* @author Fabian Krüger
@@ -48,7 +48,11 @@ public class DebugConfig {
return port;
}
- public char isSuspend() {
+ public boolean isSuspend() {
+ return suspend;
+ }
+
+ public char isSuspendEnabled() {
return suspend ? 'y' : 'n';
}
diff --git a/spring-rewrite-commons-maven-invoker/src/main/java/org/springframework/rewrite/maven/MemorySettings.java b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-shared/src/main/java/org/springframework/rewrite/plugin/shared/MemorySettings.java
similarity index 88%
rename from spring-rewrite-commons-maven-invoker/src/main/java/org/springframework/rewrite/maven/MemorySettings.java
rename to spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-shared/src/main/java/org/springframework/rewrite/plugin/shared/MemorySettings.java
index 71eb5eb..fdbaa4a 100644
--- a/spring-rewrite-commons-maven-invoker/src/main/java/org/springframework/rewrite/maven/MemorySettings.java
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-shared/src/main/java/org/springframework/rewrite/plugin/shared/MemorySettings.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.springframework.rewrite.maven;
+package org.springframework.rewrite.plugin.shared;
/**
* @author Fabian Krüger
@@ -33,6 +33,10 @@ public class MemorySettings {
return new MemorySettings(min, max);
}
+ public static MemorySettings noop() {
+ return new MemorySettings(null, null);
+ }
+
public String getMin() {
return min;
}
diff --git a/spring-rewrite-commons-maven-invoker/src/main/java/org/springframework/rewrite/maven/RewritePluginGoals.java b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-shared/src/main/java/org/springframework/rewrite/plugin/shared/PluginInvocationResult.java
similarity index 63%
rename from spring-rewrite-commons-maven-invoker/src/main/java/org/springframework/rewrite/maven/RewritePluginGoals.java
rename to spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-shared/src/main/java/org/springframework/rewrite/plugin/shared/PluginInvocationResult.java
index 9429b1e..bf252ed 100644
--- a/spring-rewrite-commons-maven-invoker/src/main/java/org/springframework/rewrite/maven/RewritePluginGoals.java
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-shared/src/main/java/org/springframework/rewrite/plugin/shared/PluginInvocationResult.java
@@ -13,24 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.springframework.rewrite.maven;
+package org.springframework.rewrite.plugin.shared;
/**
* @author Fabian Krüger
*/
-public enum RewritePluginGoals {
-
- RUN("run"), RUN_NO_FORK("runNoFork"), DRY_RUN("dryRun"), DRY_RUN_NO_FORK("dryRunNoFork"), DISCOVER("discover"),
- CYCLONEDX("cyclonedx");
-
- private final String goalName;
-
- RewritePluginGoals(String goalName) {
- this.goalName = goalName;
- }
-
- public String getGoalName() {
- return goalName;
- }
-
+public record PluginInvocationResult(boolean success, String capturedOutput) {
}
diff --git a/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-shared/src/main/java/org/springframework/rewrite/plugin/shared/RewritePluginGoals.java b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-shared/src/main/java/org/springframework/rewrite/plugin/shared/RewritePluginGoals.java
new file mode 100644
index 0000000..36b97f3
--- /dev/null
+++ b/spring-rewrite-commons-plugin-invoker/spring-rewrite-commons-plugin-invoker-shared/src/main/java/org/springframework/rewrite/plugin/shared/RewritePluginGoals.java
@@ -0,0 +1,44 @@
+/*
+ * 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.rewrite.plugin.shared;
+
+/**
+ * @author Fabian Krüger
+ */
+public enum RewritePluginGoals {
+
+ RUN("run", "rewriteRun"), RUN_NO_FORK("runNoFork", "rewriteRun"), DRY_RUN("dryRun", "rewriteDryRun"),
+ DRY_RUN_NO_FORK("dryRunNoFork", "rewriteDryRun"), DISCOVER("discover", "rewriteDiscover"),
+ CYCLONEDX("cyclonedx", null);
+
+ private final String maven;
+
+ private final String gradle;
+
+ RewritePluginGoals(String maven, String gradle) {
+ this.maven = maven;
+ this.gradle = gradle;
+ }
+
+ public String getMaven() {
+ return maven;
+ }
+
+ public String getGradle() {
+ return gradle;
+ }
+
+}