| author | akozak | 2011-11-24 09:07:55 (EST) |
|---|---|---|
| committer | Winston Prakash | 2011-12-01 20:47:27 (EST) |
| commit | 420c7e90aef75f0fe5397b7ae64ff9d8e4a2f16b (patch) (side-by-side diff) | |
| tree | e6ef9081063180473d7b029eafeb0b1134664f74 | |
| parent | cd71b16352e845e62873a075fea145e13c667f3e (diff) | |
| download | org.eclipse.hudson.core-420c7e90aef75f0fe5397b7ae64ff9d8e4a2f16b.zip org.eclipse.hudson.core-420c7e90aef75f0fe5397b7ae64ff9d8e4a2f16b.tar.gz org.eclipse.hudson.core-420c7e90aef75f0fe5397b7ae64ff9d8e4a2f16b.tar.bz2 | |
Implement cascading functionality for Build Parameters
Signed-off-by: Winston Prakash <winston.prakash@gmail.com>
9 files changed, 286 insertions, 51 deletions
diff --git a/hudson-core/src/main/java/hudson/model/AbstractProject.java b/hudson-core/src/main/java/hudson/model/AbstractProject.java index ed73899..422a0ed 100644 --- a/hudson-core/src/main/java/hudson/model/AbstractProject.java +++ b/hudson-core/src/main/java/hudson/model/AbstractProject.java @@ -843,7 +843,7 @@ public abstract class AbstractProject<P extends AbstractProject<P,R>,R extends A protected List<Action> createTransientActions() { Vector<Action> ta = new Vector<Action>(); - for (JobProperty<? super P> p : properties) + for (JobProperty<? super P> p : getAllProperties()) ta.addAll(p.getJobActions((P)this)); for (TransientProjectActionFactory tpaf : TransientProjectActionFactory.all()) @@ -1386,7 +1386,7 @@ public abstract class AbstractProject<P extends AbstractProject<P,R>,R extends A r.add(this); for (SubTaskContributor euc : SubTaskContributor.all()) r.addAll(euc.forProject(this)); - for (JobProperty<? super P> p : properties) + for (JobProperty<? super P> p : getAllProperties()) r.addAll(p.getSubTasks()); return r; } diff --git a/hudson-core/src/main/java/hudson/model/Items.java b/hudson-core/src/main/java/hudson/model/Items.java index d3b6cbb..ccae37d 100644 --- a/hudson-core/src/main/java/hudson/model/Items.java +++ b/hudson-core/src/main/java/hudson/model/Items.java @@ -22,6 +22,7 @@ import hudson.Extension; import org.eclipse.hudson.api.model.project.property.AxisListProjectProperty; import org.eclipse.hudson.api.model.project.property.BaseProjectProperty; import org.eclipse.hudson.api.model.project.property.BooleanProjectProperty; +import org.eclipse.hudson.api.model.project.property.CopyOnWriteListProjectProperty; import org.eclipse.hudson.api.model.project.property.DescribableListProjectProperty; import org.eclipse.hudson.api.model.project.property.ExternalProjectProperty; import org.eclipse.hudson.api.model.project.property.IntegerProjectProperty; @@ -148,10 +149,10 @@ public class Items { XSTREAM.alias("log-rotator-property", LogRotatorProjectProperty.class); XSTREAM.alias("result-property", ResultProjectProperty.class); + XSTREAM.alias("copy-write-list-property", CopyOnWriteListProjectProperty.class); XSTREAM.alias("axis-list-property", AxisListProjectProperty.class); XSTREAM.alias("describable-list-property", DescribableListProjectProperty.class); XSTREAM.aliasField("project-properties", Job.class, "jobProperties"); - //TODO: think about migrating to xstream's annotations. XSTREAM.alias("appointed-node-property", AppointedNode.class); } } diff --git a/hudson-core/src/main/java/hudson/model/Job.java b/hudson-core/src/main/java/hudson/model/Job.java index 4d8dcf9..17baabb 100644 --- a/hudson-core/src/main/java/hudson/model/Job.java +++ b/hudson-core/src/main/java/hudson/model/Job.java @@ -20,6 +20,7 @@ package hudson.model; import hudson.Functions; import hudson.util.CascadingUtil; import java.util.concurrent.CopyOnWriteArraySet; +import org.apache.commons.collections.ListUtils; import org.apache.commons.collections.MapUtils; import org.eclipse.hudson.api.model.project.property.AxisListProjectProperty; import org.eclipse.hudson.api.model.project.property.BaseProjectProperty; @@ -128,6 +129,7 @@ public abstract class Job<JobT extends Job<JobT, RunT>, RunT extends Run<JobT, R private static transient final String PROJECT_PROPERTY_KEY_PREFIX = "has"; public static final String PROPERTY_NAME_SEPARATOR = ";"; public static final String LOG_ROTATOR_PROPERTY_NAME = "logRotator"; + public static final String PARAMETERS_DEFINITION_JOB_PROPERTY_PROPERTY_NAME = "parametersDefinitionProperties"; /** * Next build number. Kept in a separate file because this is the only @@ -173,6 +175,12 @@ public abstract class Job<JobT extends Job<JobT, RunT>, RunT extends Run<JobT, R /** * List of {@link UserProperty}s configured for this project. + * According to new implementation {@link ParametersDefinitionProperty} were moved from this collection. So, this + * field was left protected for backward compatibility. Don't use this field directly for adding or removing + * values. Use {@link #addProperty(JobProperty)}, {@link #removeProperty(JobProperty)}, + * {@link #removeProperty(Class)} instead. + * + * @since 2.2.0 */ protected CopyOnWriteList<JobProperty<? super JobT>> properties = new CopyOnWriteList<JobProperty<? super JobT>>(); @@ -407,6 +415,7 @@ public abstract class Job<JobT extends Job<JobT, RunT>, RunT extends Run<JobT, R property.setJob(this); } convertLogRotatorProperty(); + convertJobProperty(); } void convertLogRotatorProperty() { @@ -416,6 +425,12 @@ public abstract class Job<JobT extends Job<JobT, RunT>, RunT extends Run<JobT, R } } + void convertJobProperty() { + if (null != properties && null == getProperty(PARAMETERS_DEFINITION_JOB_PROPERTY_PROPERTY_NAME)) { + setParameterDefinitionProperties(properties); + properties = null; + } + } /** * Initialize project properties if null. */ @@ -603,6 +618,22 @@ public abstract class Job<JobT extends Job<JobT, RunT>, RunT extends Run<JobT, R return true; } + public void setParameterDefinitionProperties(CopyOnWriteList<JobProperty<? super JobT>> properties) { + CopyOnWriteList parameterDefinitionProperties = new CopyOnWriteList(); + for (JobProperty property : properties) { + if (property instanceof ParametersDefinitionProperty) { + parameterDefinitionProperties.add(property); + } + } + CascadingUtil.setParameterDefinitionProperties(this, PARAMETERS_DEFINITION_JOB_PROPERTY_PROPERTY_NAME, + parameterDefinitionProperties); + } + + public CopyOnWriteList<ParametersDefinitionProperty> getParameterDefinitionProperties() { + return CascadingUtil.getCopyOnWriteListProjectProperty(this, PARAMETERS_DEFINITION_JOB_PROPERTY_PROPERTY_NAME) + .getValue(); + } + @Override protected SearchIndexBuilder makeSearchIndex() { return super.makeSearchIndex().add(new SearchIndex() { @@ -640,7 +671,16 @@ public abstract class Job<JobT extends Job<JobT, RunT>, RunT extends Run<JobT, R */ public void addProperty(JobProperty<? super JobT> jobProp) throws IOException { ((JobProperty) jobProp).setOwner(this); - properties.add(jobProp); + if (((JobProperty) jobProp) instanceof ParametersDefinitionProperty) { + CopyOnWriteList list = CascadingUtil.getCopyOnWriteListProjectProperty(this, + PARAMETERS_DEFINITION_JOB_PROPERTY_PROPERTY_NAME) + .getOriginalValue(); + if (null != list) { + list.add(jobProp); + } + } else { + properties.add(jobProp); + } save(); } @@ -650,22 +690,39 @@ public abstract class Job<JobT extends Job<JobT, RunT>, RunT extends Run<JobT, R * @since 1.279 */ public void removeProperty(JobProperty<? super JobT> jobProp) throws IOException { - properties.remove(jobProp); + if (((JobProperty) jobProp) instanceof ParametersDefinitionProperty) { + CopyOnWriteList list = CascadingUtil.getCopyOnWriteListProjectProperty(this, + PARAMETERS_DEFINITION_JOB_PROPERTY_PROPERTY_NAME) + .getOriginalValue(); + if (null != list) { + list.remove(jobProp); + } + } else { + properties.remove(jobProp); + } save(); } /** * Removes the property of the given type. * - * @return - * The property that was just removed. + * @return The property that was just removed. * @since 1.279 */ public <T extends JobProperty> T removeProperty(Class<T> clazz) throws IOException { - for (JobProperty<? super JobT> p : properties) { - if (clazz.isInstance(p)) { - removeProperty(p); - return clazz.cast(p); + CopyOnWriteList<JobProperty<? super JobT>> sourceProperties; + if (clazz.equals(ParametersDefinitionProperty.class)) { + sourceProperties = CascadingUtil.getCopyOnWriteListProjectProperty(this, + PARAMETERS_DEFINITION_JOB_PROPERTY_PROPERTY_NAME).getOriginalValue(); + } else { + sourceProperties = properties; + } + if (null != sourceProperties) { + for (JobProperty<? super JobT> p : sourceProperties) { + if (clazz.isInstance(p)) { + removeProperty(p); + return clazz.cast(p); + } } } return null; @@ -676,7 +733,7 @@ public abstract class Job<JobT extends Job<JobT, RunT>, RunT extends Run<JobT, R */ @SuppressWarnings("unchecked") public Map<JobPropertyDescriptor, JobProperty<? super JobT>> getProperties() { - return Descriptor.toMap((Iterable) properties); //TODO should we analyze properties from super psroject? + return Descriptor.toMap((Iterable) getAllProperties()); } /** @@ -685,7 +742,12 @@ public abstract class Job<JobT extends Job<JobT, RunT>, RunT extends Run<JobT, R */ @Exported(name = "property", inline = true) public List<JobProperty<? super JobT>> getAllProperties() { - return properties.getView(); + CopyOnWriteList<ParametersDefinitionProperty> definitionProperties = getParameterDefinitionProperties(); + List<JobProperty<? super JobT>> result = properties.getView(); + if (null != definitionProperties) { + result = Collections.unmodifiableList(ListUtils.union(result, definitionProperties.getView())); + } + return result; } /** @@ -693,9 +755,18 @@ public abstract class Job<JobT extends Job<JobT, RunT>, RunT extends Run<JobT, R * this job. */ public <T extends JobProperty> T getProperty(Class<T> clazz) { - for (JobProperty p : properties) { - if (clazz.isInstance(p)) { - return clazz.cast(p); + CopyOnWriteList<JobProperty<? super JobT>> sourceProperties; + if (clazz.equals(ParametersDefinitionProperty.class)) { + sourceProperties = CascadingUtil.getCopyOnWriteListProjectProperty(this, + PARAMETERS_DEFINITION_JOB_PROPERTY_PROPERTY_NAME).getOriginalValue(); + } else { + sourceProperties = properties; + } + if (null != sourceProperties) { + for (JobProperty p : sourceProperties) { + if (clazz.isInstance(p)) { + return clazz.cast(p); + } } } return null; @@ -706,9 +777,8 @@ public abstract class Job<JobT extends Job<JobT, RunT>, RunT extends Run<JobT, R */ public Collection<?> getOverrides() { List<Object> r = new ArrayList<Object>(); - for (JobProperty<? super JobT> p : properties) { + for (JobProperty<? super JobT> p : getAllProperties()) r.addAll(p.getJobOverrides()); - } return r; } @@ -1251,29 +1321,7 @@ public abstract class Job<JobT extends Job<JobT, RunT>, RunT extends Run<JobT, R public synchronized void doConfigSubmit(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException, FormException { checkPermission(CONFIGURE); - - description = req.getParameter("description"); - - keepDependencies = req.getParameter("keepDependencies") != null; - try { - properties.clear(); - - JSONObject json = req.getSubmittedForm(); - setLogRotator(req.getParameter("logrotate") != null ? LogRotator.DESCRIPTOR - .newInstance(req, json.getJSONObject("logrotate")) : null); - - int i = 0; - for (JobPropertyDescriptor d : JobPropertyDescriptor.getPropertyDescriptors(Job.this.getClass())) { - String name = "jobProperty" + (i++); - JSONObject config = json.getJSONObject(name); - JobProperty prop = d.newInstance(req, config); - if (prop != null) { - prop.setOwner(this); - properties.add(prop); - } - } - setAllowSave(false); submit(req, rsp); setAllowSave(true); @@ -1305,8 +1353,33 @@ public abstract class Job<JobT extends Job<JobT, RunT>, RunT extends Run<JobT, R * Derived class can override this to perform additional config submission * work. */ - protected void submit(StaplerRequest req, StaplerResponse rsp) - throws IOException, ServletException, FormException { + protected void submit(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException, FormException { + JSONObject json = req.getSubmittedForm(); + description = req.getParameter("description"); + keepDependencies = req.getParameter("keepDependencies") != null; + properties.clear(); + CopyOnWriteList parameterDefinitionProperties = new CopyOnWriteList(); + int i = 0; + for (JobPropertyDescriptor d : JobPropertyDescriptor + .getPropertyDescriptors(Job.this.getClass())) { + String name = "jobProperty" + (i++); + JSONObject config = json.getJSONObject(name); + JobProperty prop = d.newInstance(req, config); + + if (prop instanceof ParametersDefinitionProperty) { + prop.setOwner(this); + parameterDefinitionProperties.add(prop); + } else if (null != prop) { + prop.setOwner(this); + properties.add(prop); + } + } + setParameterDefinitionProperties(parameterDefinitionProperties); + LogRotator logRotator = null; + if (null != req.getParameter("logrotate")) { + logRotator = LogRotator.DESCRIPTOR.newInstance(req, json.getJSONObject("logrotate")); + } + setLogRotator(logRotator); } /** diff --git a/hudson-core/src/main/java/hudson/model/ParametersDefinitionProperty.java b/hudson-core/src/main/java/hudson/model/ParametersDefinitionProperty.java index 46e6002..1a5f43c 100644 --- a/hudson-core/src/main/java/hudson/model/ParametersDefinitionProperty.java +++ b/hudson-core/src/main/java/hudson/model/ParametersDefinitionProperty.java @@ -56,7 +56,17 @@ public class ParametersDefinitionProperty extends JobProperty<AbstractProject<?, public ParametersDefinitionProperty(ParameterDefinition... parameterDefinitions) { this.parameterDefinitions = Arrays.asList(parameterDefinitions); } - + + /** + * This method is called for cascading update of owners. + * + * @param owner new owner. + * @since 2.2.0 + */ + public void setOwner(AbstractProject<?, ?> owner) { + super.setOwner(owner); + } + public AbstractProject<?,?> getOwner() { return owner; } @@ -104,7 +114,7 @@ public class ParametersDefinitionProperty extends JobProperty<AbstractProject<?, } List<ParameterValue> values = new ArrayList<ParameterValue>(); - + JSONObject formData = req.getSubmittedForm(); JSONArray a = JSONArray.fromObject(formData.get("parameter")); @@ -173,7 +183,7 @@ public class ParametersDefinitionProperty extends JobProperty<AbstractProject<?, if (parameterized.isNullObject()) { return null; } - + List<ParameterDefinition> parameterDefinitions = Descriptor.newInstancesFromHeteroList( req, parameterized, "parameter", ParameterDefinition.all()); if(parameterDefinitions.isEmpty()) @@ -199,4 +209,27 @@ public class ParametersDefinitionProperty extends JobProperty<AbstractProject<?, public String getUrlName() { return null; } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + ParametersDefinitionProperty that = (ParametersDefinitionProperty) o; + if (parameterDefinitions != null ? !this.parameterDefinitions.equals(that.parameterDefinitions) + : that.parameterDefinitions != null) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + return parameterDefinitions != null ? parameterDefinitions.hashCode() : 0; + } } diff --git a/hudson-core/src/main/java/hudson/util/CascadingUtil.java b/hudson-core/src/main/java/hudson/util/CascadingUtil.java index 467988d..c2df54d 100644 --- a/hudson-core/src/main/java/hudson/util/CascadingUtil.java +++ b/hudson-core/src/main/java/hudson/util/CascadingUtil.java @@ -15,11 +15,14 @@ package hudson.util; import hudson.Functions; +import hudson.model.AbstractProject; import hudson.model.Describable; import hudson.model.Descriptor; import hudson.model.Hudson; import hudson.model.Item; import hudson.model.Job; +import hudson.model.ParameterDefinition; +import hudson.model.ParametersDefinitionProperty; import hudson.triggers.Trigger; import hudson.triggers.TriggerDescriptor; import java.lang.reflect.InvocationTargetException; @@ -35,6 +38,7 @@ import org.eclipse.hudson.api.model.IProjectProperty; import org.eclipse.hudson.api.model.project.property.AxisListProjectProperty; import org.eclipse.hudson.api.model.project.property.BaseProjectProperty; import org.eclipse.hudson.api.model.project.property.BooleanProjectProperty; +import org.eclipse.hudson.api.model.project.property.CopyOnWriteListProjectProperty; import org.eclipse.hudson.api.model.project.property.DescribableListProjectProperty; import org.eclipse.hudson.api.model.project.property.ExternalProjectProperty; import org.eclipse.hudson.api.model.project.property.IntegerProjectProperty; @@ -106,6 +110,19 @@ public class CascadingUtil { } /** + * Returns CopyOnWriteListProjectProperty by specified key. If property doesn't exists, + * it will be initialized and added to current job. + * + * @param currentJob job that should be analyzed. + * @param key key. + * @return {@link org.eclipse.hudson.api.model.project.property.CopyOnWriteListProjectProperty} instance. + * @throws NullPointerException if currentJob is null. + */ + public static CopyOnWriteListProjectProperty getCopyOnWriteListProjectProperty(Job currentJob, String key) { + return getProjectProperty(currentJob, key, CopyOnWriteListProjectProperty.class); + } + + /** * Returns ResultProjectProperty by specified key. If property doesn't exists, it will be initialized and added to * current job. * @@ -413,7 +430,7 @@ public class CascadingUtil { */ @SuppressWarnings("unchecked") public static void setChildrenTrigger(Job job, TriggerDescriptor descriptor, String key, StaplerRequest req, - JSONObject json) throws Descriptor.FormException { + JSONObject json) throws Descriptor.FormException { TriggerProjectProperty property = CascadingUtil.getTriggerProjectProperty(job, key); if (property.getValue() != null) { property.getValue().stop(); @@ -437,4 +454,45 @@ public class CascadingUtil { } } } + + /** + * Sets parameterDefinitionProperties for current job. This method is recursively executed for cascading children + * for setting valid {@link ParametersDefinitionProperty#owner} value. + * + * @param job job. + * @param key parameter key, + * @param parameterDefinitionProperties new properties to set. + */ + @SuppressWarnings("unchecked") + public static void setParameterDefinitionProperties(Job job, + String key, + CopyOnWriteList<ParametersDefinitionProperty> parameterDefinitionProperties) { + CopyOnWriteListProjectProperty projectProperty = getCopyOnWriteListProjectProperty(job, key); + CopyOnWriteList<ParametersDefinitionProperty> pdProperties + = new CopyOnWriteList<ParametersDefinitionProperty>(); + //Create new instance for each parameter in order to set owner and use in cascading children. + for (ParametersDefinitionProperty pdp : parameterDefinitionProperties) { + ParametersDefinitionProperty copiedDefinitionProperty = new ParametersDefinitionProperty( + new ArrayList<ParameterDefinition>(pdp.getParameterDefinitions())); + copiedDefinitionProperty.setOwner((AbstractProject) job); + pdProperties.add(copiedDefinitionProperty); + } + projectProperty.setValue(pdProperties); + Set<String> cascadingChildrenNames = job.getCascadingChildrenNames(); + //Iterate through cascading children and recursively update property for each child. + for (String childName : cascadingChildrenNames) { + AbstractProject childJob = (AbstractProject) Hudson.getInstance().getItem(childName); + //Check only direct children in order to avoid deep checking for properties overridden properties. + if (StringUtils.equals(job.getName(), childJob.getCascadingProjectName())) { + CopyOnWriteListProjectProperty childProperty = getCopyOnWriteListProjectProperty(childJob, key); + //If child value is equal to parent - mark this value as unmodified. + if (!projectProperty.allowOverrideValue(childProperty.getValue(), pdProperties)) { + projectProperty.setOverridden(false); + } else if (!childProperty.isOverridden()) { + //If child property was not overridden, update this property and cascading children if any. + setParameterDefinitionProperties(childJob, key, parameterDefinitionProperties); + } + } + } + } } diff --git a/hudson-core/src/main/java/org/eclipse/hudson/api/model/IProjectProperty.java b/hudson-core/src/main/java/org/eclipse/hudson/api/model/IProjectProperty.java index 4d62292..4761346 100644 --- a/hudson-core/src/main/java/org/eclipse/hudson/api/model/IProjectProperty.java +++ b/hudson-core/src/main/java/org/eclipse/hudson/api/model/IProjectProperty.java @@ -34,6 +34,11 @@ public interface IProjectProperty<T> extends Serializable { void setKey(String key); /** + * @return property key. + */ + String getKey(); + + /** * Sets the job, which is owner of current property. * * @param job {@link IJob} diff --git a/hudson-core/src/main/java/org/eclipse/hudson/api/model/project/property/BaseProjectProperty.java b/hudson-core/src/main/java/org/eclipse/hudson/api/model/project/property/BaseProjectProperty.java index a37f49a..64b1ba1 100644 --- a/hudson-core/src/main/java/org/eclipse/hudson/api/model/project/property/BaseProjectProperty.java +++ b/hudson-core/src/main/java/org/eclipse/hudson/api/model/project/property/BaseProjectProperty.java @@ -55,6 +55,13 @@ public class BaseProjectProperty<T> implements IProjectProperty<T> { /** * {@inheritDoc} */ + public String getKey() { + return propertyKey; + } + + /** + * {@inheritDoc} + */ public void setJob(IJob job) { if (null == job) { throw new IllegalArgumentException(INVALID_JOB_EXCEPTION); @@ -81,7 +88,7 @@ public class BaseProjectProperty<T> implements IProjectProperty<T> { */ @SuppressWarnings("unchecked") public T getCascadingValue() { - if (null == propertyKey) { + if (null == getKey()) { throw new IllegalArgumentException(INVALID_PROPERTY_KEY_EXCEPTION); } return getJob().hasCascadingProject() ? @@ -126,7 +133,7 @@ public class BaseProjectProperty<T> implements IProjectProperty<T> { */ @SuppressWarnings("unchecked") public void setValue(T value) { - if (null == propertyKey) { + if (null == getKey()) { throw new IllegalArgumentException(INVALID_PROPERTY_KEY_EXCEPTION); } value = prepareValue(value); diff --git a/hudson-core/src/main/java/org/eclipse/hudson/api/model/project/property/CopyOnWriteListProjectProperty.java b/hudson-core/src/main/java/org/eclipse/hudson/api/model/project/property/CopyOnWriteListProjectProperty.java new file mode 100644 index 0000000..1c3c5ac --- a/dev/null +++ b/hudson-core/src/main/java/org/eclipse/hudson/api/model/project/property/CopyOnWriteListProjectProperty.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * + * Copyright (c) 2011 Oracle Corporation. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * + * Nikita Levyankov + * + *******************************************************************************/ +package org.eclipse.hudson.api.model.project.property; + +import hudson.util.CopyOnWriteList; +import org.eclipse.hudson.api.model.IJob; + +/** + * Project property for CopyOnWriteList + * <p/> + * Date: 11/1/11 + * + * @author Nikita Levyankov + */ +public class CopyOnWriteListProjectProperty extends BaseProjectProperty<CopyOnWriteList> { + + public CopyOnWriteListProjectProperty(IJob job) { + super(job); + } + + @Override + public CopyOnWriteList getDefaultValue() { + CopyOnWriteList result = new CopyOnWriteList(); + setOriginalValue(result, false); + return result; + } + + @Override + protected boolean returnOriginalValue() { + return isOverridden() || (null != getOriginalValue() && !getOriginalValue().isEmpty()); + } + + @Override + public CopyOnWriteList getOriginalValue() { + CopyOnWriteList result = super.getOriginalValue(); + return null != result ? result : getDefaultValue(); + } + + @Override + protected void clearOriginalValue(CopyOnWriteList originalValue) { + setOriginalValue(originalValue, false); + } +} diff --git a/hudson-core/src/main/resources/hudson/model/ParametersDefinitionProperty/config.jelly b/hudson-core/src/main/resources/hudson/model/ParametersDefinitionProperty/config.jelly index cad4808..2a2da3e 100644 --- a/hudson-core/src/main/resources/hudson/model/ParametersDefinitionProperty/config.jelly +++ b/hudson-core/src/main/resources/hudson/model/ParametersDefinitionProperty/config.jelly @@ -1,6 +1,6 @@ <!-- ************************************************************************** # -# Copyright (c) 2004-2009 Oracle Corporation. +# Copyright (c) 2004-2011 Oracle Corporation. # # All rights reserved. This program and the accompanying materials # are made available under the terms of the Eclipse Public License v1.0 @@ -9,7 +9,7 @@ # # Contributors: # -# Kohsuke Kawaguchi, Tom Huybrechts +# Kohsuke Kawaguchi, Tom Huybrechts, Nikita Levyankov # # #************************************************************************** --> @@ -18,8 +18,11 @@ <j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt" xmlns:p="/lib/hudson/project"> + <j:set var="instancesProperty" value="${cu.getCopyOnWriteListProjectProperty(it, it.PARAMETERS_DEFINITION_JOB_PROPERTY_PROPERTY_NAME)}"/> <f:optionalBlock name="parameterized" title="${%This build is parameterized}" - checked="${instance!=null}" help="/help/project-config/parameterized-build.html"> + isPropertyOverridden="${instancesProperty.isOverridden()}" + resetUrl="${jobUrl}/resetProjectProperty?propertyName=${instancesProperty.key}" + checked="${instance!=null}" help="/help/project-config/parameterized-build.html"> <f:nested> <f:hetero-list name="parameter" hasHeader="true" descriptors="${h.getParameterDescriptors()}" items="${instance.parameterDefinitions}" |

