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; + } + +}