提交 abdbddb3 编写于 作者: S Stephen Connolly

Adding an extension point to allow associating custom properties with views.

上级 483e322a
......@@ -64,6 +64,8 @@ Upcoming changes</a>
(<a href="http://issues.jenkins-ci.org/browse/JENKINS-9094">issue 9094</a>)
<li class=rfe>
Added an extension point to allow adding transient actions to computers.
<li class=rfe>
Added an extension point to allow associating custom properties with views.
</ul>
</div><!--=TRUNK-END=-->
......
......@@ -24,6 +24,8 @@
package hudson.model;
import static hudson.model.Hudson.checkGoodName;
import hudson.CopyOnWrite;
import hudson.DescriptorExtensionList;
import hudson.Extension;
import hudson.ExtensionPoint;
......@@ -56,6 +58,7 @@ import java.util.Map;
import javax.servlet.ServletException;
import net.sf.json.JSONObject;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.kohsuke.stapler.export.Exported;
......@@ -111,6 +114,13 @@ public abstract class View extends AbstractModelObject implements AccessControll
protected transient List<Action> transientActions;
/**
* List of {@link ViewProperty}s configured for this view.
* @since 1.406
*/
@CopyOnWrite
private volatile List<ViewProperty> properties = new ArrayList<ViewProperty>();
protected View(String name) {
this.name = name;
}
......@@ -183,6 +193,52 @@ public abstract class View extends AbstractModelObject implements AccessControll
return description;
}
/**
* Gets the view properties configured for this view.
* @since 1.406
*/
public Map<Descriptor<ViewProperty>,ViewProperty> getProperties() {
return Descriptor.toMap(properties);
}
/**
* Updates the view object by adding a property.
* @since 1.406
*/
public synchronized void addProperty(ViewProperty p) throws IOException {
ViewProperty old = getProperty(p.getClass());
List<ViewProperty> ps = new ArrayList<ViewProperty>(properties);
if(old!=null)
ps.remove(old);
ps.add(p);
p.setView(this);
properties = ps;
owner.save();
}
/**
* List of all {@link ViewProperty}s exposed primarily for the remoting API.
* @since 1.406
*/
@Exported(name="property",inline=true)
public List<ViewProperty> getAllProperties() {
return Collections.unmodifiableList(properties);
}
/**
* Gets the specific property, or null.
* @since 1.406
*/
public <T extends ViewProperty> T getProperty(Class<T> clazz) {
for (ViewProperty p : properties) {
if(clazz.isInstance(p))
return clazz.cast(p);
}
return null;
}
public ViewDescriptor getDescriptor() {
return (ViewDescriptor)Hudson.getInstance().getDescriptorOrDie(getClass());
}
......@@ -579,6 +635,29 @@ public abstract class View extends AbstractModelObject implements AccessControll
rename(req.getParameter("name"));
JSONObject json = req.getSubmittedForm();
List<ViewProperty> props = new ArrayList<ViewProperty>();
int i = 0;
for (ViewPropertyDescriptor d: ViewProperty.all()) {
ViewProperty p = getProperty(d.clazz);
JSONObject o = json.optJSONObject("viewProperty" + (i++));
if (o != null) {
if (p != null) {
p = p.reconfigure(req, o);
} else {
p = d.newInstance(req, o);
}
p.setView(this);
}
if (p != null) {
props.add(p);
}
}
properties = props;
owner.save();
rsp.sendRedirect2("../"+name);
......
/*
* The MIT License
*
* Copyright (c) 2011, CloudBees, Inc., Stephen Connolly
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.model;
import hudson.DescriptorExtensionList;
import hudson.ExtensionPoint;
import net.sf.json.JSONObject;
import org.kohsuke.stapler.StaplerRequest;
/**
* Extensible property of {@link View}.
*
* <p>
* {@link hudson.Plugin}s can extend this to define custom properties for {@link View}s.
* {@link ViewProperty}s show up in the view configuration screen, and they are
* persisted with the view object.
*
* <p>
* Configuration screen should be defined in <code>config.jelly</code>.
* Within this page, the {@link ViewProperty} instance is available as
* the <code>instance</code> EL variable (while the <code>it</code> EL variable
* refers to the {@link View}.
*
* @author Stephen Connolly
* @since 1.406
*/
public class ViewProperty implements Describable<ViewProperty>, ExtensionPoint {
/**
* The view object that owns this property.
* This value will be set by the core code.
* Derived classes can expect this value to be always set.
*/
protected transient View view;
/*package*/ final void setView(View view) {
this.view = view;
}
public ViewPropertyDescriptor getDescriptor() {
return (ViewPropertyDescriptor)Hudson.getInstance().getDescriptorOrDie(getClass());
}
public static DescriptorExtensionList<ViewProperty,ViewPropertyDescriptor> all() {
return Hudson.getInstance().<ViewProperty,ViewPropertyDescriptor>getDescriptorList(ViewProperty.class);
}
public ViewProperty reconfigure(StaplerRequest req, JSONObject form) throws Descriptor.FormException {
return getDescriptor().newInstance(req, form);
}
}
/*
* The MIT License
*
* Copyright (c) 2011, CloudBees, Inc., Stephen Connolly
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.model;
/**
* {@link Descriptor} for {@link ViewProperty}
*
* @author Stephen Connolly
* @since 1.406
*/
public abstract class ViewPropertyDescriptor extends Descriptor<ViewProperty> {
protected ViewPropertyDescriptor(Class<? extends ViewProperty> clazz) {
super(clazz);
}
/**
* Infers the type of the corresponding {@link Describable} from the outer class.
* This version works when you follow the common convention, where a descriptor
* is written as the static nested class of the describable class.
*/
protected ViewPropertyDescriptor() {
}
/**
* Creates a default instance of {@link ViewProperty} to be associated
* with {@link View} object that wasn't created from a persisted XML data.
*
* <p>
* See {@link View} class javadoc for more details about the life cycle
* of {@link View} and when this method is invoked.
*
* @return null
* if the implementation choose not to add any property object for such view.
*/
public abstract ViewProperty newInstance(View view);
/**
* Whether or not the described property is enabled in the current context.
* Defaults to true. Over-ride in sub-classes as required.
*
* <p>
* Returning false from this method essentially has the same effect of
* making core behaves as if this {@link ViewPropertyDescriptor} is
* not a part of {@link ViewProperty#all()}.
*
* <p>
* This mechanism is useful if the availability of the property is
* contingent of some other settings.
*/
public boolean isEnabled() {
return true;
}
}
......@@ -50,6 +50,22 @@ THE SOFTWARE.
<!-- subtypes can put entries here. -->
<st:include page="configure-entries.jelly" optional="true" />
<!-- view property configurations -->
<j:invokeStatic var="descriptors" className="hudson.model.ViewProperty" method="all" />
<j:set var="instances" value="${it.properties}" />
<j:forEach var="d" items="${descriptors}" varStatus="loop">
<j:if test="${d.enabled}">
<f:section title="${d.displayName}">
<j:set var="descriptor" value="${d}" />
<j:set var="instance" value="${instances[d]}" />
<f:rowSet name="viewProperty${loop.index}">
<st:include from="${d}" page="${d.configPage}"/>
</f:rowSet>
</f:section>
</j:if>
</j:forEach>
<f:block>
<f:submit value="OK" />
</f:block>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册