package org.jfrog.bamboo.task;
import com.atlassian.bamboo.build.logger.BuildLogger;
import com.atlassian.bamboo.build.test.TestCollationService;
import com.atlassian.bamboo.process.EnvironmentVariableAccessor;
import com.atlassian.bamboo.task.TaskContext;
import com.atlassian.bamboo.task.TaskResult;
import com.atlassian.bamboo.task.TaskResultBuilder;
import com.atlassian.bamboo.task.TaskType;
import com.atlassian.bamboo.v2.build.agent.capability.Capability;
import com.atlassian.bamboo.v2.build.agent.capability.CapabilityContext;
import com.atlassian.bamboo.v2.build.agent.capability.ReadOnlyCapabilitySet;
import com.atlassian.bamboo.variable.CustomVariableContext;
import com.atlassian.plugin.Plugin;
import com.atlassian.plugin.PluginAccessor;
import com.atlassian.spring.container.ContainerManager;
import com.atlassian.utils.process.*;
import com.google.common.collect.Maps;
import org.apache.commons.lang.StringUtils;
import org.jfrog.bamboo.configuration.BuildParamsOverrideManager;
import org.jfrog.bamboo.context.AbstractBuildContext;
import org.jfrog.bamboo.util.ConstantValues;
import java.io.File;
import java.io.IOException;
import java.util.Map;
import static org.jfrog.bamboo.configuration.BuildParamsOverrideManager.SHOULD_OVERRIDE_JDK_KEY;
import static org.jfrog.bamboo.configuration.BuildParamsOverrideManager.OVERRIDE_JDK_ENV_VAR_KEY;
/**
* Common super type for all tasks
*
* @author Tomer Cohen
*/
public abstract class ArtifactoryTaskType implements TaskType {
protected static final String JDK_LABEL_KEY = "system.jdk.";
public static final String JAVA_HOME = "JAVA_HOME";
protected Map<String, String> environmentVariables;
protected PluginAccessor pluginAccessor;
protected final EnvironmentVariableAccessor environmentVariableAccessor;
private final TestCollationService testCollationService;
protected BuildParamsOverrideManager buildParamsOverrideManager;
protected CustomVariableContext customVariableContext;
protected ArtifactoryTaskType(TestCollationService testCollationService,
EnvironmentVariableAccessor environmentVariableAccessor) {
ContainerManager.autowireComponent(this);
this.testCollationService = testCollationService;
this.environmentVariableAccessor = environmentVariableAccessor;
this.buildParamsOverrideManager = new BuildParamsOverrideManager(customVariableContext);
}
public void setCustomVariableContext(CustomVariableContext customVariableContext) {
this.customVariableContext = customVariableContext;
}
@SuppressWarnings("unused")
public void setPluginAccessor(PluginAccessor pluginAccessor){
this.pluginAccessor = pluginAccessor;
}
protected void initEnvironmentVariables(AbstractBuildContext buildContext) {
Map<String, String> env = Maps.newHashMap();
env.putAll(environmentVariableAccessor.getEnvironment());
if (StringUtils.isNotBlank(buildContext.getEnvironmentVariables())) {
env.putAll(environmentVariableAccessor
.splitEnvironmentAssignments(buildContext.getEnvironmentVariables(), false));
}
environmentVariables = env;
}
/**
* Get the build logger that will print messages to Bamboo's log from the context.
*
* @param taskContext The task context.
* @return The build logger.
*/
public BuildLogger getBuildLogger(TaskContext taskContext) {
return taskContext.getBuildLogger();
}
public TaskResult collectTestResults(AbstractBuildContext buildContext, TaskContext taskContext,
ExternalProcess process) {
TaskResultBuilder builder = TaskResultBuilder.newBuilder(taskContext).checkReturnCode(process);
if (buildContext.isTestChecked() && buildContext.getTestDirectory() != null) {
testCollationService.collateTestResults(taskContext, buildContext.getTestDirectory());
builder.checkTestFailures();
}
return builder.build();
}
/**
* Get the path to the JDK according to the build configuration.
*
* @param context The build context which is defined for the current build environment.
* @param capabilityContext The capability context of the build.
* @return The path to the Java home.
*/
protected String getConfiguredJdkPath(BuildParamsOverrideManager buildParamsOverrideManager, AbstractBuildContext context,
CapabilityContext capabilityContext) {
// If the relevant Bamboo variables have been configured, read the build JDK from the configured
if (shouldOverrideJdk()) {
String jdkEnvVarName = buildParamsOverrideManager.getOverrideValue(OVERRIDE_JDK_ENV_VAR_KEY);
if (StringUtils.isEmpty(jdkEnvVarName)) {
jdkEnvVarName = JAVA_HOME;
}
String envVarValue = environmentVariables.get(jdkEnvVarName);
if (envVarValue == null) {
throw new RuntimeException("The task is configured to use the '" + jdkEnvVarName + "' environment variable for the build JDK, but this environment variable is not defined.");
}
return getPathBuilder(envVarValue).toString();
}
String jdkCapabilityKey = JDK_LABEL_KEY + context.getJdkLabel();
ReadOnlyCapabilitySet capabilitySet = capabilityContext.getCapabilitySet();
if (capabilitySet == null) {
return null;
}
Capability capability = capabilitySet.getCapability(jdkCapabilityKey);
String jdkHome;
if (capability != null) {
jdkHome = capability.getValue();
} else {
return null;
}
if (StringUtils.isBlank(jdkHome)) {
return null;
}
StringBuilder binPathBuilder = getPathBuilder(jdkHome);
return binPathBuilder.toString();
}
/**
* Returns a {@link StringBuilder} starting with a given base path and ending with a file-system separator
*
* @param basePath Base path
* @return String builder
*/
public StringBuilder getPathBuilder(String basePath) {
StringBuilder confPathBuilder = new StringBuilder(basePath);
if (!basePath.endsWith(File.separator)) {
confPathBuilder.append(File.separator);
}
return confPathBuilder;
}
/**
* @return The canonical path for a path.
*/
public String getCanonicalPath(String path) {
if (StringUtils.contains(path, " ")) {
try {
File f = new File(path);
path = f.getCanonicalPath();
} catch (IOException e) {
throw new RuntimeException("IO Exception trying to get canonical path of item: " + path, e);
}
}
return path;
}
/**
* Check if the external process got exception or some errors
*
* @param process - Bamboo external process
* @return full message of errors, if exists
*/
public String getErrorMessage(ExternalProcess process) {
ProcessHandler handler = process.getHandler();
String commandLine = process.getCommandLine();
StringBuilder message = new StringBuilder();
if (handler.getException() != null) {
message.append("Exception executing command \"")
.append(commandLine).append(" \n")
.append(handler.getException().getMessage()).append("\n")
.append(handler.getException()).append("\n");
}
String reason = null;
if (handler instanceof PluggableProcessHandler) {
OutputHandler errorHandler = ((PluggableProcessHandler) handler).getErrorHandler();
if (errorHandler instanceof StringOutputHandler) {
StringOutputHandler errorStringHandler = (StringOutputHandler) errorHandler;
if (errorStringHandler.getOutput() != null) {
reason = errorStringHandler.getOutput();
}
}
}
if (reason != null && reason.trim().length() > 0) {
message.append("Error executing command \"").append(commandLine).append("\": ").append(reason);
}
return message.toString();
}
public String getArtifactoryVersion(){
Plugin plugin = pluginAccessor.getPlugin(ConstantValues.ARTIFACTORY_PLUGIN_KEY);
if (plugin != null) {
return plugin.getPluginInformation().getVersion();
}
return StringUtils.EMPTY;
}
private boolean shouldOverrideJdk() {
return Boolean.valueOf(buildParamsOverrideManager.getOverrideValue(SHOULD_OVERRIDE_JDK_KEY));
}
}