package org.jfrog.bamboo.capability;
import com.atlassian.bamboo.command.SimpleExecuteStreamHandler;
import com.atlassian.bamboo.utils.SystemProperty;
import com.atlassian.bamboo.v2.build.agent.capability.AbstractHomeDirectoryCapabilityDefaultsHelper;
import com.atlassian.bamboo.v2.build.agent.capability.CapabilityDefaultsHelper;
import com.atlassian.bamboo.v2.build.agent.capability.ExecutablePathUtils;
import com.google.common.base.Predicate;
import com.google.common.collect.Lists;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.SystemUtils;
import org.apache.log4j.Logger;
import org.apache.tools.ant.taskdefs.Execute;
import org.apache.tools.ant.taskdefs.ExecuteWatchdog;
import org.apache.tools.ant.types.Commandline;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Maven3CapabilityHelper extends AbstractHomeDirectoryCapabilityDefaultsHelper {
private static final Logger log = Logger.getLogger(Maven3CapabilityHelper.class);
private static final String MAVEN3_HOME_POSIX = "/usr/share/maven3/";
private static final Pattern MAVEN_VERSION_3 = Pattern.compile("3\\.\\d+\\.\\d+");
private static final String M2_EXECUTABLE_NAME = "mvn";
private static final long GET_VERSION_TIMEOUT = TimeUnit.SECONDS.toMillis(10);
private static final Pattern VERSION_PATTERN = Pattern.compile("Apache Maven (\\S+).*");
@NotNull
@Override
protected String getExecutableName() {
return ExecutablePathUtils.makeBatchIfOnWindows(M2_EXECUTABLE_NAME);
}
@Nullable
@Override
protected String getEnvHome() {
return SystemProperty.MAVEN2_HOME.getValue();
}
@NotNull
@Override
protected String getPosixHome() {
return MAVEN3_HOME_POSIX;
}
@Override
@NotNull
protected String getCapabilityKey() {
return CapabilityDefaultsHelper.CAPABILITY_BUILDER_PREFIX + ".maven.Artifactory Maven 3";
}
public static class MavenVersionMatcher implements Predicate<File> {
private final Pattern pattern;
public MavenVersionMatcher(@NotNull Pattern pattern) {
this.pattern = pattern;
}
@Override
public boolean apply(@Nullable final File input) {
if (input == null) {
return false;
}
String mavenVersion = getMavenVersion(input);
return mavenVersion != null && pattern.matcher(mavenVersion).matches();
}
/**
* Parse output of "mvn --version". This method works only with Maven 2 and Maven 3
*
* @return text representation of Maven version number or null if not possible to obtain version number
*/
@Nullable
private static String getMavenVersion(final File mavenExecutable) {
if (!mavenExecutable.isFile()) {
log.info("Failed to get Maven version, file does not exists: " + mavenExecutable);
return null;
}
Commandline commandline = new Commandline();
if (SystemUtils.IS_OS_WINDOWS) {
commandline.setExecutable("cmd.exe");
commandline.addArguments(new String[]{"/c", mavenExecutable.getPath()});
} else {
commandline.setExecutable(mavenExecutable.getPath());
}
commandline.addArguments(new String[]{"--version"});
List<String> commandStdOut = Lists.newArrayList();
List<String> commandStdErr = Lists.newArrayList();
ExecuteWatchdog watchdog = new ExecuteWatchdog(GET_VERSION_TIMEOUT);
Execute execute =
new Execute(new SimpleExecuteStreamHandler(commandStdOut, commandStdErr, "MavenVersion"), watchdog);
execute.setWorkingDirectory(SystemUtils.getJavaIoTmpDir());
execute.setEnvironment(new String[]{"M2_HOME=" + mavenExecutable.getParentFile().getParent()});
execute.setCommandline(commandline.getCommandline());
try {
int exitValue = execute.execute();
if (!Execute.isFailure(exitValue)) {
for (String line : commandStdOut) {
Matcher matcher = VERSION_PATTERN.matcher(line);
if (matcher.matches()) {
return matcher.group(1);
}
}
log.warn("Failed to get Maven version, unable to analyze output: \n" + StringUtils
.join(commandStdOut, "\n"));
} else {
if (watchdog.killedProcess()) {
log.warn("Failed to get Maven version, command timed out");
} else {
log.warn("Failed to get Maven version, command failed: \n" +
StringUtils.join(commandStdErr, "\n"));
}
}
} catch (Exception e) {
log.warn("Failed to execute command", e);
}
return null;
}
}
}