package hudson.plugins.envfile;
import hudson.EnvVars;
import hudson.Extension;
import hudson.Launcher;
import hudson.Util;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.BuildListener;
import hudson.tasks.BuildWrapper;
import hudson.tasks.BuildWrapperDescriptor;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Map.Entry;
import java.util.logging.Logger;
import org.kohsuke.stapler.DataBoundConstructor;
/**
* BuildWrapper to set environment variables from a file.
*
* @author Anders Johansson
*
*/
public class EnvFileBuildWrapper extends BuildWrapper{
private static final Logger logger = Logger.getLogger(EnvFileBuildWrapper.class.getName());
private static final String NAME = "[envfile] ";
private String filePath;
@DataBoundConstructor
public EnvFileBuildWrapper(String filePath) {
this.filePath=Util.fixEmpty(filePath);
}
/**
* Get the path to the file containing environment variables.
*
* @return the filePath
*/
public String getFilePath()
{
return filePath;
}
/**
* Get the path to the file containing environment variables.
* @param filePath String path of the file containing environment variables
*/
public void setFilePath(String filePath)
{
this.filePath=filePath;
}
@Override
public Environment setUp(AbstractBuild build, Launcher launcher,
BuildListener listener) throws IOException, InterruptedException {
logger.fine("Reading environment variables from file. ");
return new EnvironmentImpl(listener);
}
class EnvironmentImpl extends Environment
{
private BuildListener listener;
public EnvironmentImpl(BuildListener listener) {
this.listener = listener;
}
private Properties readPropsFromFile(String path, Map<String, String> currentMap)
{
console("Reading environment variables from file.");
Properties props = new Properties();
FileInputStream fis = null;
String resolvedPath = Util.replaceMacro(path, currentMap);
console("Path to file: " + resolvedPath);
try
{
if(path != null)
{
fis = new FileInputStream(resolvedPath);
props.load(fis);
}
else
{
console("No path to environment file has been entered.");
}
}
catch (FileNotFoundException e)
{
console("Can not find environment file. Path to file=[" + resolvedPath + "]");
logger.warning("Environment file not found. Path to file=[" + resolvedPath + "]");
}
catch (IOException e)
{
console("Unable to read from environment file.");
logger.warning("Unable to read from environment file. " + e.getClass().getName());
}
finally
{
close(fis);
}
return props;
}
/**
* Helper to close environment file.
* @param fis {@link FileInputStream} for environment file.
*/
private void close(FileInputStream fis)
{
try
{
if(fis != null)
{
fis.close();
}
}
catch (Exception e)
{
console("Unable to close environment file.");
logger.warning("Unable to close environment file.");
}
}
private Map<String, String> getEnvFileMap(Map<String, String> currentMap)
{
Map<String, String> tmpFileEnvMap = new HashMap<String, String>();
Map<String, String> newFileEnvMap = new HashMap<String, String>();
tmpFileEnvMap.putAll(currentMap);
//Fetch env variables from fil as properties
Properties envProps = readPropsFromFile(filePath, currentMap);
if(envProps != null || envProps.size() < 1)
{
//Add env variables to temporary env map and file map containing new variables.
for (Entry<Object, Object> prop : envProps.entrySet())
{
String key = prop.getKey().toString();
String value = prop.getValue().toString();
newFileEnvMap.put(key, value);
tmpFileEnvMap.put(key, value);
}
// Resolve all variables against each other.
EnvVars.resolve(tmpFileEnvMap);
//Print resolved variables and copy resolved value to return map.
for(String key : newFileEnvMap.keySet())
{
newFileEnvMap.put(key, tmpFileEnvMap.get(key));
console(key + "=" + newFileEnvMap.get(key));
}
}
return newFileEnvMap;
}
private void console(String str)
{
listener.getLogger().println(NAME + str);
}
@Override
public void buildEnvVars(Map<String, String> env)
{
env.putAll(getEnvFileMap(env));
}
}
@Extension
public static final class DescriptorImpl extends BuildWrapperDescriptor
{
@Override
public String getDisplayName() {
return Messages.EnvFileBuildWrapper_DisplayName();
}
@Override
public boolean isApplicable(AbstractProject item) {
return true;
}
}
}