提交 88ea8de4 编写于 作者: K Kohsuke Kawaguchi 提交者: Stephen Connolly

added a mechanism for creating invisible node properties

上级 788209de
...@@ -382,7 +382,7 @@ THE SOFTWARE. ...@@ -382,7 +382,7 @@ THE SOFTWARE.
<dependency> <dependency>
<groupId>org.kohsuke.stapler</groupId> <groupId>org.kohsuke.stapler</groupId>
<artifactId>stapler-jelly</artifactId> <artifactId>stapler-jelly</artifactId>
<version>1.155</version> <version>1.161</version>
<exclusions> <exclusions>
<exclusion> <exclusion>
<groupId>commons-jelly</groupId> <groupId>commons-jelly</groupId>
......
...@@ -51,6 +51,7 @@ import hudson.util.TagCloud; ...@@ -51,6 +51,7 @@ import hudson.util.TagCloud;
import hudson.util.TagCloud.WeightFunction; import hudson.util.TagCloud.WeightFunction;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Type;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
...@@ -58,6 +59,7 @@ import java.util.List; ...@@ -58,6 +59,7 @@ import java.util.List;
import java.util.logging.Logger; import java.util.logging.Logger;
import net.sf.json.JSONObject; import net.sf.json.JSONObject;
import org.kohsuke.stapler.BindInterceptor;
import org.kohsuke.stapler.Stapler; import org.kohsuke.stapler.Stapler;
import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.export.ExportedBean; import org.kohsuke.stapler.export.ExportedBean;
...@@ -365,8 +367,32 @@ public abstract class Node extends AbstractModelObject implements Reconfigurable ...@@ -365,8 +367,32 @@ public abstract class Node extends AbstractModelObject implements Reconfigurable
return getACL().hasPermission(permission); return getACL().hasPermission(permission);
} }
public Node reconfigure(StaplerRequest req, JSONObject form) throws FormException { public Node reconfigure(final StaplerRequest req, JSONObject form) throws FormException {
return form==null ? null : getDescriptor().newInstance(req, form); if (form==null) return null;
final JSONObject jsonForProperties = form.optJSONObject("nodeProperties");
BindInterceptor old = req.setBindListener(new BindInterceptor() {
@Override
public Object onConvert(Type targetType, Class targetTypeErasure, Object jsonSource) {
if (jsonForProperties!=jsonSource) return DEFAULT;
try {
DescribableList<NodeProperty<?>, NodePropertyDescriptor> tmp = new DescribableList<NodeProperty<?>, NodePropertyDescriptor>(Saveable.NOOP,getNodeProperties().toList());
tmp.rebuild(req, jsonForProperties, NodeProperty.all());
return tmp.toList();
} catch (FormException e) {
throw new IllegalArgumentException(e);
} catch (IOException e) {
throw new IllegalArgumentException(e);
}
}
});
try {
return getDescriptor().newInstance(req, form);
} finally {
req.setBindListener(old);
}
} }
public abstract NodeDescriptor getDescriptor(); public abstract NodeDescriptor getDescriptor();
......
...@@ -26,6 +26,8 @@ package hudson.slaves; ...@@ -26,6 +26,8 @@ package hudson.slaves;
import hudson.ExtensionPoint; import hudson.ExtensionPoint;
import hudson.Launcher; import hudson.Launcher;
import hudson.DescriptorExtensionList; import hudson.DescriptorExtensionList;
import hudson.model.Descriptor.FormException;
import hudson.model.ReconfigurableDescribable;
import hudson.model.queue.CauseOfBlockage; import hudson.model.queue.CauseOfBlockage;
import hudson.scm.SCM; import hudson.scm.SCM;
import hudson.model.AbstractBuild; import hudson.model.AbstractBuild;
...@@ -35,6 +37,8 @@ import hudson.model.Environment; ...@@ -35,6 +37,8 @@ import hudson.model.Environment;
import hudson.model.Hudson; import hudson.model.Hudson;
import hudson.model.Node; import hudson.model.Node;
import hudson.model.Queue.Task; import hudson.model.Queue.Task;
import net.sf.json.JSONObject;
import org.kohsuke.stapler.StaplerRequest;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
...@@ -63,7 +67,7 @@ import java.util.List; ...@@ -63,7 +67,7 @@ import java.util.List;
* *
* @since 1.286 * @since 1.286
*/ */
public abstract class NodeProperty<N extends Node> implements Describable<NodeProperty<?>>, ExtensionPoint { public abstract class NodeProperty<N extends Node> implements ReconfigurableDescribable<NodeProperty<?>>, ExtensionPoint {
protected transient N node; protected transient N node;
...@@ -109,6 +113,10 @@ public abstract class NodeProperty<N extends Node> implements Describable<NodePr ...@@ -109,6 +113,10 @@ public abstract class NodeProperty<N extends Node> implements Describable<NodePr
return new Environment() {}; return new Environment() {};
} }
public NodeProperty<?> reconfigure(StaplerRequest req, JSONObject form) throws FormException {
return form==null ? null : getDescriptor().newInstance(req, form);
}
/** /**
* Lists up all the registered {@link NodeDescriptor}s in the system. * Lists up all the registered {@link NodeDescriptor}s in the system.
*/ */
......
package hudson.slaves;
import com.gargoylesoftware.htmlunit.html.HtmlForm;
import com.gargoylesoftware.htmlunit.html.HtmlLabel;
import hudson.model.Descriptor.FormException;
import hudson.model.Slave;
import net.sf.json.JSONObject;
import org.jvnet.hudson.test.HudsonTestCase;
import org.jvnet.hudson.test.TestExtension;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.StaplerRequest;
/**
* @author Kohsuke Kawaguchi
*/
public class NodePropertyTest extends HudsonTestCase {
public void testInvisibleProperty() throws Exception {
DumbSlave s = createSlave();
InvisibleProperty before = new InvisibleProperty();
s.getNodeProperties().add(before);
assertFalse(before.reconfigured);
DumbSlave s2 = configRoundtrip(s);
assertNotSame(s,s2);
InvisibleProperty after = s2.getNodeProperties().get(InvisibleProperty.class);
assertSame(before,after);
assertTrue(after.reconfigured);
}
public static class InvisibleProperty extends NodeProperty<Slave> {
boolean reconfigured = false;
@Override
public NodeProperty<?> reconfigure(StaplerRequest req, JSONObject form) throws FormException {
reconfigured = true;
return this;
}
@TestExtension
public static class DescriptorImpl extends NodePropertyDescriptor {
@Override
public String getDisplayName() {
return null;
}
}
}
public void testBasicConfigRoundtrip() throws Exception {
DumbSlave s = createSlave();
HtmlForm f = createWebClient().goTo("/computer/" + s.getNodeName() + "/configure").getFormByName("config");
((HtmlLabel)f.selectSingleNode(".//LABEL[text()='Some Property']")).click();
submit(f);
PropertyImpl p = hudson.getNode(s.getNodeName()).getNodeProperties().get(PropertyImpl.class);
assertEquals("Duke",p.name);
p.name = "Kohsuke";
configRoundtrip(s);
PropertyImpl p2 = hudson.getNode(s.getNodeName()).getNodeProperties().get(PropertyImpl.class);
assertNotSame(p,p2);
assertEqualDataBoundBeans(p,p2);
}
public static class PropertyImpl extends NodeProperty<Slave> {
public String name;
@DataBoundConstructor
public PropertyImpl(String name) {
this.name = name;
}
@TestExtension("testBasicConfigRoundtrip")
public static class DescriptorImpl extends NodePropertyDescriptor {
@Override
public String getDisplayName() {
return "Some Property";
}
}
}
}
<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form">
<f:entry field="name" title="${%Name}">
<f:textbox default="Duke"/>
</f:entry>
</j:jelly>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册