| author | akozak | 2011-11-23 10:01:09 (EST) |
|---|---|---|
| committer | Winston Prakash | 2011-12-01 20:47:12 (EST) |
| commit | 4e01a2ecd322a88d81aefffb8faafc6f367addab (patch) (side-by-side diff) | |
| tree | 70c54721207f3c0f4cf9ba7b12fc274fe73c1161 | |
| parent | bdf469bfe5cf37551fe567c4af2dbb3916b967c5 (diff) | |
| download | org.eclipse.hudson.core-4e01a2ecd322a88d81aefffb8faafc6f367addab.zip org.eclipse.hudson.core-4e01a2ecd322a88d81aefffb8faafc6f367addab.tar.gz org.eclipse.hudson.core-4e01a2ecd322a88d81aefffb8faafc6f367addab.tar.bz2 | |
Introduce isModified field in order to trigger Property changes from UI. Implement workaround for equals methods absence
Signed-off-by: Winston Prakash <winston.prakash@gmail.com>
11 files changed, 260 insertions, 59 deletions
diff --git a/hudson-core/src/main/java/hudson/matrix/MatrixProject.java b/hudson-core/src/main/java/hudson/matrix/MatrixProject.java index 2c32527..47b66cb 100644 --- a/hudson-core/src/main/java/hudson/matrix/MatrixProject.java +++ b/hudson-core/src/main/java/hudson/matrix/MatrixProject.java @@ -50,7 +50,12 @@ import hudson.util.FormValidation; import hudson.util.FormValidation.Kind; import net.sf.json.JSONObject; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; import org.eclipse.hudson.api.matrix.IMatrixProject; +import org.eclipse.hudson.api.model.project.property.AxisListProjectProperty; +import org.eclipse.hudson.api.model.project.property.BooleanProjectProperty; +import org.eclipse.hudson.api.model.project.property.ResultProjectProperty; +import org.eclipse.hudson.api.model.project.property.StringProjectProperty; import org.kohsuke.stapler.HttpResponse; import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.StaplerResponse; @@ -171,7 +176,11 @@ public class MatrixProject extends BaseBuildableProject<MatrixProject, MatrixBui * @inheritDoc */ public void setAxes(AxisList axes) throws IOException { - getAxesListProjectProperty(AXES_PROPERTY_NAME).setValue(axes); + setAxes(axes, true); + } + + protected void setAxes(AxisList axes, boolean forceModify) throws IOException { + setProjectPropertyValue(AXES_PROPERTY_NAME, AxisListProjectProperty.class, axes, forceModify); rebuildConfigurations(); save(); } @@ -187,7 +196,7 @@ public class MatrixProject extends BaseBuildableProject<MatrixProject, MatrixBui * @inheritDoc */ public void setRunSequentially(boolean runSequentially) throws IOException { - getBooleanProperty(RUN_SEQUENTIALLY_PROPERTY_NAME).setValue(runSequentially); + setProjectPropertyValue(RUN_SEQUENTIALLY_PROPERTY_NAME, BooleanProjectProperty.class, runSequentially, true); save(); } @@ -202,7 +211,12 @@ public class MatrixProject extends BaseBuildableProject<MatrixProject, MatrixBui * @inheritDoc */ public void setCombinationFilter(String combinationFilter) throws IOException { - getStringProperty(COMBINATION_FILTER_PROPERTY_NAME).setValue(combinationFilter); + setCombinationFilter(combinationFilter, true); + } + + protected void setCombinationFilter(String combinationFilter, boolean forceModify) throws IOException { + setProjectPropertyValue(COMBINATION_FILTER_PROPERTY_NAME, StringProjectProperty.class, combinationFilter, + forceModify); rebuildConfigurations(); save(); } @@ -218,7 +232,12 @@ public class MatrixProject extends BaseBuildableProject<MatrixProject, MatrixBui * @inheritDoc */ public void setTouchStoneCombinationFilter(String touchStoneCombinationFilter) { - getStringProperty(TOUCH_STONE_COMBINATION_FILTER_PROPERTY_NAME).setValue(touchStoneCombinationFilter); + setTouchStoneCombinationFilter(touchStoneCombinationFilter, true); + } + + protected void setTouchStoneCombinationFilter(String touchStoneCombinationFilter, boolean forceModify) { + setProjectPropertyValue(TOUCH_STONE_COMBINATION_FILTER_PROPERTY_NAME, StringProjectProperty.class, + touchStoneCombinationFilter, forceModify); } /** @@ -232,7 +251,12 @@ public class MatrixProject extends BaseBuildableProject<MatrixProject, MatrixBui * @inheritDoc */ public void setTouchStoneResultCondition(Result touchStoneResultCondition) { - getResultProperty(TOUCH_STONE_RESULT_CONDITION_PROPERTY_NAME).setValue(touchStoneResultCondition); + setTouchStoneResultCondition(touchStoneResultCondition, true); + } + + protected void setTouchStoneResultCondition(Result touchStoneResultCondition, boolean forceModify) { + setProjectPropertyValue(TOUCH_STONE_RESULT_CONDITION_PROPERTY_NAME, ResultProjectProperty.class, + touchStoneResultCondition, forceModify); } /** @@ -246,7 +270,12 @@ public class MatrixProject extends BaseBuildableProject<MatrixProject, MatrixBui * @inheritDoc */ public void setCustomWorkspace(String customWorkspace) throws IOException { - getStringProperty(CUSTOM_WORKSPACE_PROPERTY_NAME).setValue(customWorkspace); + setCustomWorkspace(customWorkspace, true); + } + + protected void setCustomWorkspace(String customWorkspace, boolean forceModify) throws IOException { + setProjectPropertyValue(CUSTOM_WORKSPACE_PROPERTY_NAME, StringProjectProperty.class, customWorkspace, + forceModify); } @Override @@ -572,20 +601,23 @@ public class MatrixProject extends BaseBuildableProject<MatrixProject, MatrixBui COMBINATION_FILTER_PROPERTY_NAME)) : null); if (req.getParameter(HAS_TOUCH_STONE_COMBINATION_FILTER_PARAM)!=null) { - setTouchStoneCombinationFilter(Util.nullify(req.getParameter(TOUCH_STONE_COMBINATION_FILTER_PARAM))); - setTouchStoneResultCondition(Result.fromString(req.getParameter(TOUCH_STONE_RESULT_CONDITION_PARAM))); + setTouchStoneCombinationFilter( + StringUtils.trimToNull(req.getParameter(TOUCH_STONE_COMBINATION_FILTER_PARAM)), false); + setTouchStoneResultCondition( + Result.fromString(req.getParameter(TOUCH_STONE_RESULT_CONDITION_PARAM)), false); } else { - setTouchStoneCombinationFilter(null); + setTouchStoneCombinationFilter(null, false); } setCustomWorkspace( - req.hasParameter(CUSTOM_WORKSPACE_PARAM) ? req.getParameter(CUSTOM_WORKSPACE_DIRECTORY_PARAM) : null); + req.hasParameter(CUSTOM_WORKSPACE_PARAM) ? req.getParameter(CUSTOM_WORKSPACE_DIRECTORY_PARAM) : null, + false); // parse system axes DescribableList<Axis, AxisDescriptor> newAxes = DescribableListUtil.buildFromHetero(this, req, json, "axis", Axis.all()); checkAxisNames(newAxes); - setAxes(new AxisList(newAxes.toList())); + setAxes(new AxisList(newAxes.toList()), false); setRunSequentially(json.has(RUN_SEQUENTIALLY_PROPERTY_NAME)); diff --git a/hudson-core/src/main/java/hudson/model/AbstractProject.java b/hudson-core/src/main/java/hudson/model/AbstractProject.java index 0cc428c..8401848 100644 --- a/hudson-core/src/main/java/hudson/model/AbstractProject.java +++ b/hudson-core/src/main/java/hudson/model/AbstractProject.java @@ -39,6 +39,7 @@ import hudson.model.RunMap.Constructor; import hudson.model.labels.LabelAtom; import hudson.model.labels.LabelExpression; import org.eclipse.hudson.api.model.IProjectProperty; +import org.eclipse.hudson.api.model.project.property.BooleanProjectProperty; import org.eclipse.hudson.api.model.project.property.IntegerProjectProperty; import hudson.model.queue.CauseOfBlockage; import hudson.model.queue.SubTask; @@ -95,6 +96,7 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.math.NumberUtils; import org.eclipse.hudson.api.model.IAbstractProject; import org.eclipse.hudson.api.model.project.property.SCMProjectProperty; +import org.eclipse.hudson.api.model.project.property.StringProjectProperty; import org.kohsuke.args4j.Argument; import org.kohsuke.args4j.CmdLineException; import org.kohsuke.stapler.ForwardToView; @@ -344,56 +346,57 @@ public abstract class AbstractProject<P extends AbstractProject<P,R>,R extends A } void convertBlockBuildWhenUpstreamBuildingProperty() throws IOException { - if (null == getProperty(BLOCK_BUILD_WHEN_UPSTREAM_BUILDING_PROPERTY_NAME)) { + if (blockBuildWhenUpstreamBuilding && null == getProperty(BLOCK_BUILD_WHEN_UPSTREAM_BUILDING_PROPERTY_NAME)) { setBlockBuildWhenUpstreamBuilding(blockBuildWhenUpstreamBuilding); blockBuildWhenUpstreamBuilding = false; } } void convertBlockBuildWhenDownstreamBuildingProperty() throws IOException { - if (null == getProperty(BLOCK_BUILD_WHEN_DOWNSTREAM_BUILDING_PROPERTY_NAME)) { + if (blockBuildWhenDownstreamBuilding + && null == getProperty(BLOCK_BUILD_WHEN_DOWNSTREAM_BUILDING_PROPERTY_NAME)) { setBlockBuildWhenDownstreamBuilding(blockBuildWhenDownstreamBuilding); blockBuildWhenDownstreamBuilding = false; } } void convertConcurrentBuildProperty() throws IOException { - if (null == getProperty(CONCURRENT_BUILD_PROPERTY_NAME)) { + if (concurrentBuild && null == getProperty(CONCURRENT_BUILD_PROPERTY_NAME)) { setConcurrentBuild(concurrentBuild); concurrentBuild = false; } } void convertCleanWorkspaceRequiredProperty() throws IOException { - if (null == getProperty(CLEAN_WORKSPACE_REQUIRED_PROPERTY_NAME)) { + if (cleanWorkspaceRequired && null == getProperty(CLEAN_WORKSPACE_REQUIRED_PROPERTY_NAME)) { setCleanWorkspaceRequired(cleanWorkspaceRequired); cleanWorkspaceRequired = false; } } void convertQuietPeriodProperty() throws IOException { - if (null == getProperty(QUIET_PERIOD_PROPERTY_NAME)) { + if (null != quietPeriod && null == getProperty(QUIET_PERIOD_PROPERTY_NAME)) { setQuietPeriod(quietPeriod); quietPeriod = null; } } void convertScmCheckoutRetryCountProperty() throws IOException { - if (null == getProperty(SCM_CHECKOUT_RETRY_COUNT_PROPERTY_NAME)) { + if (null != scmCheckoutRetryCount && null == getProperty(SCM_CHECKOUT_RETRY_COUNT_PROPERTY_NAME)) { setScmCheckoutRetryCount(scmCheckoutRetryCount); scmCheckoutRetryCount = null; } } void convertJDKProperty() throws IOException { - if (null == getProperty(JDK_PROPERTY_NAME)) { + if (null != jdk && null == getProperty(JDK_PROPERTY_NAME)) { setJDK(jdk); jdk = null; } } void convertScmProperty() throws IOException { - if (null == getProperty(SCM_PROPERTY_NAME)) { + if (null != scm && null == getProperty(SCM_PROPERTY_NAME)) { setScm(scm); scm = null; } @@ -422,7 +425,11 @@ public abstract class AbstractProject<P extends AbstractProject<P,R>,R extends A return Hudson.CONCURRENT_BUILD && getBooleanProperty(CONCURRENT_BUILD_PROPERTY_NAME).getValue(); } public void setConcurrentBuild(boolean b) throws IOException { - getBooleanProperty(CONCURRENT_BUILD_PROPERTY_NAME).setValue(b); + setConcurrentBuild(b, true); + } + + public void setConcurrentBuild(boolean b, boolean forceModify) throws IOException { + setProjectPropertyValue(CONCURRENT_BUILD_PROPERTY_NAME, BooleanProjectProperty.class, b, forceModify); save(); } @@ -431,7 +438,12 @@ public abstract class AbstractProject<P extends AbstractProject<P,R>,R extends A } public void setCleanWorkspaceRequired(boolean cleanWorkspaceRequired) { - getBooleanProperty(CLEAN_WORKSPACE_REQUIRED_PROPERTY_NAME).setValue(cleanWorkspaceRequired); + setCleanWorkspaceRequired(cleanWorkspaceRequired, true); + } + + public void setCleanWorkspaceRequired(boolean cleanWorkspaceRequired, boolean forceModify) { + setProjectPropertyValue(CLEAN_WORKSPACE_REQUIRED_PROPERTY_NAME, BooleanProjectProperty.class, + cleanWorkspaceRequired, forceModify); } /** * If this project is configured to be always built on this node, @@ -643,7 +655,11 @@ public abstract class AbstractProject<P extends AbstractProject<P,R>,R extends A * @throws IOException if any. */ public void setQuietPeriod(Integer seconds) throws IOException { - getIntegerProperty(QUIET_PERIOD_PROPERTY_NAME).setValue(seconds); + setQuietPeriod(seconds, true); + } + + protected void setQuietPeriod(Integer seconds, boolean forceModify) throws IOException { + setProjectPropertyValue(QUIET_PERIOD_PROPERTY_NAME, IntegerProjectProperty.class, seconds, forceModify); save(); } @@ -654,8 +670,14 @@ public abstract class AbstractProject<P extends AbstractProject<P,R>,R extends A } public void setScmCheckoutRetryCount(Integer retryCount) { - getIntegerProperty(SCM_CHECKOUT_RETRY_COUNT_PROPERTY_NAME).setValue(retryCount); + setScmCheckoutRetryCount(retryCount, true); } + + public void setScmCheckoutRetryCount(Integer retryCount, boolean forceModify) { + setProjectPropertyValue(SCM_CHECKOUT_RETRY_COUNT_PROPERTY_NAME, IntegerProjectProperty.class, retryCount, + forceModify); + } + /** * Sets scmCheckoutRetryCount, Uses {@link NumberUtils#isNumber(String)} for checking retryCount param. * If it is not valid number, null will be set. @@ -664,11 +686,15 @@ public abstract class AbstractProject<P extends AbstractProject<P,R>,R extends A * @throws IOException if any. */ protected void setScmCheckoutRetryCount(String scmCheckoutRetryCount) throws IOException { + setScmCheckoutRetryCount(scmCheckoutRetryCount, true); + } + + protected void setScmCheckoutRetryCount(String scmCheckoutRetryCount, boolean forceModify) throws IOException { Integer retryCount = null; if (NumberUtils.isNumber(scmCheckoutRetryCount)) { retryCount = NumberUtils.createInteger(scmCheckoutRetryCount); } - setScmCheckoutRetryCount(retryCount); + setScmCheckoutRetryCount(retryCount, forceModify); } /** @@ -689,13 +715,16 @@ public abstract class AbstractProject<P extends AbstractProject<P,R>,R extends A * @throws IOException if any. */ protected void setQuietPeriod(String seconds) throws IOException { + setQuietPeriod(seconds, true); + } + + protected void setQuietPeriod(String seconds, boolean forceModify) throws IOException { Integer period = null; if (NumberUtils.isNumber(seconds)) { period = NumberUtils.createInteger(seconds); } - setQuietPeriod(period); + setQuietPeriod(period, forceModify); } - /** * Checks whether scmRetryCount is configured * @@ -724,7 +753,12 @@ public abstract class AbstractProject<P extends AbstractProject<P,R>,R extends A } public void setBlockBuildWhenDownstreamBuilding(boolean b) throws IOException { - getBooleanProperty(BLOCK_BUILD_WHEN_DOWNSTREAM_BUILDING_PROPERTY_NAME).setValue(b); + setBlockBuildWhenDownstreamBuilding(b, true); + } + + public void setBlockBuildWhenDownstreamBuilding(boolean b, boolean forceModify) throws IOException { + setProjectPropertyValue(BLOCK_BUILD_WHEN_DOWNSTREAM_BUILDING_PROPERTY_NAME, + BooleanProjectProperty.class, b, forceModify); save(); } @@ -733,7 +767,12 @@ public abstract class AbstractProject<P extends AbstractProject<P,R>,R extends A } public void setBlockBuildWhenUpstreamBuilding(boolean b) throws IOException { - getBooleanProperty(BLOCK_BUILD_WHEN_UPSTREAM_BUILDING_PROPERTY_NAME).setValue(b); + setBlockBuildWhenUpstreamBuilding(b, true); + } + + public void setBlockBuildWhenUpstreamBuilding(boolean b, boolean forceModify) throws IOException { + setProjectPropertyValue(BLOCK_BUILD_WHEN_UPSTREAM_BUILDING_PROPERTY_NAME, + BooleanProjectProperty.class, b, forceModify); save(); } @@ -1078,7 +1117,11 @@ public abstract class AbstractProject<P extends AbstractProject<P,R>,R extends A } public void setJDK(String jdk) { - getStringProperty(JDK_PROPERTY_NAME).setValue(jdk); + setJDK(jdk, true); + } + + public void setJDK(String jdk, boolean forceModify) { + setProjectPropertyValue(JDK_PROPERTY_NAME, StringProjectProperty.class, jdk, forceModify); } public BuildAuthorizationToken getAuthToken() { @@ -1570,7 +1613,11 @@ public abstract class AbstractProject<P extends AbstractProject<P,R>,R extends A @SuppressWarnings("unchecked") public void setScm(SCM scm) throws IOException { - getProperty(SCM_PROPERTY_NAME, SCMProjectProperty.class).setValue(scm); + setScm(scm, true); + } + + public void setScm(SCM scm, boolean forceModify) throws IOException { + setProjectPropertyValue(SCM_PROPERTY_NAME, SCMProjectProperty.class, scm, forceModify); //save(); } @@ -1854,12 +1901,13 @@ public abstract class AbstractProject<P extends AbstractProject<P,R>,R extends A makeDisabled(null != req.getParameter("disable")); setCascadingProjectName(StringUtils.trimToNull(req.getParameter("cascadingProjectName"))); - setJDK(req.getParameter("jdk")); - setQuietPeriod(null != req.getParameter("hasCustomQuietPeriod") ? req.getParameter("quiet_period") : null); + setJDK(req.getParameter("jdk"), false); + setQuietPeriod(null != req.getParameter("hasCustomQuietPeriod") ? req.getParameter("quiet_period") : null, + false); setScmCheckoutRetryCount(null != req.getParameter("hasCustomScmCheckoutRetryCount") - ? req.getParameter("scmCheckoutRetryCount") : null); - setBlockBuildWhenDownstreamBuilding(null != req.getParameter("blockBuildWhenDownstreamBuilding")); - setBlockBuildWhenUpstreamBuilding(null != req.getParameter("blockBuildWhenUpstreamBuilding")); + ? req.getParameter("scmCheckoutRetryCount") : null, false); + setBlockBuildWhenDownstreamBuilding(null != req.getParameter("blockBuildWhenDownstreamBuilding"), false); + setBlockBuildWhenUpstreamBuilding(null != req.getParameter("blockBuildWhenUpstreamBuilding"), false); if (req.getParameter("hasSlaveAffinity") != null) { // New logic for handling whether this choice came from the dropdown or textfield. @@ -1876,15 +1924,15 @@ public abstract class AbstractProject<P extends AbstractProject<P,R>,R extends A } - setCleanWorkspaceRequired(null != req.getParameter("cleanWorkspaceRequired")); + setCleanWorkspaceRequired(null != req.getParameter("cleanWorkspaceRequired"), false); canRoam = assignedNode==null; - setConcurrentBuild(req.getSubmittedForm().has("concurrentBuild")); + setConcurrentBuild(req.getSubmittedForm().has("concurrentBuild"), false); authToken = BuildAuthorizationToken.create(req); - setScm(SCMS.parseSCM(req,this)); + setScm(SCMS.parseSCM(req,this), false); for (Trigger t : triggers) t.stop(); diff --git a/hudson-core/src/main/java/hudson/model/BaseBuildableProject.java b/hudson-core/src/main/java/hudson/model/BaseBuildableProject.java index 4d3ec47..109dcd3 100644 --- a/hudson-core/src/main/java/hudson/model/BaseBuildableProject.java +++ b/hudson-core/src/main/java/hudson/model/BaseBuildableProject.java @@ -214,7 +214,7 @@ public abstract class BaseBuildableProject<P extends BaseBuildableProject<P,B>,B * @param req {@link StaplerRequest} * @param json {@link JSONObject} * @param descriptors list of descriptors. - * @throws hudson.model.Descriptor.FormException + * @throws hudson.model.Descriptor.FormException if any. */ @SuppressWarnings("unchecked") protected void buildPublishers( StaplerRequest req, JSONObject json, List<Descriptor<Publisher>> descriptors) throws FormException{ diff --git a/hudson-core/src/main/java/hudson/model/FreeStyleProject.java b/hudson-core/src/main/java/hudson/model/FreeStyleProject.java index 569b621..ee6084f 100644 --- a/hudson-core/src/main/java/hudson/model/FreeStyleProject.java +++ b/hudson-core/src/main/java/hudson/model/FreeStyleProject.java @@ -23,6 +23,7 @@ import java.io.IOException; import org.apache.commons.lang3.StringUtils; import org.eclipse.hudson.api.model.IFreeStyleProject; +import org.eclipse.hudson.api.model.project.property.StringProjectProperty; import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.StaplerResponse; @@ -87,7 +88,12 @@ public class FreeStyleProject extends Project<FreeStyleProject,FreeStyleBuild> i * @throws IOException if any. */ public void setCustomWorkspace(String customWorkspace) throws IOException { - getStringProperty(CUSTOM_WORKSPACE_PROPERTY_NAME).setValue(customWorkspace); + setCustomWorkspace(customWorkspace, true); + } + + protected void setCustomWorkspace(String customWorkspace, boolean forceModify) throws IOException { + setProjectPropertyValue(CUSTOM_WORKSPACE_PROPERTY_NAME, StringProjectProperty.class, customWorkspace, + forceModify); save(); } @@ -96,7 +102,7 @@ public class FreeStyleProject extends Project<FreeStyleProject,FreeStyleBuild> i throws IOException, ServletException, Descriptor.FormException { super.submit(req, rsp); setCustomWorkspace( - req.hasParameter("customWorkspace") ? req.getParameter("customWorkspace.directory") : null); + req.hasParameter("customWorkspace") ? req.getParameter("customWorkspace.directory") : null, false); } @Override diff --git a/hudson-core/src/main/java/hudson/model/Job.java b/hudson-core/src/main/java/hudson/model/Job.java index f1fec03..b51d30d 100644 --- a/hudson-core/src/main/java/hudson/model/Job.java +++ b/hudson-core/src/main/java/hudson/model/Job.java @@ -382,7 +382,7 @@ public abstract class Job<JobT extends Job<JobT, RunT>, RunT extends Run<JobT, R } void convertLogRotatorProperty() { - if (null == getProperty(LOG_ROTATOR_PROPERTY_NAME)) { + if (null != logRotator && null == getProperty(LOG_ROTATOR_PROPERTY_NAME)) { setLogRotator(logRotator); logRotator = null; } @@ -551,11 +551,36 @@ public abstract class Job<JobT extends Job<JobT, RunT>, RunT extends Run<JobT, R * * @param logRotator log rotator. */ - @SuppressWarnings("unchecked") public void setLogRotator(LogRotator logRotator) { - getProperty(LOG_ROTATOR_PROPERTY_NAME, LogRotatorProjectProperty.class).setValue(logRotator); + setLogRotator(logRotator, true); + } + + public void setLogRotator(LogRotator logRotator, boolean forceModify) { + setProjectPropertyValue(LOG_ROTATOR_PROPERTY_NAME, LogRotatorProjectProperty.class, logRotator, forceModify); + } + + /** + * Update project property with new value. ForceModify flag is taken into account. + * If property is null - it will be initialized and added to current job. + * + * @param key property key. + * @param clazz property class. + * @param value new value. + * @param forceModify true - to set property value even if it was not modified from UI. Basically this parameter is + * used for cascading functionality. + */ + @SuppressWarnings("unchecked") + protected void setProjectPropertyValue(String key, Class clazz, Object value, boolean forceModify) { + IProjectProperty property = getProperty(key, clazz); + if (null != property) { + if (forceModify) { + property.setModified(forceModify); + } + property.setValue(value); + } } + /** * Perform log rotation. */ @@ -1417,6 +1442,15 @@ public abstract class Job<JobT extends Job<JobT, RunT>, RunT extends Run<JobT, R setCascadingProjectName(projectName); } + public synchronized void doModifyCascadingProperty(@QueryParameter(fixEmpty = true) String propertyName) { + if (null != propertyName) { + IProjectProperty property = getProperty(propertyName); + if (null != property) { + property.setModified(true); + } + } + } + /** * Sets cascadingProject name. * @@ -1431,7 +1465,7 @@ public abstract class Job<JobT extends Job<JobT, RunT>, RunT extends Run<JobT, R this.cascadingProject = (JobT) Functions.getItemByName(Hudson.getInstance().getAllItems(this.getClass()), cascadingProjectName); for (IProjectProperty property : jobProperties.values()) { - property.setOverridden(property.getValue() != property.getCascadingValue()); + property.setOverridden(property.isModified()); } } } 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 a4f11b8..64bda37 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 @@ -42,6 +42,12 @@ public interface IProjectProperty<T> extends Serializable { /** * Sets property value. + * If property has cascading value, than modified flag will be checked. + * If property was modified and {@link #allowOverrideValue(Object, Object)} method returns true, that value will be + * set to current property.<br/> + * If property doesn't have cascading value, than value will be set directly. + * + * NOTE: use should call {@link #setModified(boolean)} method before setting cascading value. * * @param value value to set. */ @@ -101,4 +107,16 @@ public interface IProjectProperty<T> extends Serializable { * @param overridden true - mark property as overridden, false - otherwise. */ void setOverridden(boolean overridden); + + /** + * Method set modified state for current property. + * + * @param modified true if property was modified by user. + */ + void setModified(boolean modified); + + /** + * @return true if property was modified, false - otherwise. + */ + boolean isModified(); } 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 3c51644..0a506de 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 @@ -35,6 +35,7 @@ public class BaseProjectProperty<T> implements IProjectProperty<T> { private transient IJob job; private T originalValue; private boolean propertyOverridden; + private boolean modified; /** * Instantiate new property. @@ -79,6 +80,20 @@ public class BaseProjectProperty<T> implements IProjectProperty<T> { /** * {@inheritDoc} */ + public void setModified(boolean modified) { + this.modified = modified; + } + + /** + * {@inheritDoc} + */ + public boolean isModified() { + return modified; + } + + /** + * {@inheritDoc} + */ @SuppressWarnings("unchecked") public T getCascadingValue() { if (null == propertyKey) { @@ -126,10 +141,12 @@ public class BaseProjectProperty<T> implements IProjectProperty<T> { } else { T cascadingValue = getCascadingValue(); T candidateValue = null == value ? getDefaultValue() : value; - if (allowOverrideValue(cascadingValue, candidateValue)) { - setOriginalValue(value, true); - } else { - resetValue(); + if (isModified()) { + if (allowOverrideValue(cascadingValue, candidateValue)) { + setOriginalValue(value, true); + } else { + resetValue(); + } } } } diff --git a/hudson-core/src/test/java/hudson/model/FreeStyleProjectTest.java b/hudson-core/src/test/java/hudson/model/FreeStyleProjectTest.java index 14b1688..9cf4538 100644 --- a/hudson-core/src/test/java/hudson/model/FreeStyleProjectTest.java +++ b/hudson-core/src/test/java/hudson/model/FreeStyleProjectTest.java @@ -258,6 +258,7 @@ public class FreeStyleProjectTest { parentProject.setCustomWorkspace(parentCustomWorkspace); FreeStyleProjectMock childProject = new FreeStyleProjectMock("child"); childProject.setCascadingProject(parentProject); + childProject.getStringProperty(FreeStyleProject.CUSTOM_WORKSPACE_PROPERTY_NAME).setModified(true); childProject.setCustomWorkspace(childCustomWorkspace); assertEquals(childCustomWorkspace, childProject.getCustomWorkspace()); } @@ -306,6 +307,7 @@ public class FreeStyleProjectTest { parentProject.setJDK(parentJdkName); FreeStyleProjectMock childProject = new FreeStyleProjectMock("child"); childProject.setCascadingProject(parentProject); + childProject.getStringProperty(AbstractProject.JDK_PROPERTY_NAME).setModified(true); childProject.setJDK(childJdkName); assertEquals(childJdkName, childProject.getJDKName()); } @@ -379,6 +381,7 @@ public class FreeStyleProjectTest { parentProject.setQuietPeriod(parentQuietPeriod); FreeStyleProjectMock childProject = new FreeStyleProjectMock("child"); childProject.setCascadingProject(parentProject); + childProject.getIntegerProperty(AbstractProject.QUIET_PERIOD_PROPERTY_NAME).setModified(true); childProject.setQuietPeriod(childQuietPeriod); Hudson hudson = createMock(Hudson.class); @@ -452,6 +455,7 @@ public class FreeStyleProjectTest { replayAll(); assertEquals(childProject.getScmCheckoutRetryCount(), globalScmCheckoutRetryCount); childProject.setCascadingProject(parentProject); + childProject.getIntegerProperty(AbstractProject.SCM_CHECKOUT_RETRY_COUNT_PROPERTY_NAME).setModified(true); childProject.setScmCheckoutRetryCount(scmCheckoutRetryCount); assertEquals(childProject.getScmCheckoutRetryCount(), Integer.parseInt(scmCheckoutRetryCount)); verifyAll(); @@ -465,6 +469,7 @@ public class FreeStyleProjectTest { parentProject.setScmCheckoutRetryCount(parentScmCheckoutRetryCount); FreeStyleProjectMock childProject = new FreeStyleProjectMock("child"); childProject.setCascadingProject(parentProject); + childProject.getIntegerProperty(AbstractProject.SCM_CHECKOUT_RETRY_COUNT_PROPERTY_NAME).setModified(true); childProject.setScmCheckoutRetryCount(childScmCheckoutRetryCount); Hudson hudson = createMock(Hudson.class); diff --git a/hudson-core/src/test/java/hudson/model/LegacyProjectTest.java b/hudson-core/src/test/java/hudson/model/LegacyProjectTest.java index 539c50f..d22732e 100644 --- a/hudson-core/src/test/java/hudson/model/LegacyProjectTest.java +++ b/hudson-core/src/test/java/hudson/model/LegacyProjectTest.java @@ -19,6 +19,8 @@ import hudson.tasks.Maven; import hudson.tasks.junit.JUnitResultArchiver; import java.io.File; import java.net.URISyntaxException; +import org.eclipse.hudson.api.model.IProjectProperty; +import org.eclipse.hudson.api.model.project.property.BooleanProjectProperty; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; @@ -62,7 +64,9 @@ public class LegacyProjectTest { project.initProjectProperties(); assertNull(project.getProperty(FreeStyleProject.CUSTOM_WORKSPACE_PROPERTY_NAME)); project.convertCustomWorkspaceProperty(); - assertNotNull(project.getProperty(FreeStyleProject.CUSTOM_WORKSPACE_PROPERTY_NAME)); + IProjectProperty property = project.getProperty(FreeStyleProject.CUSTOM_WORKSPACE_PROPERTY_NAME); + assertNotNull(property); + assertEquals("/tmp", property.getValue()); } /** @@ -149,7 +153,10 @@ public class LegacyProjectTest { project.initProjectProperties(); assertNull(project.getProperty(AbstractProject.BLOCK_BUILD_WHEN_DOWNSTREAM_BUILDING_PROPERTY_NAME)); project.convertBlockBuildWhenDownstreamBuildingProperty(); - assertNotNull(project.getProperty(AbstractProject.BLOCK_BUILD_WHEN_DOWNSTREAM_BUILDING_PROPERTY_NAME)); + BooleanProjectProperty property = (BooleanProjectProperty)project.getProperty( + AbstractProject.BLOCK_BUILD_WHEN_DOWNSTREAM_BUILDING_PROPERTY_NAME); + assertNotNull(property); + assertTrue(property.getValue()); } /** @@ -165,7 +172,10 @@ public class LegacyProjectTest { project.initProjectProperties(); assertNull(project.getProperty(AbstractProject.BLOCK_BUILD_WHEN_UPSTREAM_BUILDING_PROPERTY_NAME)); project.convertBlockBuildWhenUpstreamBuildingProperty(); - assertNotNull(project.getProperty(AbstractProject.BLOCK_BUILD_WHEN_UPSTREAM_BUILDING_PROPERTY_NAME)); + BooleanProjectProperty property = (BooleanProjectProperty)project.getProperty( + AbstractProject.BLOCK_BUILD_WHEN_UPSTREAM_BUILDING_PROPERTY_NAME); + assertNotNull(property); + assertTrue(property.getValue()); } /** @@ -181,7 +191,10 @@ public class LegacyProjectTest { project.initProjectProperties(); assertNull(project.getProperty(AbstractProject.CONCURRENT_BUILD_PROPERTY_NAME)); project.convertConcurrentBuildProperty(); - assertNotNull(project.getProperty(AbstractProject.CONCURRENT_BUILD_PROPERTY_NAME)); + BooleanProjectProperty property = (BooleanProjectProperty)project.getProperty( + AbstractProject.CONCURRENT_BUILD_PROPERTY_NAME); + assertNotNull(property); + assertTrue(property.getValue()); } /** diff --git a/hudson-core/src/test/java/org/eclipse/hudson/api/model/project/property/ProjectPropertyTest.java b/hudson-core/src/test/java/org/eclipse/hudson/api/model/project/property/ProjectPropertyTest.java index 38f2d9c..f544a6d 100644 --- a/hudson-core/src/test/java/org/eclipse/hudson/api/model/project/property/ProjectPropertyTest.java +++ b/hudson-core/src/test/java/org/eclipse/hudson/api/model/project/property/ProjectPropertyTest.java @@ -486,6 +486,7 @@ public class ProjectPropertyTest { project.setCascadingProject(parent); //If value set to null, need to check whether default value is equals to cascading + property.setModified(true); property.setValue(null); assertTrue(property.isOverridden()); String overriddenValue = "newValue"; diff --git a/hudson-war/src/main/webapp/scripts/cascading.js b/hudson-war/src/main/webapp/scripts/cascading.js index 00a96e7..43c61d2 100644 --- a/hudson-war/src/main/webapp/scripts/cascading.js +++ b/hudson-war/src/main/webapp/scripts/cascading.js @@ -1,7 +1,7 @@ /******************************************************************************* * - * Copyright (c) 2004-2010 Oracle Corporation. + * 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 @@ -31,10 +31,14 @@ hudsonRules["A.reset-button"] = function(e) { e = null; // avoid memory leak } -jQuery(document).ready(function(){ - jQuery('select[name=cascadingProjectName]').change(function() { - var url = window.location.href; - var jobUrl = url.substr(0, url.lastIndexOf('/'))+'/updateCascadingProject'; +function getJobUrl() { + var url = window.location.href; + return url.substr(0, url.lastIndexOf('/')) +} + +function onCascadingProjectUpdated() { + jQuery('select[name=cascadingProjectName]').change(function() { + var jobUrl = getJobUrl()+'/updateCascadingProject'; var cascadingProject = jQuery(this).val(); new Ajax.Request(jobUrl+'?projectName='+cascadingProject, { method : 'get', @@ -43,4 +47,27 @@ jQuery(document).ready(function(){ } }); }); -});
\ No newline at end of file +} + +function onProjectPropertyChanged() { + jQuery('input').change(function() { + var ref = jQuery(this).attr('id'); + var cascadingProperty = ''; + if (ref != '') { + cascadingProperty = jQuery(this).attr('name'); + } else { + var childRef = jQuery(this).parents('tr').attr('nameref'); + cascadingProperty = jQuery('#'+childRef).attr('name'); + } + var jobUrl = getJobUrl()+'/modifyCascadingProperty?propertyName='+cascadingProperty; + new Ajax.Request(jobUrl, { + method : 'get' + }); + }); +} + +jQuery(document).ready(function(){ + onCascadingProjectUpdated(); + onProjectPropertyChanged(); +}); + |

