* BAEL-7201: Maven compilation example

* BAEL-7201: Disable the tests

* BAEL-7201: Created MavenAdapter and moved repeated code

* BAEL-7201: Project creation and tests

* BAEL-7201: A couple of renames and refactors

* BAEL-7201: Extract constants

* BAEL-7201: Cleaned the POM

* BAEL-7201: Remove unnecessary access modifiers
This commit is contained in:
Eugene Kovko 2024-02-02 20:26:16 +01:00 committed by GitHub
parent 772649421b
commit 9d23ecb95b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 359 additions and 0 deletions

View File

@ -8,6 +8,36 @@
<version>0.0.1-SNAPSHOT</version>
<name>maven-exec-plugin</name>
<dependencies>
<dependency>
<groupId>org.apache.maven.shared</groupId>
<artifactId>maven-invoker</artifactId>
<version>${apache.maven.invoker.version}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-embedder</artifactId>
<version>${apache.maven.version}</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
@ -38,6 +68,9 @@
<properties>
<maven-compiler-plugin.version>3.12.1</maven-compiler-plugin.version>
<exec-maven-plugin.version>3.1.0</exec-maven-plugin.version>
<junit.jupiter.version>5.10.0</junit.jupiter.version>
<apache.maven.version>3.9.6</apache.maven.version>
<apache.maven.invoker.version>3.2.0</apache.maven.invoker.version>
</properties>
</project>

View File

@ -0,0 +1,17 @@
package com.baeldung.learningplatform;
public enum JavaVersion {
JAVA_8("1.8"), JAVA_9("9"), JAVA_17("17");
private final String version;
JavaVersion(String version) {
this.version = version;
}
public String getVersion() {
return this.version;
}
}

View File

@ -0,0 +1,13 @@
package com.baeldung.learningplatform;
import java.nio.file.Path;
public interface Maven {
String POM_XML = "pom.xml";
String COMPILE_GOAL = "compile";
String USE_CUSTOM_POM = "-f";
int OK = 0;
String MVN = "mvn";
void compile(Path projectFolder);
}

View File

@ -0,0 +1,12 @@
package com.baeldung.learningplatform;
public class MavenCompilationException extends RuntimeException {
public MavenCompilationException(String message, Throwable cause) {
super(message, cause);
}
public MavenCompilationException(String message) {
super(message);
}
}

View File

@ -0,0 +1,16 @@
package com.baeldung.learningplatform;
import java.nio.file.Path;
import org.apache.maven.cli.MavenCli;
public class MavenEmbedder implements Maven {
public static final String MVN_HOME = "maven.multiModuleProjectDirectory";
@Override
public void compile(Path projectFolder) {
MavenCli cli = new MavenCli();
System.setProperty(MVN_HOME, projectFolder.toString());
cli.doMain(new String[]{COMPILE_GOAL}, projectFolder.toString(), null, null);
}
}

View File

@ -0,0 +1,26 @@
package com.baeldung.learningplatform;
import java.io.IOException;
import java.nio.file.Path;
public abstract class MavenExecutorAdapter implements Maven {
@Override
public void compile(Path projectFolder) {
int exitCode;
try {
exitCode = execute(projectFolder, COMPILE_GOAL);
} catch (InterruptedException e) {
throw new MavenCompilationException("Interrupted during compilation", e);
} catch (IOException e) {
throw new MavenCompilationException("Incorrect execution", e);
}
if (exitCode != OK) {
throw new MavenCompilationException("Failure during compilation: " + exitCode);
}
}
protected abstract int execute(Path projectFolder, String compileGoal)
throws InterruptedException, IOException;
}

View File

@ -0,0 +1,30 @@
package com.baeldung.learningplatform;
import java.nio.file.Path;
import java.util.Collections;
import org.apache.maven.shared.invoker.DefaultInvocationRequest;
import org.apache.maven.shared.invoker.DefaultInvoker;
import org.apache.maven.shared.invoker.InvocationRequest;
import org.apache.maven.shared.invoker.InvocationResult;
import org.apache.maven.shared.invoker.Invoker;
import org.apache.maven.shared.invoker.MavenInvocationException;
public class MavenInvoker implements Maven {
@Override
public void compile(Path projectFolder) {
InvocationRequest request = new DefaultInvocationRequest();
request.setPomFile(projectFolder.resolve(POM_XML).toFile());
request.setGoals(Collections.singletonList(Maven.COMPILE_GOAL));
Invoker invoker = new DefaultInvoker();
try {
InvocationResult result = invoker.execute(request);
if (result.getExitCode() != 0) {
throw new MavenCompilationException("Build failed", result.getExecutionException());
}
} catch (MavenInvocationException e) {
throw new MavenCompilationException("Exception during Maven invocation", e);
}
}
}

View File

@ -0,0 +1,15 @@
package com.baeldung.learningplatform;
import java.io.IOException;
import java.nio.file.Path;
public class MavenProcessBuilder extends MavenExecutorAdapter {
private static final ProcessBuilder PROCESS_BUILDER = new ProcessBuilder();
protected int execute(Path projectFolder, String compileGoal) throws IOException, InterruptedException {
Process process = PROCESS_BUILDER
.command(MVN, USE_CUSTOM_POM, projectFolder.resolve(POM_XML).toString(), compileGoal)
.start();
return process.waitFor();
}
}

View File

@ -0,0 +1,13 @@
package com.baeldung.learningplatform;
import java.io.IOException;
import java.nio.file.Path;
public class MavenRuntimeExec extends MavenExecutorAdapter {
@Override
protected int execute(Path projectFolder, String compileGoal) throws InterruptedException, IOException {
String[] arguments = {MVN, USE_CUSTOM_POM, projectFolder.resolve(POM_XML).toString(), COMPILE_GOAL};
Process process = Runtime.getRuntime().exec(arguments);
return process.waitFor();
}
}

View File

@ -0,0 +1,100 @@
package com.baeldung.learningplatform;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import org.apache.maven.model.Build;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.Model;
import org.apache.maven.model.Plugin;
import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
import org.codehaus.plexus.util.xml.Xpp3Dom;
public class ProjectBuilder {
private static final String PACKAGE = "package ";
private static final String POM_XML = "pom.xml";
private static final String SRC_TEST = "src/test/";
private static final String SRC_MAIN_JAVA = "src/main/java/";
private static final String PACKAGE_DELIMITER = ".";
private static final String MAIN_JAVA = "Main.java";
private final List<Dependency> dependencies = new ArrayList<>();
private JavaVersion javaVersion = JavaVersion.JAVA_8;
public ProjectBuilder addDependency(String groupId, String artifactId, String version) {
Dependency dependency = new Dependency();
dependency.setGroupId(groupId);
dependency.setArtifactId(artifactId);
dependency.setVersion(version);
dependencies.add(dependency);
return this;
}
public ProjectBuilder setJavaVersion(JavaVersion version) {
this.javaVersion = version;
return this;
}
public void build(String userName, Path projectPath, String packageName) throws IOException {
Model model = new Model();
configureModel(userName, model);
dependencies.forEach(model::addDependency);
Build build = configureJavaVersion();
model.setBuild(build);
MavenXpp3Writer writer = new MavenXpp3Writer();
writer.write(new FileWriter(projectPath.resolve(POM_XML).toFile()), model);
generateFolders(projectPath, SRC_TEST);
Path generatedPackage = generateFolders(projectPath,
SRC_MAIN_JAVA +
packageName.replace(PACKAGE_DELIMITER, FileSystems.getDefault().getSeparator()));
String generatedClass = generateMainClass(PACKAGE + packageName);
Files.writeString(generatedPackage.resolve(MAIN_JAVA), generatedClass);
}
private static void configureModel(String userName, Model model) {
model.setModelVersion("4.0.0");
model.setArtifactId("com." + userName.toLowerCase());
model.setGroupId("learning-project");
model.setVersion("0.0.1-SNAPSHOT");
}
private static String generateMainClass(String packageName) {
return packageName + ";\n" +
"\n" +
"public class Main {\n" +
" public static void main(String[] args){\n" +
" System.out.println(\"Hello World!\");\n" +
" }\n" +
"}\n";
}
private static Path generateFolders(Path sourceFolder, String packageName) throws IOException {
return Files.createDirectories(sourceFolder.resolve(packageName));
}
private Build configureJavaVersion() {
Plugin plugin = new Plugin();
plugin.setGroupId("org.apache.maven.plugins");
plugin.setArtifactId("maven-compiler-plugin");
plugin.setVersion("3.8.1");
Xpp3Dom configuration = new Xpp3Dom("configuration");
Xpp3Dom source = new Xpp3Dom("source");
source.setValue(javaVersion.getVersion());
Xpp3Dom target = new Xpp3Dom("target");
target.setValue(javaVersion.getVersion());
configuration.addChild(source);
configuration.addChild(target);
plugin.setConfiguration(configuration);
Build build = new Build();
build.addPlugin(plugin);
return build;
}
}

View File

@ -0,0 +1,32 @@
package com.baeldung.learningplatform;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
public class FileUtil {
private FileUtil() {
}
public static void removeDirectoryRecursively(Path folder) throws IOException {
if (Files.exists(folder)) {
Files.walkFileTree(folder, new SimpleFileVisitor<>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Files.delete(file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
Files.delete(dir);
return FileVisitResult.CONTINUE;
}
});
}
}
}

View File

@ -0,0 +1,41 @@
package com.baeldung.learningplatform;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.stream.Stream;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.io.TempDir;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
class MavenRuntimeExecUnitTest {
private static final String PACKAGE_NAME = "com.baeldung.generatedcode";
private static final String USER_NAME = "john_doe";
@TempDir
private Path tempDir;
@BeforeEach
public void setUp() throws IOException {
ProjectBuilder projectBuilder = new ProjectBuilder();
projectBuilder.build(USER_NAME, tempDir, PACKAGE_NAME);
}
@ParameterizedTest
@MethodSource
void givenMavenInterface_whenCompileMavenProject_thenCreateTargetDirectory(Maven maven) {
maven.compile(tempDir);
assertTrue(Files.exists(tempDir));
}
static Stream<Maven> givenMavenInterface_whenCompileMavenProject_thenCreateTargetDirectory() {
return Stream.of(
new MavenRuntimeExec(),
new MavenProcessBuilder(),
new MavenEmbedder(),
new MavenInvoker());
}
}

View File

@ -0,0 +1,11 @@
package com.baeldung.learningplatform;
import java.nio.file.Path;
import java.nio.file.Paths;
public interface ProjectsPaths {
public static final Path PROJECT_DIR = Paths.get("src/test/resources/learning-project/");
public static final Path PROJECT_POM_XML = PROJECT_DIR.resolve("pom.xml");
public static final Path PROJECT_TARGET = PROJECT_DIR.resolve("target");
}