@@ -0,0 +1,2464 @@
+package nu.studer.teamcity.buildscan.agent;%0A%0Aimport jetbrains.buildServer.agent.BuildRunnerContext;%0Aimport org.jetbrains.annotations.NotNull;%0A%0Aimport java.io.BufferedReader;%0Aimport java.io.File;%0Aimport java.io.IOException;%0Aimport java.io.InputStreamReader;%0Aimport java.util.regex.Matcher;%0Aimport java.util.regex.Pattern;%0A%0A/**%0A * This class executes Maven commands and returns their output, both standard output and standard error, when given a%0A * %7B@link BuildRunnerContext%7D.%0A */%0Afinal class MavenCommandExecutor %7B%0A%0A    private final BuildRunnerContext runnerContext;%0A%0A    public MavenCommandExecutor(BuildRunnerContext context) %7B%0A        this.runnerContext = context;%0A    %7D%0A%0A    @NotNull%0A    public Result execute(String args) throws IOException %7B%0A        String command = getMavenExe().getAbsolutePath() + %22 %22 + args;%0A        ProcessBuilder processBuilder = new ProcessBuilder(command.split(%22 %22))%0A            .redirectErrorStream(true);%0A        return new Result(processBuilder.start());%0A    %7D%0A%0A    private File getMavenExe() %7B%0A        String mavenPath = runnerContext.getToolPath(%22maven%22);%0A        String mvnExe = System.getProperty(%22os.name%22).toLowerCase().contains(%22win%22) ? %22mvn.cmd%22 : %22mvn%22;%0A        return new File(mavenPath, %22bin/%22 + mvnExe);%0A    %7D%0A%0A    public static class Result %7B%0A%0A        public final Process process;%0A        private String output;%0A%0A        public Result(Process process) %7B%0A            this.process = process;%0A        %7D%0A%0A        @NotNull%0A        public String getOutput() throws InterruptedException, IOException %7B%0A            if (output == null) %7B%0A                process.waitFor();%0A%0A                // this logic eagerly consumes the entire output into memory, which should not be an issue when only%0A                // used for %60mvn --version%60, which generates ~5 lines of output%0A                // this may should be revisited if other commands are executed here%0A                StringBuilder sb = new StringBuilder();%0A                BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));%0A%0A                int ch;%0A                while ((ch = reader.read()) != -1) %7B%0A                    sb.append((char) ch);%0A                %7D%0A%0A                output = sb.toString();%0A            %7D%0A%0A            return output;%0A        %7D%0A%0A        @NotNull%0A        public Matcher match(Pattern pattern) throws InterruptedException, IOException %7B%0A            return pattern.matcher(getOutput());%0A        %7D%0A    %7D%0A%7D%0A

Add `MavenCommandExecutor` to execute Maven commands from a `BuildRunnerContext`