package com.cwctravel.hudson.plugins.extended_choice_parameter;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StringReader;
import java.lang.reflect.Field;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletException;
import org.acegisecurity.Authentication;
import org.acegisecurity.context.SecurityContextHolder;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.Property;
import org.codehaus.groovy.control.CompilerConfiguration;
import org.jenkinsci.plugins.scriptsecurity.scripts.ApprovalContext;
import org.jenkinsci.plugins.scriptsecurity.scripts.ClasspathEntry;
import org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval;
import org.jenkinsci.plugins.scriptsecurity.scripts.UnapprovedClasspathException;
import org.jenkinsci.plugins.scriptsecurity.scripts.UnapprovedUsageException;
import org.jenkinsci.plugins.scriptsecurity.scripts.languages.GroovyLanguage;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.Stapler;
import org.kohsuke.stapler.StaplerRequest;
import com.opencsv.CSVReader;
import groovy.lang.Binding;
import groovy.lang.GroovyCodeSource;
import groovy.lang.GroovyShell;
import hudson.EnvVars;
import hudson.Extension;
import hudson.Util;
import hudson.cli.CLICommand;
import hudson.model.AbstractProject;
import hudson.model.ParameterDefinition;
import hudson.model.ParameterValue;
import hudson.model.User;
import hudson.util.DirScanner;
import hudson.util.FileVisitor;
import hudson.util.FormValidation;
import hudson.util.LogTaskListener;
import jenkins.model.Jenkins;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
public class ExtendedChoiceParameterDefinition extends ParameterDefinition {
private static final long serialVersionUID = -2946187268529865645L;
private static final Logger LOGGER = Logger.getLogger(ExtendedChoiceParameterDefinition.class.getName());
private static final String ATTR_REQUEST_GROOVY_BINDING = "com.cwctravel.hudson.plugins.extended_choice_parameter.groovyBinding";
public static final String PARAMETER_TYPE_SINGLE_SELECT = "PT_SINGLE_SELECT";
public static final String PARAMETER_TYPE_MULTI_SELECT = "PT_MULTI_SELECT";
public static final String PARAMETER_TYPE_CHECK_BOX = "PT_CHECKBOX";
public static final String PARAMETER_TYPE_RADIO = "PT_RADIO";
public static final String PARAMETER_TYPE_TEXT_BOX = "PT_TEXTBOX";
public static final String PARAMETER_TYPE_HIDDEN = "PT_HIDDEN";
public static final String PARAMETER_TYPE_MULTI_LEVEL_SINGLE_SELECT = "PT_MULTI_LEVEL_SINGLE_SELECT";
public static final String PARAMETER_TYPE_MULTI_LEVEL_MULTI_SELECT = "PT_MULTI_LEVEL_MULTI_SELECT";
public static final String PARAMETER_TYPE_JSON = "PT_JSON";
private transient GroovyShell groovyShell;
@Extension @Symbol({"extendedChoice"})
public static class DescriptorImpl extends ParameterDescriptor {
@Override
public String getDisplayName() {
return Messages.ExtendedChoiceParameterDefinition_DisplayName();
}
public FormValidation doCheckPropertyFile(@QueryParameter final String propertyFile, @QueryParameter final String propertyKey,
@QueryParameter final String type) throws IOException, ServletException {
if(StringUtils.isBlank(propertyFile)) {
return FormValidation.ok();
}
Project project = new Project();
Property property = new Property();
property.setProject(project);
File prop = new File(propertyFile);
try {
if(prop.exists()) {
property.setFile(prop);
}
else {
URL propertyFileUrl = new URL(propertyFile);
property.setUrl(propertyFileUrl);
}
property.execute();
}
catch(MalformedURLException e) {
return FormValidation.warning(Messages.ExtendedChoiceParameterDefinition_PropertyFileDoesntExist(), propertyFile);
}
catch(BuildException e) {
return FormValidation.warning(Messages.ExtendedChoiceParameterDefinition_PropertyFileDoesntExist(), propertyFile);
}
if(PARAMETER_TYPE_MULTI_LEVEL_SINGLE_SELECT.equals(type) || PARAMETER_TYPE_MULTI_LEVEL_MULTI_SELECT.equals(type)) {
return FormValidation.ok();
}
else if(StringUtils.isNotBlank(propertyKey)) {
if(project.getProperty(propertyKey) != null) {
return FormValidation.ok();
}
else {
return FormValidation.warning(Messages.ExtendedChoiceParameterDefinition_PropertyFileExistsButProvidedKeyIsInvalid(), propertyFile, propertyKey);
}
}
else {
return FormValidation.warning(Messages.ExtendedChoiceParameterDefinition_PropertyFileExistsButNoProvidedKey(), propertyFile);
}
}
public FormValidation doCheckPropertyKey(@QueryParameter final String propertyFile, @QueryParameter final String propertyKey,
@QueryParameter final String type) throws IOException, ServletException {
return doCheckPropertyFile(propertyFile, propertyKey, type);
}
public FormValidation doCheckDefaultPropertyFile(@QueryParameter final String defaultPropertyFile,
@QueryParameter final String defaultPropertyKey, @QueryParameter final String type) throws IOException, ServletException {
return doCheckPropertyFile(defaultPropertyFile, defaultPropertyKey, type);
}
public FormValidation doCheckDefaultPropertyKey(@QueryParameter final String defaultPropertyFile,
@QueryParameter final String defaultPropertyKey, @QueryParameter final String type) throws IOException, ServletException {
return doCheckPropertyFile(defaultPropertyFile, defaultPropertyKey, type);
}
@Override
public ExtendedChoiceParameterDefinition newInstance(StaplerRequest req, JSONObject formData) throws FormException {
String name = null;
String type = null;
String description = null;
String multiSelectDelimiter = null;
boolean quoteValue = false;
boolean saveJSONParameterToFile = false;
int visibleItemCount = 5;
String propertyValue = null;
String propertyKey = null;
String propertyFile = null;
String groovyScript = null;
String groovyScriptFile = null;
String bindings = null;
String groovyClasspath = null;
String javascriptFile = null;
String javascript = null;
String defaultPropertyValue = null;
String defaultPropertyKey = null;
String defaultPropertyFile = null;
String defaultGroovyScript = null;
String defaultGroovyScriptFile = null;
String defaultBindings = null;
String defaultGroovyClasspath = null;
String descriptionPropertyValue = null;
String descriptionPropertyKey = null;
String descriptionPropertyFile = null;
String descriptionGroovyScript = null;
String descriptionGroovyScriptFile = null;
String descriptionBindings = null;
String descriptionGroovyClasspath = null;
String projectName = null;
name = formData.getString("name");
description = formData.getString("description");
AbstractProject, ?> project = Stapler.getCurrentRequest().findAncestorObject(AbstractProject.class);
if(project != null) {
projectName = project.getName();
}
JSONObject parameterGroup = formData.getJSONObject("parameterGroup");
if(parameterGroup != null) {
int value = parameterGroup.getInt("value");
if(value == 0) {
type = parameterGroup.getString("type");
quoteValue = parameterGroup.getBoolean("quoteValue");
visibleItemCount = parameterGroup.optInt("visibleItemCount", 5);
multiSelectDelimiter = parameterGroup.getString("multiSelectDelimiter");
if(StringUtils.isEmpty(multiSelectDelimiter)) {
multiSelectDelimiter = ",";
}
JSONObject propertySourceJSON = (JSONObject)parameterGroup.get("propertySource");
if(propertySourceJSON != null) {
if(propertySourceJSON.getInt("value") == 0) {
propertyValue = propertySourceJSON.getString("propertyValue");
}
else if(propertySourceJSON.getInt("value") == 1) {
propertyFile = propertySourceJSON.getString("propertyFile");
propertyKey = propertySourceJSON.getString("propertyKey");
}
else if(propertySourceJSON.getInt("value") == 2) {
groovyScript = propertySourceJSON.getString("groovyScript");
bindings = propertySourceJSON.getString("bindings");
groovyClasspath = propertySourceJSON.getString("groovyClasspath");
}
else if(propertySourceJSON.getInt("value") == 3) {
groovyScriptFile = propertySourceJSON.getString("groovyScriptFile");
bindings = propertySourceJSON.getString("bindings");
groovyClasspath = propertySourceJSON.getString("groovyClasspath");
}
}
JSONObject defaultPropertySourceJSON = (JSONObject)parameterGroup.get("defaultPropertySource");
if(defaultPropertySourceJSON != null) {
if(defaultPropertySourceJSON.getInt("value") == 0) {
defaultPropertyValue = defaultPropertySourceJSON.getString("defaultPropertyValue");
}
else if(defaultPropertySourceJSON.getInt("value") == 1) {
defaultPropertyFile = defaultPropertySourceJSON.getString("defaultPropertyFile");
defaultPropertyKey = defaultPropertySourceJSON.getString("defaultPropertyKey");
}
else if(defaultPropertySourceJSON.getInt("value") == 2) {
defaultGroovyScript = defaultPropertySourceJSON.getString("defaultGroovyScript");
defaultBindings = defaultPropertySourceJSON.getString("defaultBindings");
defaultGroovyClasspath = defaultPropertySourceJSON.getString("defaultGroovyClasspath");
}
else if(defaultPropertySourceJSON.getInt("value") == 3) {
defaultGroovyScriptFile = defaultPropertySourceJSON.getString("defaultGroovyScriptFile");
defaultBindings = defaultPropertySourceJSON.getString("defaultBindings");
defaultGroovyClasspath = defaultPropertySourceJSON.getString("defaultGroovyClasspath");
}
}
JSONObject descriptionPropertySourceJSON = (JSONObject)parameterGroup.get("descriptionPropertySource");
if(descriptionPropertySourceJSON != null) {
if(descriptionPropertySourceJSON.getInt("value") == 0) {
descriptionPropertyValue = descriptionPropertySourceJSON.getString("descriptionPropertyValue");
}
else if(descriptionPropertySourceJSON.getInt("value") == 1) {
descriptionPropertyFile = descriptionPropertySourceJSON.getString("descriptionPropertyFile");
descriptionPropertyKey = descriptionPropertySourceJSON.getString("descriptionPropertyKey");
}
else if(descriptionPropertySourceJSON.getInt("value") == 2) {
descriptionGroovyScript = descriptionPropertySourceJSON.getString("descriptionGroovyScript");
descriptionBindings = descriptionPropertySourceJSON.getString("descriptionBindings");
descriptionGroovyClasspath = descriptionPropertySourceJSON.getString("descriptionGroovyClasspath");
}
else if(descriptionPropertySourceJSON.getInt("value") == 3) {
descriptionGroovyScriptFile = descriptionPropertySourceJSON.getString("descriptionGroovyScriptFile");
descriptionBindings = descriptionPropertySourceJSON.getString("descriptionBindings");
descriptionGroovyClasspath = descriptionPropertySourceJSON.getString("descriptionGroovyClasspath");
}
}
}
else if(value == 1) {
type = parameterGroup.getString("type");
propertyFile = parameterGroup.getString("propertyFile");
propertyValue = parameterGroup.optString("propertyValue");
}
else if(value == 2) {
type = PARAMETER_TYPE_JSON;
JSONObject jsonParameterConfigSourceJSON = (JSONObject)parameterGroup.get("jsonParameterConfigSource");
if(jsonParameterConfigSourceJSON != null) {
if(jsonParameterConfigSourceJSON.getInt("value") == 0) {
groovyScript = jsonParameterConfigSourceJSON.getString("groovyScript");
groovyScriptFile = null;
bindings = jsonParameterConfigSourceJSON.getString("bindings");
groovyClasspath = jsonParameterConfigSourceJSON.getString("groovyClasspath");
}
else if(jsonParameterConfigSourceJSON.getInt("value") == 1) {
groovyScript = null;
groovyScriptFile = jsonParameterConfigSourceJSON.getString("groovyScriptFile");
bindings = jsonParameterConfigSourceJSON.getString("bindings");
groovyClasspath = jsonParameterConfigSourceJSON.getString("groovyClasspath");
}
}
JSONObject jsonParameterConfigJavascriptSourceJSON = (JSONObject)parameterGroup.get("jsonParameterConfigJavascriptSource");
if(jsonParameterConfigJavascriptSourceJSON != null) {
if(jsonParameterConfigJavascriptSourceJSON.getInt("value") == 0) {
javascript = jsonParameterConfigJavascriptSourceJSON.optString("javascript");
javascriptFile = null;
}
else if(jsonParameterConfigJavascriptSourceJSON.getInt("value") == 1) {
javascriptFile = jsonParameterConfigJavascriptSourceJSON.optString("javascriptFile");
javascript = null;
}
}
saveJSONParameterToFile = parameterGroup.optBoolean("saveJSONParameterToFile");
}
}
else {
type = formData.getString("type");
propertyFile = formData.getString("propertyFile");
propertyKey = formData.getString("propertyKey");
propertyValue = formData.optString("value");
defaultPropertyFile = formData.optString("defaultPropertyFile");
defaultPropertyKey = formData.optString("defaultPropertyKey");
defaultPropertyValue = formData.optString("defaultValue");
}
//@formatter:off
return new ExtendedChoiceParameterDefinition(name,
type,
propertyValue,
projectName,
propertyFile,
groovyScript,
groovyScriptFile,
bindings,
groovyClasspath,
propertyKey,
defaultPropertyValue,
defaultPropertyFile,
defaultGroovyScript,
defaultGroovyScriptFile,
defaultBindings,
defaultGroovyClasspath,
defaultPropertyKey,
descriptionPropertyValue,
descriptionPropertyFile,
descriptionGroovyScript,
descriptionGroovyScriptFile,
descriptionBindings,
descriptionGroovyClasspath,
descriptionPropertyKey,
javascriptFile,
javascript,
saveJSONParameterToFile,
quoteValue,
visibleItemCount,
description,
multiSelectDelimiter);
//@formatter:on
}
}
private boolean quoteValue;
private boolean saveJSONParameterToFile;
private int visibleItemCount;
private String type;
private String value;
private String propertyFile;
private String groovyScript;
private String groovyScriptFile;
private String bindings;
private String groovyClasspath;
private String propertyKey;
private String defaultValue;
private String defaultPropertyFile;
private String defaultGroovyScript;
private String defaultGroovyScriptFile;
private String defaultBindings;
private String defaultGroovyClasspath;
private String defaultPropertyKey;
private String multiSelectDelimiter;
private String descriptionPropertyValue;
private String descriptionPropertyFile;
private String descriptionGroovyScript;
private String descriptionGroovyScriptFile;
private String descriptionBindings;
private String descriptionGroovyClasspath;
private String descriptionPropertyKey;
private String javascriptFile;
private String javascript;
private String projectName;
//@formatter:off
@DataBoundConstructor
public ExtendedChoiceParameterDefinition(String name,
String type,
String value,
String projectName,
String propertyFile,
String groovyScript,
String groovyScriptFile,
String bindings,
String groovyClasspath,
String propertyKey,
String defaultValue,
String defaultPropertyFile,
String defaultGroovyScript,
String defaultGroovyScriptFile,
String defaultBindings,
String defaultGroovyClasspath,
String defaultPropertyKey,
String descriptionPropertyValue,
String descriptionPropertyFile,
String descriptionGroovyScript,
String descriptionGroovyScriptFile,
String descriptionBindings,
String descriptionGroovyClasspath,
String descriptionPropertyKey,
String javascriptFile,
String javascript,
boolean saveJSONParameterToFile,
boolean quoteValue,
int visibleItemCount,
String description,
String multiSelectDelimiter) {
//@formatter:on
super(name, description);
this.type = type;
this.value = value;
this.projectName = projectName;
this.propertyFile = propertyFile;
this.propertyKey = propertyKey;
this.groovyScript = groovyScript;
this.groovyScriptFile = groovyScriptFile;
this.bindings = bindings;
this.groovyClasspath = groovyClasspath;
this.defaultValue = defaultValue;
this.defaultPropertyFile = defaultPropertyFile;
this.defaultPropertyKey = defaultPropertyKey;
this.defaultGroovyScript = defaultGroovyScript;
this.defaultGroovyScriptFile = defaultGroovyScriptFile;
this.defaultBindings = defaultBindings;
this.defaultGroovyClasspath = defaultGroovyClasspath;
this.descriptionPropertyValue = descriptionPropertyValue;
this.descriptionPropertyFile = descriptionPropertyFile;
this.descriptionPropertyKey = descriptionPropertyKey;
this.descriptionGroovyScript = descriptionGroovyScript;
this.descriptionGroovyScriptFile = descriptionGroovyScriptFile;
this.descriptionBindings = descriptionBindings;
this.descriptionGroovyClasspath = descriptionGroovyClasspath;
this.javascriptFile = javascriptFile;
this.javascript = javascript;
this.saveJSONParameterToFile = saveJSONParameterToFile;
this.quoteValue = quoteValue;
if(visibleItemCount == 0) {
visibleItemCount = 5;
}
this.visibleItemCount = visibleItemCount;
if(multiSelectDelimiter == null || "".equals(multiSelectDelimiter)) {
multiSelectDelimiter = ",";
}
this.multiSelectDelimiter = multiSelectDelimiter;
}
private Map computeDefaultValueMap() {
Map defaultValueMap = null;
String effectiveDefaultValue = computeEffectiveDefaultValue();
if(!StringUtils.isBlank(effectiveDefaultValue)) {
defaultValueMap = new HashMap();
String[] defaultValues = StringUtils.split(effectiveDefaultValue, ',');
for(String value: defaultValues) {
defaultValueMap.put(StringUtils.trim(value), true);
}
}
return defaultValueMap;
}
private Map computeDescriptionPropertyValueMap(String effectiveValue) {
Map descriptionPropertyValueMap = null;
if(effectiveValue != null) {
String[] values = effectiveValue.split(",");
String effectiveDescriptionPropertyValue = computeEffectiveDescriptionPropertyValue();
if(!StringUtils.isBlank(effectiveDescriptionPropertyValue)) {
descriptionPropertyValueMap = new HashMap();
String[] descriptionPropertyValues = StringUtils.split(effectiveDescriptionPropertyValue, ',');
for(int i = 0; i < values.length && i < descriptionPropertyValues.length; i++) {
descriptionPropertyValueMap.put(values[i], descriptionPropertyValues[i]);
}
}
}
return descriptionPropertyValueMap;
}
@Override
public ParameterValue createValue(StaplerRequest request) {
String[] requestValues = request.getParameterValues(getName());
return createValue(requestValues);
}
@Override
public ParameterValue createValue(CLICommand command, String value) throws IOException, InterruptedException {
String[] requestValues = (value != null) ? value.split(",") : null;
return createValue(requestValues);
}
ParameterValue createValue(String[] requestValues) {
if(requestValues == null || requestValues.length == 0) {
return getDefaultParameterValue();
}
if(PARAMETER_TYPE_TEXT_BOX.equals(type) || PARAMETER_TYPE_HIDDEN.equals(type)) {
return new ExtendedChoiceParameterValue(getName(), requestValues[0]);
}
else {
String valueStr = computeEffectiveValue();
if(valueStr != null) {
List result = new ArrayList<>();
String[] values = valueStr.split(",");
Set valueSet = new HashSet<>();
for(String value: values) {
valueSet.add(value);
}
for(String requestValue: requestValues) {
if(valueSet.contains(requestValue)) {
result.add(requestValue);
}
}
return new ExtendedChoiceParameterValue(getName(), StringUtils.join(result, getMultiSelectDelimiter()));
}
}
return null;
}
@Override
public ParameterValue createValue(StaplerRequest request, JSONObject jO) {
Object value = jO.get("value");
String strValue = "";
if(value instanceof String) {
strValue = (String)value;
}
else if(value instanceof JSONArray) {
StringBuilder sB = new StringBuilder();
JSONArray jsonValues = (JSONArray)value;
if(isMultiLevelParameterType()) {
final int valuesBetweenLevels = this.value.split(",").length;
Iterator> it = jsonValues.iterator();
for(int i = 1; it.hasNext(); i++) {
String nextValue = it.next().toString();
if(i % valuesBetweenLevels == 0) {
if(sB.length() > 0) {
sB.append(getMultiSelectDelimiter());
}
sB.append(nextValue);
}
}
strValue = sB.toString();
}
else {
strValue = StringUtils.join(jsonValues.iterator(), getMultiSelectDelimiter());
}
}
if(quoteValue) {
strValue = """ + strValue + """;
}
return new ExtendedChoiceParameterValue(getName(), strValue);
}
private boolean isMultiLevelParameterType() {
return type.equals(PARAMETER_TYPE_MULTI_LEVEL_SINGLE_SELECT) || type.equals(PARAMETER_TYPE_MULTI_LEVEL_MULTI_SELECT);
}
private boolean isBasicParameterType() {
return type.equals(PARAMETER_TYPE_SINGLE_SELECT) || type.equals(PARAMETER_TYPE_MULTI_SELECT) || type.equals(PARAMETER_TYPE_CHECK_BOX) || type.equals(PARAMETER_TYPE_RADIO) || type.equals(PARAMETER_TYPE_TEXT_BOX) || type.equals(PARAMETER_TYPE_HIDDEN);
}
@Override
public ParameterValue getDefaultParameterValue() {
if(isBasicParameterType()) {
String defaultValue = computeEffectiveDefaultValue();
if(!StringUtils.isBlank(defaultValue)) {
if(quoteValue) {
defaultValue = """ + defaultValue + """;
}
return new ExtendedChoiceParameterValue(getName(), defaultValue);
}
}
return super.getDefaultParameterValue();
}
// note that computeValue is not called by multiLevel.jelly
private String computeValue(String value, String propertyFilePath, String propertyKey, String groovyScript, String groovyScriptFile,
String bindings, String groovyClasspath, boolean isSingleValued) {
if(!StringUtils.isBlank(propertyFilePath) && !StringUtils.isBlank(propertyKey)) {
try {
String resolvedPropertyFilePath = expandVariables(propertyFilePath);
File propertyFile = new File(resolvedPropertyFilePath);
if(propertyFile.exists()) {
Project project = new Project();
Property property = new Property();
property.setProject(project);
property.setFile(propertyFile);
property.execute();
return project.getProperty(propertyKey);
}
else {
Project project = new Project();
Property property = new Property();
property.setProject(project);
URL propertyFileUrl = new URL(resolvedPropertyFilePath);
property.setUrl(propertyFileUrl);
property.execute();
return project.getProperty(propertyKey);
}
}
catch(Exception e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
}
else if(!StringUtils.isBlank(groovyScript)) {
return executeGroovyScriptAndProcessGroovyValue(groovyScript, bindings, groovyClasspath, isSingleValued);
}
else if(!StringUtils.isBlank(groovyScriptFile)) {
return executeGroovyScriptFile(groovyScriptFile, bindings, groovyClasspath, isSingleValued);
}
else if(!StringUtils.isBlank(value)) {
return value;
}
return null;
}
private String executeGroovyScriptFile(String groovyScriptFile, String bindings, String groovyClasspath, boolean isSingleValued) {
String result = null;
try {
String groovyScript = loadGroovyScriptFile(groovyScriptFile);
result = executeGroovyScriptAndProcessGroovyValue(groovyScript, bindings, groovyClasspath, isSingleValued);
}
catch(Exception e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
return result;
}
private String loadGroovyScriptFile(String groovyScriptFile) throws IOException {
String resolvedGroovyScriptFile = expandVariables(groovyScriptFile);
String groovyScript = Util.loadFile(new File(resolvedGroovyScriptFile));
return groovyScript;
}
private String executeGroovyScriptAndProcessGroovyValue(String groovyScript, String bindings, String groovyClasspath, boolean isSingleValued) {
String result = null;
try {
Object groovyValue = executeGroovyScript(groovyScript, bindings, groovyClasspath);
result = processGroovyValue(isSingleValued, groovyValue);
}
catch(Exception e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
return result;
}
private Object executeGroovyScript(String groovyScript, String bindings, String groovyClasspath) throws URISyntaxException, IOException {
Object groovyValue = null;
if(checkScriptApproval(groovyScript, groovyClasspath, false)) {
GroovyShell groovyShell = getGroovyShell(groovyClasspath);
GroovyCodeSource codeSource = new GroovyCodeSource(groovyScript, computeMD5Hash(groovyScript), "/groovy/shell");
groovyShell.getClassLoader().parseClass(codeSource, true);
setBindings(groovyShell, bindings);
groovyValue = groovyShell.evaluate(codeSource);
}
return groovyValue;
}
private String computeMD5Hash(String str) {
String result = str;
if(str != null) {
result = DigestUtils.md5Hex(str);
}
result = "_" + result;
return result;
}
private Binding getGroovyBinding() {
Binding groovyBinding = null;
StaplerRequest currentRequest = Stapler.getCurrentRequest();
if(currentRequest != null) {
groovyBinding = (Binding)currentRequest.getAttribute(ATTR_REQUEST_GROOVY_BINDING);
if(groovyBinding == null) {
groovyBinding = new Binding();
currentRequest.setAttribute(ATTR_REQUEST_GROOVY_BINDING, groovyBinding);
}
}
else {
groovyBinding = new Binding();
}
return groovyBinding;
}
private synchronized GroovyShell getGroovyShell(String groovyClasspath) {
if(groovyShell == null) {
Jenkins jenkins = Jenkins.getInstance();
if(jenkins != null) {
ClassLoader cl = jenkins.getPluginManager().uberClassLoader;
if(cl == null) {
cl = Thread.currentThread().getContextClassLoader();
}
CompilerConfiguration compilerConfiguration = new CompilerConfiguration();
if(!StringUtils.isBlank(groovyClasspath)) {
compilerConfiguration.setClasspath(groovyClasspath);
}
Binding groovyBinding = getGroovyBinding();
groovyShell = new GroovyShell(cl, groovyBinding, compilerConfiguration);
}
}
else {
if(!StringUtils.isBlank(groovyClasspath)) {
String[] groovyClasspathElements = groovyClasspath.split(";");
for(String groovyClasspathElement: groovyClasspathElements) {
groovyShell.getClassLoader().addClasspath(groovyClasspathElement);
}
}
try {
Binding groovyBinding = getGroovyBinding();
Field contextField = groovyShell.getClass().getDeclaredField("context");
contextField.setAccessible(true);
contextField.set(groovyShell, groovyBinding);
}
catch(NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
}
return groovyShell;
}
private String processGroovyValue(boolean isSingleValued, Object groovyValue) {
String value = null;
if(groovyValue instanceof String[]) {
String[] groovyValues = (String[])groovyValue;
if(!isSingleValued) {
value = StringUtils.join((String[])groovyValue, multiSelectDelimiter);
}
else if(groovyValues.length > 0) {
value = groovyValues[0];
}
}
else if(groovyValue instanceof List>) {
List> groovyValues = (List>)groovyValue;
if(!isSingleValued) {
value = StringUtils.join(groovyValues, multiSelectDelimiter);
}
else if(!groovyValues.isEmpty()) {
value = (String)groovyValues.get(0);
}
}
else if(groovyValue instanceof String) {
value = (String)groovyValue;
}
return value;
}
private void setBindings(GroovyShell shell, String bindings) throws IOException {
if(bindings != null) {
Properties p = new Properties();
p.load(new StringReader(bindings));
for(Map.Entry