diff --git a/core/src/main/java/hudson/Functions.java b/core/src/main/java/hudson/Functions.java index 1ce8caa559..e72340ab32 100644 --- a/core/src/main/java/hudson/Functions.java +++ b/core/src/main/java/hudson/Functions.java @@ -57,6 +57,7 @@ import hudson.views.MyViewsTabBar; import hudson.views.ViewsTabBar; import hudson.widgets.RenderOnDemandClosure; import jenkins.model.GlobalConfiguration; +import jenkins.model.GlobalSecurityConfigurationPart; import jenkins.model.Jenkins; import jenkins.model.ModelObjectWithContextMenu; import org.acegisecurity.providers.anonymous.AnonymousAuthenticationToken; @@ -74,7 +75,6 @@ import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.StaplerResponse; import org.kohsuke.stapler.jelly.InternationalizedStringExpression.RawHtmlArgument; -import javax.management.modelmbean.DescriptorSupport; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; @@ -771,30 +771,6 @@ public class Functions { * we needed this for {@link GlobalConfiguration}s are for backward compatibility. */ public static Collection getSortedDescriptorsForGlobalConfig() { - class Tag implements Comparable { - double ordinal; - String hierarchy; - Descriptor d; - - Tag(double ordinal, Descriptor d) { - this.ordinal = ordinal; - this.d = d; - this.hierarchy = buildSuperclassHierarchy(d.clazz, new StringBuilder()).toString(); - } - - private StringBuilder buildSuperclassHierarchy(Class c, StringBuilder buf) { - Class sc = c.getSuperclass(); - if (sc!=null) buildSuperclassHierarchy(sc,buf).append(':'); - return buf.append(c.getName()); - } - - public int compareTo(Tag that) { - int r = Double.compare(this.ordinal, that.ordinal); - if (r!=0) return -r; // descending for ordinal - return this.hierarchy.compareTo(that.hierarchy); - } - } - ExtensionList exts = Jenkins.getInstance().getExtensionList(Descriptor.class); List r = new ArrayList(exts.size()); @@ -812,7 +788,47 @@ public class Functions { return DescriptorVisibilityFilter.apply(Jenkins.getInstance(),answer); } + public static Collection getSortedDescriptorsForGlobalSecurityConfig() { + ExtensionList exts = Jenkins.getInstance().getExtensionList(GlobalSecurityConfigurationPart.class); + + List r = new ArrayList(exts.size()); + for (ExtensionComponent c : exts.getComponents()) { + Descriptor d = c.getInstance(); + if (d.getGlobalConfigPage()==null) continue; + r.add(new Tag(c.ordinal(), d)); + } + Collections.sort(r); + List answer = new ArrayList(r.size()); + for (Tag d : r) answer.add(d.d); + + return DescriptorVisibilityFilter.apply(Jenkins.getInstance(),answer); + + } + + private static class Tag implements Comparable { + double ordinal; + String hierarchy; + Descriptor d; + + Tag(double ordinal, Descriptor d) { + this.ordinal = ordinal; + this.d = d; + this.hierarchy = buildSuperclassHierarchy(d.clazz, new StringBuilder()).toString(); + } + + private StringBuilder buildSuperclassHierarchy(Class c, StringBuilder buf) { + Class sc = c.getSuperclass(); + if (sc!=null) buildSuperclassHierarchy(sc,buf).append(':'); + return buf.append(c.getName()); + } + + public int compareTo(Tag that) { + int r = Double.compare(this.ordinal, that.ordinal); + if (r!=0) return -r; // descending for ordinal + return this.hierarchy.compareTo(that.hierarchy); + } + } /** * Computes the path to the icon of the given action * from the context path. diff --git a/core/src/main/java/hudson/security/GlobalSecurityConfiguration.java b/core/src/main/java/hudson/security/GlobalSecurityConfiguration.java index a26a3b1078..6435e01843 100644 --- a/core/src/main/java/hudson/security/GlobalSecurityConfiguration.java +++ b/core/src/main/java/hudson/security/GlobalSecurityConfiguration.java @@ -25,7 +25,9 @@ package hudson.security; import hudson.BulkChange; import hudson.Extension; +import hudson.Functions; import hudson.markup.MarkupFormatter; +import hudson.model.Descriptor; import hudson.model.Descriptor.FormException; import hudson.model.ManagementLink; import hudson.util.FormApply; @@ -95,9 +97,23 @@ public class GlobalSecurityConfiguration extends ManagementLink { } else { j.disableSecurity(); } - // return true for backward compatibility reasons - return true; + + // persist all the additional security configs + boolean result = true; + for(Descriptor d : Functions.getSortedDescriptorsForGlobalSecurityConfig()){ + result &= configureDescriptor(req,json,d); + } + + return result; } + + private boolean configureDescriptor(StaplerRequest req, JSONObject json, Descriptor d) throws FormException { + // collapse the structure to remain backward compatible with the JSON structure before 1. + String name = d.getJsonSafeClassName(); + JSONObject js = json.has(name) ? json.getJSONObject(name) : new JSONObject(); // if it doesn't have the property, the method returns invalid null object. + json.putAll(js); + return d.configure(req, js); + } @Override public String getDisplayName() { diff --git a/core/src/main/java/jenkins/model/GlobalSecurityConfigurationPart.java b/core/src/main/java/jenkins/model/GlobalSecurityConfigurationPart.java new file mode 100644 index 0000000000..c34c1996a4 --- /dev/null +++ b/core/src/main/java/jenkins/model/GlobalSecurityConfigurationPart.java @@ -0,0 +1,48 @@ +package jenkins.model; + +import hudson.ExtensionList; +import hudson.ExtensionPoint; +import hudson.model.Describable; +import hudson.model.Descriptor; + +/** + * Convenient base class for extensions that contributes to the global security configuration page but nothing else. + * + *

Views

+ *

+ * Subtypes of this class should define config.groovy that gets pulled into the global security configuration page. + * + * + * @author Dominik Bartholdi + * @since 1.494 + */ +public abstract class GlobalSecurityConfigurationPart extends Descriptor implements ExtensionPoint, Describable { + protected GlobalSecurityConfigurationPart() { + super(self()); + } + + public final Descriptor getDescriptor() { + return this; + } + + /** + * Unless this object has additional web presence, display name is not used at all. + * So default to "". + */ + public String getDisplayName() { + return ""; + } + + @Override + public String getGlobalConfigPage() { + return getConfigPage(); + } + + /** + * Returns all the registered {@link GlobalSecurityConfigurationPart} descriptors. + */ + public static ExtensionList all() { + return Jenkins.getInstance().getDescriptorList(GlobalSecurityConfigurationPart.class); + // pointless type parameters help work around bugs in javac in earlier versions http://codepad.org/m1bbFRrH + } +} diff --git a/core/src/main/resources/hudson/security/GlobalSecurityConfiguration/index.jelly b/core/src/main/resources/hudson/security/GlobalSecurityConfiguration/index.jelly index 597a2d931e..d7b720761a 100644 --- a/core/src/main/resources/hudson/security/GlobalSecurityConfiguration/index.jelly +++ b/core/src/main/resources/hudson/security/GlobalSecurityConfiguration/index.jelly @@ -28,6 +28,13 @@ + + + + + + +