Skip to content

Commit

Permalink
[JENKINS-17875] Improved the way to retrieve (and keep) project.
Browse files Browse the repository at this point in the history
  • Loading branch information
ikedam committed Dec 6, 2013
1 parent 3862977 commit 3fed072
Show file tree
Hide file tree
Showing 5 changed files with 189 additions and 29 deletions.
Expand Up @@ -27,9 +27,11 @@
import java.util.List;
import java.util.regex.Pattern;

import jenkins.model.Jenkins;
import hudson.Extension;
import hudson.DescriptorExtensionList;
import hudson.model.Descriptor;
import hudson.model.Describable;
import hudson.model.ParameterValue;
import hudson.model.StringParameterValue;
import hudson.model.SimpleParameterDefinition;
Expand Down Expand Up @@ -79,6 +81,73 @@ public static Pattern getNamePattern()
@Extension
public static class DescriptorImpl extends ParameterDescriptor
{
/**
* Create a new instance of {@link SystemGroovyChoiceListProvider} from user inputs.
*
* @param req
* @param formData
* @return
* @throws hudson.model.Descriptor.FormException
* @see hudson.model.Descriptor#newInstance(org.kohsuke.stapler.StaplerRequest, net.sf.json.JSONObject)
*/
@Override
public ExtensibleChoiceParameterDefinition newInstance(StaplerRequest req,
JSONObject formData)
throws hudson.model.Descriptor.FormException
{
return new ExtensibleChoiceParameterDefinition(
formData.getString("name"),
bindJSONWithDescriptor(req, formData, "choiceListProvider", ChoiceListProvider.class),
formData.getBoolean("editable"),
formData.getString("description")
);
}

/**
* Create a new {@link Describable} object from user inputs.
*
* @param req
* @param formData
* @param fieldName
* @param clazz
* @return
* @throws hudson.model.Descriptor.FormException
*/
private <T extends Describable<?>> T bindJSONWithDescriptor(
StaplerRequest req,
JSONObject formData,
String fieldName,
Class<T> clazz
) throws hudson.model.Descriptor.FormException {
formData = formData.getJSONObject(fieldName);
if (formData == null || formData.isNullObject()) {
return null;
}
if (!formData.has("stapler-class")) {
throw new FormException("No stapler-class is specified", fieldName);
}
String staplerClazzName = formData.getString("stapler-class");
if (staplerClazzName == null) {
throw new FormException("No stapler-class is specified", fieldName);
}
try {
@SuppressWarnings("unchecked")
Class<? extends T> staplerClass = (Class<? extends T>)Jenkins.getInstance().getPluginManager().uberClassLoader.loadClass(staplerClazzName);
Descriptor<?> d = Jenkins.getInstance().getDescriptorOrDie(staplerClass);

@SuppressWarnings("unchecked")
T instance = (T)d.newInstance(req, formData);

return instance;
} catch(ClassNotFoundException e) {
throw new FormException(
String.format("Failed to instantiate %s", staplerClazzName),
e,
fieldName
);
}
}

/**
* Returns the string to be shown in a job configuration page, in the dropdown of &quot;Add Parameter&quot;.
*
Expand Down
Expand Up @@ -38,12 +38,14 @@
import java.util.logging.Logger;

import jenkins.model.Jenkins;
import net.sf.json.JSONObject;

import org.apache.commons.lang.StringUtils;
import org.codehaus.groovy.control.CompilerConfiguration;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.Stapler;
import org.kohsuke.stapler.StaplerRequest;

/**
* A choice provider whose choices are determined by a Groovy script.
Expand All @@ -69,6 +71,24 @@ public class SystemGroovyChoiceListProvider extends ChoiceListProvider implement
@Extension
public static class DescriptorImpl extends Descriptor<ChoiceListProvider>
{
/**
* Create a new instance of {@link SystemGroovyChoiceListProvider} from user inputs.
*
* @param req
* @param formData
* @return
* @throws hudson.model.Descriptor.FormException
* @see hudson.model.Descriptor#newInstance(org.kohsuke.stapler.StaplerRequest, net.sf.json.JSONObject)
*/
@Override
public SystemGroovyChoiceListProvider newInstance(StaplerRequest req, JSONObject formData)
throws hudson.model.Descriptor.FormException
{
SystemGroovyChoiceListProvider provider = (SystemGroovyChoiceListProvider)super.newInstance(req, formData);
provider.setProject(req.findAncestorObject(AbstractProject.class));
return provider;
}

/**
* the display name shown in the dropdown to select a choice provider.
*
Expand All @@ -84,18 +104,19 @@ public String getDisplayName()
/**
* Returns the selection of a default choice.
*
* @param choiceListText
* @param req null passed in tests.
* @param scriptText
* @return the selection of a default choice
*/
public ListBoxModel doFillDefaultChoiceItems(@QueryParameter String scriptText)
public ListBoxModel doFillDefaultChoiceItems(StaplerRequest req, @QueryParameter String scriptText)
{
ListBoxModel ret = new ListBoxModel();
ret.add(Messages.ExtensibleChoiceParameterDefinition_NoDefaultChoice(), NoDefaultChoice);

List<String> choices = null;
try
{
choices = runScript(scriptText);
choices = runScript(scriptText, (req != null)?req.findAncestorObject(AbstractProject.class):null);
}
catch(Exception e)
{
Expand All @@ -113,12 +134,12 @@ public ListBoxModel doFillDefaultChoiceItems(@QueryParameter String scriptText)
return ret;
}

public FormValidation doTest(@QueryParameter String scriptText)
public FormValidation doTest(StaplerRequest req, @QueryParameter String scriptText)
{
List<String> choices = null;
try
{
choices = runScript(scriptText);
choices = runScript(scriptText, (req != null)?req.findAncestorObject(AbstractProject.class):null);
}
catch(Exception e)
{
Expand All @@ -144,9 +165,19 @@ public FormValidation doTest(@QueryParameter String scriptText)
public List<String> getChoiceList()
{
List<String> ret = null;
AbstractProject<?,?> project = getProject();
if(project == null)
{
// try to retrieve from current request.
if(Stapler.getCurrentRequest() != null)
{
project = Stapler.getCurrentRequest().findAncestorObject(AbstractProject.class);
}
}

try
{
ret = runScript(getScriptText());
ret = runScript(getScriptText(), project);
}
catch(Exception e)
{
Expand All @@ -155,7 +186,7 @@ public List<String> getChoiceList()
return (ret != null)?ret:new ArrayList<String>(0);
}

private static List<String> runScript(String scriptText) {
private static List<String> runScript(String scriptText, AbstractProject<?,?> project) {
CompilerConfiguration compilerConfig = new CompilerConfiguration();

// see RemotingDiagnostics.Script
Expand All @@ -167,11 +198,7 @@ private static List<String> runScript(String scriptText) {

Binding binding = new Binding();
binding.setVariable("jenkins", Jenkins.getInstance());
if (Stapler.getCurrentRequest() != null) {
binding.setVariable("project", Stapler.getCurrentRequest().findAncestorObject(AbstractProject.class));
} else {
binding.setVariable("project", null);
}
binding.setVariable("project", project);
GroovyShell shell =
new GroovyShell(cl, binding, compilerConfig);

Expand Down Expand Up @@ -236,4 +263,27 @@ public SystemGroovyChoiceListProvider(String scriptText, String defaultChoice)
this.scriptText = scriptText;
this.defaultChoice = (!NoDefaultChoice.equals(defaultChoice))?defaultChoice:null;
}

/**
* The project of this is configured in.
* This will be stored in job configuration XML like
* &lt;project class=&quot;project&quot; reference=&quot;../../../../../..&quot; /&gt;
*/
private AbstractProject<?,?> project;

/**
* @param project
*/
protected void setProject(AbstractProject<?,?> project)
{
this.project = project;
}

/**
* @return
*/
protected AbstractProject<?,?> getProject()
{
return project;
}
}
Expand Up @@ -11,7 +11,7 @@
<dt>jenkins</dt>
<dd>The instance of <a href="http://javadoc.jenkins-ci.org/jenkins/model/Jenkins.html">Jenkins</a>. Just a short cut for Jenkins.getInstance().</dd>
<dt>project</dt>
<dd>The project. An instance of <a href="http://javadoc.jenkins-ci.org/hudson/model/AbstractProject.html">AbstractProject</a>. Available only when a build is triggered from a browser. Otherwise, e.g. when triggered with polling or triggered from CLI, this will be null.</dd>
<dd>The project. An instance of <a href="http://javadoc.jenkins-ci.org/hudson/model/AbstractProject.html">AbstractProject</a>.</dd>
</dl>
<br>
<br>
Expand Down
Expand Up @@ -10,7 +10,7 @@
<dt>jenkins</dt>
<dd><a href="http://javadoc.jenkins-ci.org/jenkins/model/Jenkins.html">Jenkins</a> のインスタンス。 Jenkins.getInstance() のショートカットです。</dd>
<dt>project</dt>
<dd>対象のプロジェクト。<a href="http://javadoc.jenkins-ci.org/hudson/model/AbstractProject.html">AbstractProject</a> のインスタンス。ブラウザからビルドを行った時のみ有効で、それ以外の場合 (ポーリング時、CLIからの起動時など) は null になります。</dd>
<dd>対象のプロジェクト。<a href="http://javadoc.jenkins-ci.org/hudson/model/AbstractProject.html">AbstractProject</a> のインスタンス。</dd>
</dl>
<br>
<p>スクリプトの例:</p>
Expand Down

0 comments on commit 3fed072

Please sign in to comment.