Skip to content

Commit

Permalink
Refactor project crawler runner
Browse files Browse the repository at this point in the history
  • Loading branch information
kaklakariada committed Jan 31, 2024
1 parent 678ab31 commit e144e11
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 68 deletions.
2 changes: 1 addition & 1 deletion maven-project-crawler/error_code_config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ error-tags:
PK-MPC:
packages:
- com.exasol.projectkeeper
highest-index: 63
highest-index: 64
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ public class MavenProjectCrawlerMojo extends AbstractMojo {
// [impl -> dsn~eclipse-prefs-java-version~1]
@Override
public void execute() {
if (projectsToCrawl == null || projectsToCrawl.isBlank()) {
throw new IllegalArgumentException(ExaError.messageBuilder("E-PK-MPC-64")
.message("Property {{property name}} is not defined or empty.", PROPERTY_PROJECTS_TO_CRAWL)
.mitigation("Specify property with least one pom file.").toString());
}
final MavenProjectFromFileReader mavenProjectReader = new DefaultMavenProjectFromFileReader(
this.mavenProjectBuilder, this.session);
final MavenModelFromRepositoryReader modelFromRepositoryReader = new MavenModelFromRepositoryReader(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,37 +1,28 @@
package com.exasol.projectkeeper;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.time.Duration;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;

import com.exasol.errorreporting.ExaError;
import com.exasol.projectkeeper.shared.mavenprojectcrawler.MavenProjectCrawlResult;
import com.exasol.projectkeeper.shared.mavenprojectcrawler.ResponseCoder;
import com.exasol.projectkeeper.sources.analyze.generic.MavenProcessBuilder;
import com.exasol.projectkeeper.stream.AsyncStreamReader;
import com.exasol.projectkeeper.stream.CollectingConsumer;
import com.exasol.projectkeeper.sources.analyze.generic.SimpleProcess;

/**
* Runs the maven plugin goal on the current repository and returns the parsed result.
*/
public class JavaProjectCrawlerRunner {
private static final Logger LOGGER = Logger.getLogger(JavaProjectCrawlerRunner.class.getName());
private static final Duration STREAM_READING_TIMEOUT = Duration.ofSeconds(1);
private final Path mvnRepositoryOverride;
private final String ownVersion;

/**
* Create a new instance of {@link JavaProjectCrawlerRunner}.
*
* @param mvnRepositoryOverride maven repository override. Use {@code null} for default
* @param mvnRepositoryOverride Maven repository override. This is useful for running integration tests. Use
* {@code null} for default.
* @param ownVersion project-keeper version
*/
public JavaProjectCrawlerRunner(final Path mvnRepositoryOverride, final String ownVersion) {
Expand All @@ -51,63 +42,39 @@ public MavenProjectCrawlResult crawlProject(final Path... pomFiles) {
}

private String runCrawlerPlugin(final Path... pomFiles) {
final String projectList = Arrays.stream(pomFiles).map(pomFile -> pomFile.toAbsolutePath().toString()
// we use / instead of \ here as a fix for https://github.com/eclipse-ee4j/yasson/issues/540
.replace(FileSystems.getDefault().getSeparator(), "/")).collect(Collectors.joining(";"));
final List<String> commandParts = buildMavenCommand(projectList);
LOGGER.fine(() -> "Executing command " + commandParts);
try {
final Process proc = new ProcessBuilder(commandParts).redirectErrorStream(true).start();

final CollectingConsumer outputStreamConsumer = new AsyncStreamReader()
.startCollectingConsumer(proc.getInputStream());
final CollectingConsumer errorStreamConsumer = new AsyncStreamReader()
.startCollectingConsumer(proc.getErrorStream());

if (!proc.waitFor(90, TimeUnit.SECONDS)) {
final String stdOutput = outputStreamConsumer.getCurrentContent();
final String stdError = errorStreamConsumer.getCurrentContent();
throw new IllegalStateException(ExaError.messageBuilder("E-PK-CORE-81").message(
"Timeout while executing command {{executed command|u}}. Output: {{std output}}, error: {{std error}}",
commandParts, stdOutput, stdError).toString());
}
final int exitCode = proc.exitValue();
final String output = outputStreamConsumer.getContent(STREAM_READING_TIMEOUT);
if (exitCode != 0) {
LOGGER.log(Level.SEVERE, output);
throw new IllegalStateException(ExaError.messageBuilder("E-PK-CORE-78").message(
"Failed to run command {{executed command|u}}, exit code was {{exit code}}. Output:\n{{output}}",
commandParts, exitCode, output).toString());
}
return new ResponseCoder().decodeResponse(output);
} catch (final IOException exception) {
throw new UncheckedIOException(getRunFailedMessage(), exception);
} catch (final InterruptedException exception) {
Thread.currentThread().interrupt();
throw new IllegalStateException(getRunFailedMessage(), exception);
}
final MavenProcessBuilder builder = buildMavenCommand(pomFiles);
final SimpleProcess process = builder.startSimpleProcess();
process.waitUntilFinished(Duration.ofSeconds(90));
return new ResponseCoder().decodeResponse(process.getOutputStreamContent());
}

private List<String> buildMavenCommand(final String projectList) {
final MavenProcessBuilder command = MavenProcessBuilder.create().addArguments("--batch-mode",
"-Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn",
"com.exasol:project-keeper-java-project-crawler:" + this.ownVersion + ":" + "crawl",
"-DprojectsToCrawl=" + projectList,
/*
* We need to disable the model cache here since it caches the parent poms with {revision} as version
* and then runs into trouble since the cache is different when reading the old pom (for comparing
* dependencies).
*/
"-Dmaven.defaultProjectBuilder.disableGlobalModelCache=true");
private MavenProcessBuilder buildMavenCommand(final Path... pomFiles) {
final MavenProcessBuilder builder = MavenProcessBuilder.create()
.addArguments(
"-Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn",
"com.exasol:project-keeper-java-project-crawler:" + this.ownVersion + ":" + "crawl",
"-DprojectsToCrawl=" + getProjectList(pomFiles),
/*
* We need to disable the model cache here since it caches the parent poms with {revision} as
* version and then runs into trouble since the cache is different when reading the old pom (for
* comparing dependencies).
*/
"-Dmaven.defaultProjectBuilder.disableGlobalModelCache=true")
.workingDir(null);

if (this.mvnRepositoryOverride != null) {
command.addArgument("-Dmaven.repo.local=" + this.mvnRepositoryOverride);
builder.addArgument("-Dmaven.repo.local=" + this.mvnRepositoryOverride);
}
return command.build();
return builder;
}

private String getRunFailedMessage() {
return ExaError.messageBuilder("E-PK-CORE-80").message("Failed to run project-keeper-java-project-crawler.")
.toString();
private String getProjectList(final Path... pomFiles) {
return Arrays.stream(pomFiles).map(this::formatPath).collect(Collectors.joining(";"));
}

private String formatPath(final Path pomFile) {
return pomFile.toAbsolutePath().toString()
// we use / instead of \ here as a fix for https://github.com/eclipse-ee4j/yasson/issues/540
.replace(FileSystems.getDefault().getSeparator(), "/");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@

import static java.util.Arrays.asList;

import java.nio.file.Path;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

import com.exasol.projectkeeper.OsCheck;
import com.exasol.projectkeeper.OsCheck.OSType;
Expand All @@ -13,7 +16,10 @@
*/
public class MavenProcessBuilder {

private static final Logger LOG = Logger.getLogger(MavenProcessBuilder.class.getName());
private static final Duration DEFAULT_TIMEOUT = Duration.ofSeconds(30);
private final List<String> command = new ArrayList<>();
private Path workingDir = null;

private MavenProcessBuilder() {
// Use create() method
Expand All @@ -27,6 +33,7 @@ private MavenProcessBuilder() {
public static MavenProcessBuilder create() {
final MavenProcessBuilder builder = new MavenProcessBuilder();
builder.addArgument(getMavenExecutable());
builder.addArgument("--batch-mode");
return builder;
}

Expand All @@ -53,12 +60,23 @@ public MavenProcessBuilder addArgument(final String argument) {
}

/**
* Build the command that can be used as argument for {@link ProcessBuilder}.
* Define the working directory where to execute the command. Default: {@code null}.
*
* @return the command
* @param workingDir working dir
* @return {@code this} for fluent programming
*/
public MavenProcessBuilder workingDir(final Path workingDir) {
this.workingDir = workingDir;
return this;
}

/**
* Build the command and run it.
*
* @return the running {@link SimpleProcess}
*/
public List<String> build() {
return List.copyOf(this.command);
public SimpleProcess startSimpleProcess() {
return SimpleProcess.start(workingDir, command);
}

private static String getMavenExecutable() {
Expand Down

0 comments on commit e144e11

Please sign in to comment.