Add Maven launcher using Maven Invoker
This commit is contained in:
22
README.adoc
22
README.adoc
@@ -12,6 +12,28 @@ ____
|
||||
|
||||
== Get started
|
||||
|
||||
=== Modules
|
||||
|
||||
[plantuml,"models",svg]
|
||||
.....
|
||||
component srcMaven as "src-maven" {
|
||||
component srcMavenInvoker as "src-maven-invoker" {
|
||||
}
|
||||
component srcMavenEmbedder as "src-maven-embedder" {
|
||||
}
|
||||
}
|
||||
|
||||
component srcGradle as "src-gradle" {
|
||||
component srcGradleModel as "src-gradle-model" {
|
||||
}
|
||||
component srcGradleParser as "src-gradle-parser" {
|
||||
}
|
||||
component srcGradlePlugin as "src-gradle-plugin" {
|
||||
}
|
||||
}
|
||||
}
|
||||
.....
|
||||
|
||||
=== Add Dependency
|
||||
|
||||
**Maven**
|
||||
|
||||
7
pom.xml
7
pom.xml
@@ -17,6 +17,7 @@
|
||||
<module>spring-rewrite-commons-examples</module>
|
||||
<module>spring-rewrite-commons-starters</module>
|
||||
<module>spring-rewrite-commons-gradle</module>
|
||||
<module>spring-rewrite-commons-maven-invoker</module>
|
||||
</modules>
|
||||
|
||||
<organization>
|
||||
@@ -110,6 +111,12 @@
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit-pioneer</groupId>
|
||||
<artifactId>junit-pioneer</artifactId>
|
||||
<version>${junit-pioneer.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
|
||||
99
spring-rewrite-commons-maven-invoker/pom.xml
Normal file
99
spring-rewrite-commons-maven-invoker/pom.xml
Normal file
@@ -0,0 +1,99 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.rewrite</groupId>
|
||||
<artifactId>spring-rewrite-commons</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>spring-rewrite-commons-maven-invoker</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.shared</groupId>
|
||||
<artifactId>maven-shared-utils</artifactId>
|
||||
<version>3.4.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.shared</groupId>
|
||||
<artifactId>maven-invoker</artifactId>
|
||||
<version>${maven-invoker.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.resolver</groupId>
|
||||
<artifactId>maven-resolver-util</artifactId>
|
||||
<version>${maven-resolver.version}</version> <!-- Please check for the latest version available -->
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openrewrite.maven</groupId>
|
||||
<artifactId>rewrite-maven-plugin</artifactId>
|
||||
<version>${rewrite-maven-plugin.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.resolver</groupId>
|
||||
<artifactId>maven-resolver-api</artifactId>
|
||||
<version>${maven-resolver.version}</version> <!-- Check for the latest version -->
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.resolver</groupId>
|
||||
<artifactId>maven-resolver-impl</artifactId>
|
||||
<version>${maven-resolver.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.resolver</groupId>
|
||||
<artifactId>maven-resolver-transport-wagon</artifactId>
|
||||
<version>${maven-resolver.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.resolver</groupId>
|
||||
<artifactId>maven-resolver-connector-basic</artifactId>
|
||||
<version>${maven-resolver.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.wagon</groupId>
|
||||
<artifactId>wagon-http</artifactId>
|
||||
<version>${maven-wagon-http.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven</groupId>
|
||||
<artifactId>maven-resolver-provider</artifactId>
|
||||
<version>${maven.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven</groupId>
|
||||
<artifactId>maven-compat</artifactId>
|
||||
<version>${maven.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit-pioneer</groupId>
|
||||
<artifactId>junit-pioneer</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* @author Fabian Krüger
|
||||
*/
|
||||
public class BuildConfig {
|
||||
|
||||
private boolean skipTests = false;
|
||||
|
||||
private MemorySettings memorySettings;
|
||||
|
||||
BuildConfig(boolean skipTests, MemorySettings memorySettings) {
|
||||
this.skipTests = skipTests;
|
||||
this.memorySettings = memorySettings;
|
||||
}
|
||||
|
||||
private BuildConfig(boolean skipTests) {
|
||||
this.skipTests = skipTests;
|
||||
}
|
||||
|
||||
public static BuildConfig skipTests() {
|
||||
BuildConfig buildConfig = new BuildConfig(true);
|
||||
return buildConfig;
|
||||
}
|
||||
|
||||
public static BuildConfig defaultConfig() {
|
||||
return new BuildConfig(false);
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
boolean isSkipTests() {
|
||||
return skipTests;
|
||||
}
|
||||
|
||||
public MemorySettings getMemorySettings() {
|
||||
return memorySettings;
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
|
||||
private boolean skipTests;
|
||||
|
||||
private MemorySettings memorySettings = MemorySettings.of("31M", "256M");
|
||||
|
||||
public Builder skipTests(boolean b) {
|
||||
this.skipTests = b;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BuildConfig build() {
|
||||
return new BuildConfig(skipTests, memorySettings);
|
||||
}
|
||||
|
||||
public Builder withMemory(String min, String max) {
|
||||
this.memorySettings = MemorySettings.of(min, max);
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* @author Fabian Krüger
|
||||
*/
|
||||
public class DebugConfig {
|
||||
|
||||
private int port = 5005;
|
||||
|
||||
private boolean suspend = true;
|
||||
|
||||
private boolean isDebugEnabled = true;
|
||||
|
||||
public static DebugConfig from(int port, boolean suspend) {
|
||||
return new DebugConfig(port, suspend, true);
|
||||
}
|
||||
|
||||
public static DebugConfig fromDefault() {
|
||||
return new DebugConfig(5005, false, true);
|
||||
}
|
||||
|
||||
public static DebugConfig disabled() {
|
||||
return new DebugConfig(5005, false, false);
|
||||
}
|
||||
|
||||
private DebugConfig(int port, boolean suspend, boolean isDebugEnabled) {
|
||||
this.port = port;
|
||||
this.suspend = suspend;
|
||||
this.isDebugEnabled = isDebugEnabled;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public char isSuspend() {
|
||||
return suspend ? 'y' : 'n';
|
||||
}
|
||||
|
||||
public boolean isDebugEnabled() {
|
||||
return isDebugEnabled;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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 org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* @author Fabian Krüger
|
||||
*/
|
||||
public class MavenInvocationRequestFactory {
|
||||
|
||||
@NotNull
|
||||
public InvocationRequest createMavenInvocationRequest(Path baseDir, DebugConfig debugConfig,
|
||||
BuildConfig buildConfig, List<String> givenGoals, Consumer<String> lineConsumer) {
|
||||
List<String> goals = new ArrayList<>(givenGoals);
|
||||
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");
|
||||
}
|
||||
|
||||
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();
|
||||
if (buildConfig.getMemorySettings() != null) {
|
||||
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()));
|
||||
}
|
||||
request.setMavenOpts(mavenOpts.toString());
|
||||
return request;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,379 @@
|
||||
/*
|
||||
* 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<String> recipeNames) {
|
||||
MavenInvokerRewriteRecipeLauncherBuilder builders = new MavenInvokerRewriteRecipeLauncherBuilder();
|
||||
return builders.applyRecipes(recipeNames);
|
||||
}
|
||||
|
||||
private InvocationResult invokeRewritePlugin(Invoker invoker, Path baseDir, List<String> recipeNames,
|
||||
List<String> dependencies, DebugConfig debugConfig, BuildConfig buildConfig, Consumer<String> 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<String> recipeNames, List<String> dependencies,
|
||||
DebugConfig debugConfig, BuildConfig buildConfig, Consumer<String> 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<String> lineConsumer, String openRewriteCommand) {
|
||||
List<String> 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<String> lineConsumer, List<String> providedGoals) {
|
||||
// List<String> 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<String> recipeNames, List<String> 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<String> recipeNames);
|
||||
|
||||
}
|
||||
|
||||
public interface OnDirBuilder {
|
||||
|
||||
OptionalBuilder onDir(Path baseDir);
|
||||
|
||||
}
|
||||
|
||||
public interface OptionalBuilder {
|
||||
|
||||
OptionalBuilder withDebugConfig(DebugConfig debugConfig);
|
||||
|
||||
OptionalBuilder withDependencies(String... dependencyGavs);
|
||||
|
||||
OptionalBuilder withDependencies(List<String> dependencyGavs);
|
||||
|
||||
OptionalBuilder withBuildConfig(BuildConfig buildConfig);
|
||||
|
||||
OptionalBuilder withOutputListener(Consumer<String> 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<String> recipes = new ArrayList<>();
|
||||
|
||||
private List<String> dependencies = new ArrayList<>();
|
||||
|
||||
private BuildConfig buildConfig = BuildConfig.defaultConfig();
|
||||
|
||||
private DebugConfig debugConfig = DebugConfig.disabled();
|
||||
|
||||
private Consumer<String> 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<String> 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<String> 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 <a href="https://cyclonedx.org/">CycloneDx</a>
|
||||
*/
|
||||
@Override
|
||||
public InvocationResult cyclonedx() {
|
||||
return executeRewriteGoal(invoker, baseDir, recipes, dependencies, debugConfig, buildConfig, outputListener,
|
||||
RewritePluginGoals.CYCLONEDX);
|
||||
}
|
||||
|
||||
private InvocationResult executeRewriteGoal(Invoker invoker, Path baseDir, List<String> recipeNames,
|
||||
List<String> dependencies, DebugConfig debugConfig, BuildConfig buildConfig,
|
||||
Consumer<String> 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<String> 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<String> 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.*;
|
||||
|
||||
/**
|
||||
* @author Fabian Krüger
|
||||
*/
|
||||
public class MavenInvoker {
|
||||
|
||||
private Invoker invoker = new DefaultInvoker();
|
||||
|
||||
public InvocationResult invoke(InvocationRequest request) {
|
||||
try {
|
||||
return invoker.execute(request);
|
||||
}
|
||||
catch (MavenInvocationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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.maven;
|
||||
|
||||
/**
|
||||
* @author Fabian Krüger
|
||||
*/
|
||||
public class MemorySettings {
|
||||
|
||||
private final String min;
|
||||
|
||||
private final String max;
|
||||
|
||||
public MemorySettings(String min, String max) {
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
public static MemorySettings of(String min, String max) {
|
||||
return new MemorySettings(min, max);
|
||||
}
|
||||
|
||||
public String getMin() {
|
||||
return min;
|
||||
}
|
||||
|
||||
public String getMax() {
|
||||
return max;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* @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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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.InvocationResult;
|
||||
import org.apache.maven.shared.utils.cli.CommandLineException;
|
||||
|
||||
public class DummyInvocationResult implements InvocationResult {
|
||||
|
||||
@Override
|
||||
public CommandLineException getExecutionException() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getExitCode() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* 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.InvocationRequest;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Fabian Krüger
|
||||
*/
|
||||
public class MavenInvocationRequestFactoryTest {
|
||||
|
||||
@Test
|
||||
@DisplayName("build standard request")
|
||||
void buildStandardRequest() {
|
||||
MavenInvocationRequestFactory sut = new MavenInvocationRequestFactory();
|
||||
List<String> goals = List.of("clean", "package", "--fail-at-end");
|
||||
Consumer<String> lineConsumer = s -> {
|
||||
};
|
||||
Path baseDir = Path.of("./testcode/does-not-exist");
|
||||
|
||||
InvocationRequest request = sut.createMavenInvocationRequest(baseDir, DebugConfig.disabled(),
|
||||
BuildConfig.defaultConfig(), goals, lineConsumer);
|
||||
|
||||
assertThat(request.getGoals()).isEqualTo(goals);
|
||||
assertThat(request.getBaseDirectory()).isEqualTo(baseDir.toFile());
|
||||
assertThat(request.getMavenOpts()).isBlank();
|
||||
assertThat(request.getOutputHandler(null)).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("build debug request")
|
||||
void buildDebugRequest() {
|
||||
MavenInvocationRequestFactory sut = new MavenInvocationRequestFactory();
|
||||
List<String> goals = List.of("clean", "package", "--fail-at-end");
|
||||
Consumer<String> lineConsumer = s -> {
|
||||
};
|
||||
Path baseDir = Path.of("./testcode/does-not-exist");
|
||||
|
||||
InvocationRequest request = sut.createMavenInvocationRequest(baseDir, DebugConfig.from(1234, true),
|
||||
BuildConfig.defaultConfig(), goals, lineConsumer);
|
||||
|
||||
assertThat(request.getMavenOpts())
|
||||
.isEqualTo(" -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=1234 ");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("throws exception on empty baseDir")
|
||||
void errorListener() {
|
||||
MavenInvocationRequestFactory sut = new MavenInvocationRequestFactory();
|
||||
List<String> lines = new ArrayList<>();
|
||||
Path baseDir = Path.of("./testcode/does-not-exist").toAbsolutePath().normalize();
|
||||
@NotNull
|
||||
InvocationRequest result = sut.createMavenInvocationRequest(baseDir, DebugConfig.disabled(),
|
||||
BuildConfig.defaultConfig(), List.of("clean"), lines::add);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("build declared memory request and skip tests")
|
||||
void buildDeclaredMemoryRequestAndSkipTests() {
|
||||
|
||||
MavenInvocationRequestFactory sut = new MavenInvocationRequestFactory();
|
||||
List<String> goals = List.of("clean", "package", "--fail-at-end");
|
||||
Consumer<String> lineConsumer = s -> {
|
||||
};
|
||||
Path baseDir = Path.of("./testcode/does-not-exist");
|
||||
|
||||
InvocationRequest request = sut.createMavenInvocationRequest(baseDir, DebugConfig.disabled(),
|
||||
BuildConfig.builder().withMemory("12M", "2G").skipTests(true).build(), goals, lineConsumer);
|
||||
|
||||
assertThat(request.getMavenOpts()).isEqualTo("-Xms12M -Xmx2G ");
|
||||
assertThat(request.getGoals()).contains("-DskipTests");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
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<String> 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<String> 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<String> 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<String> 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<String> 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<String> 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<String> 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<String> 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<String> 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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
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<String> capturedLines = new ArrayList<>();
|
||||
|
||||
private Consumer<String> 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<String> 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<String> lineConsumer, List<String> givenGoals) throws MavenInvocationException {
|
||||
InvocationRequest mavenInvocationRequest = new MavenInvocationRequestFactory()
|
||||
.createMavenInvocationRequest(baseDir, debugConfig, buildConfig, givenGoals, lineConsumer);
|
||||
ArgumentCaptor<InvocationRequest> captor = ArgumentCaptor.forClass(InvocationRequest.class);
|
||||
verify(mavenInvoker).execute(captor.capture());
|
||||
InvocationRequest request = captor.getValue();
|
||||
assertThat(request).usingRecursiveComparison().isEqualTo(mavenInvocationRequest);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.acme</groupId>
|
||||
<artifactId>parent</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../</relativePath>
|
||||
</parent>
|
||||
<artifactId>application</artifactId>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.acme</groupId>
|
||||
<artifactId>component</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.validation</groupId>
|
||||
<artifactId>validation-api</artifactId>
|
||||
<version>2.0.1.Final</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1 @@
|
||||
the content
|
||||
@@ -0,0 +1 @@
|
||||
the test content
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.acme</groupId>
|
||||
<artifactId>parent</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../</relativePath>
|
||||
</parent>
|
||||
<artifactId>component</artifactId>
|
||||
</project>
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.acme</groupId>
|
||||
<artifactId>parent</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
<modules>
|
||||
<module>application</module>
|
||||
<module>component</module>
|
||||
</modules>
|
||||
</project>
|
||||
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.example.maven</groupId>
|
||||
<artifactId>simple</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
Reference in New Issue
Block a user