Skip to content

Commit

Permalink
[FIXED JENKINS-29476] Add jenkinsProject variable to binding context
Browse files Browse the repository at this point in the history
  • Loading branch information
kinow committed Dec 20, 2015
1 parent 84e6849 commit 920bd25
Show file tree
Hide file tree
Showing 2 changed files with 170 additions and 16 deletions.
92 changes: 76 additions & 16 deletions src/main/java/org/biouno/unochoice/AbstractScriptableParameter.java
@@ -1,7 +1,7 @@
/*
* The MIT License (MIT)
*
* Copyright (c) <2014-2015> <Ioannis Moutsatsos, Bruno P. Kinoshita>
* Copyright (c) 2014-2015 Ioannis Moutsatsos, Bruno P. Kinoshita
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
Expand All @@ -24,37 +24,58 @@

package org.biouno.unochoice;

import hudson.model.ParameterValue;
import hudson.model.StringParameterValue;

import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;

import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
import org.biouno.unochoice.model.Script;
import org.biouno.unochoice.util.ScriptCallback;
import org.biouno.unochoice.util.Utils;
import org.kohsuke.stapler.Ancestor;
import org.kohsuke.stapler.Stapler;
import org.kohsuke.stapler.StaplerRequest;

import hudson.model.ParameterValue;
import hudson.model.Project;
import hudson.model.StringParameterValue;

/**
* Base class for parameters with scripts.
*
* @author Bruno P. Kinoshita
* @since 0.20
*/
public abstract class AbstractScriptableParameter extends AbstractUnoChoiceParameter implements ScriptableParameter<Map<Object, Object>> {
public abstract class AbstractScriptableParameter extends AbstractUnoChoiceParameter
implements ScriptableParameter<Map<Object, Object>> {

/*
* Serial UID.
*/
private static final long serialVersionUID = -1718340722437175976L;

protected static final String SEPARATOR = "__LESEP__"; // used to split values that come from the UI via Ajax POST's

protected final Script script;

private static final long serialVersionUID = -6533352776594510145L;
/**
* Used to split values that come from the UI via Ajax POST's
*/
protected static final String SEPARATOR = "__LESEP__";
/**
* Constant used to add the project in the environment variables map.
*/
protected static final String JENKINS_PROJECT_VARIABLE_NAME = "jenkinsProject";
/**
* Number of visible items on the screen.
*/
private volatile int visibleItemCount = 1;
/**
* Script used to render the parameter.
*/
protected final Script script;
/**
* The project name.
*/
private final String projectName;

/**
* Inherited constructor.
Expand All @@ -69,6 +90,7 @@ public abstract class AbstractScriptableParameter extends AbstractUnoChoiceParam
protected AbstractScriptableParameter(String name, String description, Script script) {
super(name, description);
this.script = script;
this.projectName = null;
}

/**
Expand All @@ -84,6 +106,22 @@ protected AbstractScriptableParameter(String name, String description, Script sc
protected AbstractScriptableParameter(String name, String description, String randomName, Script script) {
super(name, description, randomName);
this.script = script;
// Try to get the project name from the current request. In case of being called in some other non-web way,
// the name will be fetched later via Jenkins.getInstance() and iterating through all items. This is for a
// performance wise approach first.
final StaplerRequest currentRequest = Stapler.getCurrentRequest();
String projectName = null;
if (currentRequest != null) {
final Ancestor ancestor = currentRequest.findAncestor(Project.class);
if (ancestor != null) {
final Object o = ancestor.getObject();
if (o instanceof Project) {
final Project<?, ?> project = (Project<?, ?>) o;
projectName = project.getName();
}
}
}
this.projectName = projectName;
}

/**
Expand All @@ -96,15 +134,34 @@ public Script getScript() {
}

/**
* Gets the current parameters, be it before or after other referenced parameters
* triggered an update.
* Gets the current parameters, be it before or after other referenced parameters triggered an update. Populates
* parameters common to all evaluations, such as jenkinsProject, which is the current Jenkins project.
*
* @return the current parameters
* @return the current parameters with pre-populated defaults
*/
public Map<Object, Object> getParameters() {
return Collections.emptyMap();
}

/**
* Helper parameters used to render the parameter definition.
* @return Map with helper parameters
*/
private Map<Object, Object> getHelperParameters() {
final Map<Object, Object> helperParameters = new LinkedHashMap<Object, Object>();
Project<?, ?> project = null;
if (StringUtils.isNotBlank(this.projectName)) {
// first we try to get the item given its name, which is more efficient
project = Utils.getProjectByName(this.projectName);
} else {
// otherwise, in case we don't have the item name, we iterate looking for a job that uses this UUID
project = Utils.findProjectByParameterUUID(this.getRandomName());
}
if (project != null)
helperParameters.put(JENKINS_PROJECT_VARIABLE_NAME, project);
return helperParameters;
}

public Map<Object, Object> getChoices() {
Map<Object, Object> choices = this.getChoices(getParameters());
visibleItemCount = choices.size();
Expand Down Expand Up @@ -133,7 +190,8 @@ public Map<Object, Object> getChoices(Map<Object, Object> parameters) {
visibleItemCount = map.size();
return map;
}
LOGGER.warning(String.format("Script parameter with name '%s' is not an instance of java.util.Map. The parameter value is %s", getName(), value));
LOGGER.warning(String.format("Script parameter with name '%s' is not an instance of java.util.Map. The "
+ "parameter value is %s", getName(), value));
return Collections.emptyMap();
}

Expand All @@ -151,7 +209,9 @@ public String getChoicesAsString(Map<Object, Object> parameters) {
@SuppressWarnings({ "rawtypes", "unchecked" })
private Object eval(Map<Object, Object> parameters) {
try {
final ScriptCallback<Exception> callback = new ScriptCallback(getName(), script, parameters);
Map<Object, Object> scriptParameters = getHelperParameters();
scriptParameters.putAll(parameters);
final ScriptCallback<Exception> callback = new ScriptCallback(getName(), script, scriptParameters);
return callback.call();
} catch (Exception e) {
LOGGER.log(Level.SEVERE, "Error executing script for dynamic parameter", e);
Expand Down
94 changes: 94 additions & 0 deletions src/main/java/org/biouno/unochoice/util/Utils.java
Expand Up @@ -24,13 +24,22 @@

package org.biouno.unochoice.util;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
import org.biouno.unochoice.AbstractUnoChoiceParameter;
import org.jenkinsci.plugins.scriptler.config.Script;
import org.jenkinsci.plugins.scriptler.config.ScriptlerConfiguration;

import hudson.model.ParameterDefinition;
import hudson.model.ParametersDefinitionProperty;
import hudson.model.Project;
import jenkins.model.Jenkins;

/**
* Utility methods.
*
Expand Down Expand Up @@ -111,4 +120,89 @@ public static String createRandomParameterName(String prefix, String suffix) {
public static Map<String, String> getSystemEnv() {
return System.getenv();
}

/**
* Get project in Jenkins given its name.
*
* @since 1.3
* @param projectName project name in Jenkins
* @return Project or {@code null} if none with this name
*/
public static Project<?, ?> getProjectByName(String projectName) {
Jenkins instance = Jenkins.getInstance();
if (instance != null) {
Object o = instance.getItem(projectName);
if (o instanceof Project)
return (Project<?, ?>) o;
}
return null;
}

/**
* Find the current project give its parameter UUID.
*
* @author dynamic-parameter-plugin
* @since 1.3
* @param parameterUUID parameter UUID
* @return {@code null} if the current project cannot be found
*/
@SuppressWarnings("rawtypes")
public static Project findProjectByParameterUUID(String parameterUUID) {
Jenkins instance = Jenkins.getInstance();
if (instance != null) {
List<Project> projects = instance.getAllItems(Project.class);
for (Project project : projects) {
if (isParameterDefintionOf(parameterUUID, project)) {
return project;
}
}
}
return null;
}

/**
* Returns true if this parameter definition is a definition of the given project.
*
* @since 1.3
* @author dynamic-parameter-plugin
* @param parameterUUID UUID of the project parameter
* @param project the project to search for this parameter definition.
* @return {@code true} if the project contains this parameter definition.
*/
@SuppressWarnings("rawtypes")
private static boolean isParameterDefintionOf(String parameterUUID, Project project) {
List<ParameterDefinition> parameterDefinitions = getProjectParameterDefinitions(project);
for (ParameterDefinition pd : parameterDefinitions) {
if (pd instanceof AbstractUnoChoiceParameter) {
AbstractUnoChoiceParameter parameterDefinition = (AbstractUnoChoiceParameter) pd;
String uuid = parameterDefinition.getRandomName();
if (ObjectUtils.equals(parameterUUID, uuid)) {
return true;
}
}
}
return false;
}


/**
* Get the parameter definitions for the given project.
*
* @since 1.3
* @author dynamic-parameter-plugin
* @param project the project for which the parameter definitions should be found
* @return parameter definitions or an empty list
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public static List<ParameterDefinition> getProjectParameterDefinitions(Project project) {
ParametersDefinitionProperty parametersDefinitionProperty = (ParametersDefinitionProperty) project
.getProperty(ParametersDefinitionProperty.class);
if (parametersDefinitionProperty != null) {
List<ParameterDefinition> parameterDefinitions = parametersDefinitionProperty.getParameterDefinitions();
if (parameterDefinitions != null) {
return parameterDefinitions;
}
}
return Collections.EMPTY_LIST;
}
}

0 comments on commit 920bd25

Please sign in to comment.