From abdbddb340f4c3cf499bc68020363308669f96db Mon Sep 17 00:00:00 2001 From: Stephen Connolly Date: Wed, 30 Mar 2011 12:08:23 +0100 Subject: [PATCH] Adding an extension point to allow associating custom properties with views. --- changelog.html | 2 + core/src/main/java/hudson/model/View.java | 79 +++++++++++++++++++ .../main/java/hudson/model/ViewProperty.java | 72 +++++++++++++++++ .../hudson/model/ViewPropertyDescriptor.java | 74 +++++++++++++++++ .../hudson/model/View/configure.jelly | 16 ++++ 5 files changed, 243 insertions(+) create mode 100644 core/src/main/java/hudson/model/ViewProperty.java create mode 100644 core/src/main/java/hudson/model/ViewPropertyDescriptor.java diff --git a/changelog.html b/changelog.html index 286d5d57d3..3b03d87d61 100644 --- a/changelog.html +++ b/changelog.html @@ -64,6 +64,8 @@ Upcoming changes (issue 9094)
  • Added an extension point to allow adding transient actions to computers. +
  • + Added an extension point to allow associating custom properties with views. diff --git a/core/src/main/java/hudson/model/View.java b/core/src/main/java/hudson/model/View.java index 67ee3bc46a..1103a523a7 100644 --- a/core/src/main/java/hudson/model/View.java +++ b/core/src/main/java/hudson/model/View.java @@ -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 transientActions; + /** + * List of {@link ViewProperty}s configured for this view. + * @since 1.406 + */ + @CopyOnWrite + private volatile List properties = new ArrayList(); + 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,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 ps = new ArrayList(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 getAllProperties() { + return Collections.unmodifiableList(properties); + } + + /** + * Gets the specific property, or null. + * @since 1.406 + */ + public T getProperty(Class 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 props = new ArrayList(); + 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); diff --git a/core/src/main/java/hudson/model/ViewProperty.java b/core/src/main/java/hudson/model/ViewProperty.java new file mode 100644 index 0000000000..74cdb40a67 --- /dev/null +++ b/core/src/main/java/hudson/model/ViewProperty.java @@ -0,0 +1,72 @@ +/* + * 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}. + * + *

    + * {@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. + * + *

    + * Configuration screen should be defined in config.jelly. + * Within this page, the {@link ViewProperty} instance is available as + * the instance EL variable (while the it EL variable + * refers to the {@link View}. + * + * @author Stephen Connolly + * @since 1.406 + */ +public class ViewProperty implements Describable, 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 all() { + return Hudson.getInstance().getDescriptorList(ViewProperty.class); + } + + public ViewProperty reconfigure(StaplerRequest req, JSONObject form) throws Descriptor.FormException { + return getDescriptor().newInstance(req, form); + } + +} diff --git a/core/src/main/java/hudson/model/ViewPropertyDescriptor.java b/core/src/main/java/hudson/model/ViewPropertyDescriptor.java new file mode 100644 index 0000000000..b7c474b47f --- /dev/null +++ b/core/src/main/java/hudson/model/ViewPropertyDescriptor.java @@ -0,0 +1,74 @@ +/* + * 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 { + protected ViewPropertyDescriptor(Class 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. + * + *

    + * 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. + * + *

    + * 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()}. + * + *

    + * This mechanism is useful if the availability of the property is + * contingent of some other settings. + */ + public boolean isEnabled() { + return true; + } +} diff --git a/core/src/main/resources/hudson/model/View/configure.jelly b/core/src/main/resources/hudson/model/View/configure.jelly index 941d991329..acee8d3038 100644 --- a/core/src/main/resources/hudson/model/View/configure.jelly +++ b/core/src/main/resources/hudson/model/View/configure.jelly @@ -50,6 +50,22 @@ THE SOFTWARE. + + + + + + + + + + + + + + + + -- GitLab