diff --git a/core/src/main/java/hudson/Functions.java b/core/src/main/java/hudson/Functions.java index 9f74f42b20..cef9739510 100644 --- a/core/src/main/java/hudson/Functions.java +++ b/core/src/main/java/hudson/Functions.java @@ -956,11 +956,13 @@ public class Functions { if (d.getGlobalConfigPage()==null) continue; if (d instanceof GlobalConfiguration) { - if (predicate.apply(((GlobalConfiguration)d).getCategory())) + if (predicate.apply((d.getCategory()))) { r.add(new Tag(c.ordinal(), d)); + } } else { - if (predicate.apply(GlobalConfigurationCategory.get(Unclassified.class))) + if (predicate.apply(d.getCategory())) { r.add(new Tag(0, d)); + } } } Collections.sort(r); diff --git a/core/src/main/java/hudson/model/Descriptor.java b/core/src/main/java/hudson/model/Descriptor.java index 2160d27b17..2a0295040c 100644 --- a/core/src/main/java/hudson/model/Descriptor.java +++ b/core/src/main/java/hudson/model/Descriptor.java @@ -36,6 +36,8 @@ import hudson.util.FormValidation.CheckMethod; import hudson.util.ReflectionUtils; import hudson.util.ReflectionUtils.Parameter; import hudson.views.ListViewColumn; +import jenkins.model.GlobalConfiguration; +import jenkins.model.GlobalConfigurationCategory; import jenkins.model.Jenkins; import net.sf.json.JSONArray; import net.sf.json.JSONObject; @@ -807,7 +809,18 @@ public abstract class Descriptor> implements Saveable { public String getGlobalConfigPage() { return getViewPage(clazz, getPossibleViewNames("global"), null); } - + + /** + * Define the global configuration category the global config of this Descriptor is in. + * + * @return never null, always the same value for a given instance of {@link Descriptor}. + * + * @since TODO, used to be in {@link GlobalConfiguration} before that. + */ + public GlobalConfigurationCategory getCategory() { + return GlobalConfigurationCategory.get(GlobalConfigurationCategory.Unclassified.class); + } + private String getViewPage(Class clazz, String pageName, String defaultValue) { return getViewPage(clazz,Collections.singleton(pageName),defaultValue); } diff --git a/core/src/main/java/hudson/tools/ToolDescriptor.java b/core/src/main/java/hudson/tools/ToolDescriptor.java index 567c298a0d..9e3ae6311d 100644 --- a/core/src/main/java/hudson/tools/ToolDescriptor.java +++ b/core/src/main/java/hudson/tools/ToolDescriptor.java @@ -34,6 +34,8 @@ import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.Collections; import java.util.List; + +import jenkins.model.GlobalConfigurationCategory; import jenkins.model.Jenkins; import net.sf.json.JSONObject; import org.jvnet.tiger_types.Types; @@ -89,6 +91,12 @@ public abstract class ToolDescriptor extends Descrip return PropertyDescriptor.for_(ToolProperty.all(),clazz); } + + @Override + public GlobalConfigurationCategory getCategory() { + return GlobalConfigurationCategory.get(GlobalConfigurationCategory.Tools.class); + } + /** * Optional list of installers to be configured by default for new tools of this type. * If there are popular versions of the tool available using generic installation techniques, diff --git a/core/src/main/java/jenkins/model/GlobalConfiguration.java b/core/src/main/java/jenkins/model/GlobalConfiguration.java index 15cc69f831..31c8e08ff3 100644 --- a/core/src/main/java/jenkins/model/GlobalConfiguration.java +++ b/core/src/main/java/jenkins/model/GlobalConfiguration.java @@ -42,15 +42,6 @@ public abstract class GlobalConfiguration extends Descriptor d : Functions.getSortedDescriptorsForGlobalConfig(FILTER)){ + result &= configureDescriptor(req, json, d); + } + + return result; + } + + private boolean configureDescriptor(StaplerRequest req, JSONObject json, Descriptor d) throws Descriptor.FormException { + 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); + } + + public static Predicate FILTER = new Predicate() { + public boolean apply(GlobalConfigurationCategory input) { + return input instanceof GlobalConfigurationCategory.Tools; + } + }; + + private static final Logger LOGGER = Logger.getLogger(GlobalToolConfiguration.class.getName()); +} diff --git a/core/src/main/java/jenkins/mvn/GlobalMavenConfig.java b/core/src/main/java/jenkins/mvn/GlobalMavenConfig.java index 67ace424e8..d7dc4f5e74 100644 --- a/core/src/main/java/jenkins/mvn/GlobalMavenConfig.java +++ b/core/src/main/java/jenkins/mvn/GlobalMavenConfig.java @@ -2,6 +2,7 @@ package jenkins.mvn; import hudson.Extension; import jenkins.model.GlobalConfiguration; +import jenkins.model.GlobalConfigurationCategory; import net.sf.json.JSONObject; import org.kohsuke.stapler.StaplerRequest; @@ -16,6 +17,11 @@ public class GlobalMavenConfig extends GlobalConfiguration { load(); } + @Override + public GlobalConfigurationCategory getCategory() { + return GlobalConfigurationCategory.get(GlobalConfigurationCategory.Tools.class); + } + @Override public boolean configure(StaplerRequest req, JSONObject json) throws FormException { req.bindJSON(this, json); diff --git a/core/src/main/resources/jenkins/management/Messages.properties b/core/src/main/resources/jenkins/management/Messages.properties index 6789348339..ff1761da0f 100644 --- a/core/src/main/resources/jenkins/management/Messages.properties +++ b/core/src/main/resources/jenkins/management/Messages.properties @@ -25,6 +25,9 @@ ConfigureLink.DisplayName=Configure System ConfigureLink.Description=Configure global settings and paths. +ConfigureTools.DisplayName=Global Tool Configuration +ConfigureTools.Description=Configure tools, their locations and automatic installers. + ReloadLink.DisplayName=Reload Configuration from Disk ReloadLink.Description=Discard all the loaded data in memory and reload everything from file system.\n\ Useful when you modified config files directly on disk. diff --git a/core/src/main/resources/jenkins/model/GlobalToolConfiguration/index.groovy b/core/src/main/resources/jenkins/model/GlobalToolConfiguration/index.groovy new file mode 100644 index 0000000000..9bbba7f075 --- /dev/null +++ b/core/src/main/resources/jenkins/model/GlobalToolConfiguration/index.groovy @@ -0,0 +1,44 @@ +package hudson.security.GlobalToolConfiguration + +import hudson.Functions +import hudson.model.Descriptor + +def f=namespace(lib.FormTagLib) +def l=namespace(lib.LayoutTagLib) +def st=namespace("jelly:stapler") + +l.layout(norefresh:true, permission:app.ADMINISTER, title:my.displayName) { + l.side_panel { + l.tasks { + l.task(icon:"icon-up icon-md", href:rootURL+'/', title:_("Back to Dashboard")) + l.task(icon:"icon-setting icon-md", href:"${rootURL}/manage", title:_("Manage Jenkins")) + } + } + l.main_panel { + h1 { + l.icon(class: 'icon-setting icon-xlg') + // TODO more appropriate icon + text(my.displayName) + } + + p() + div(class:"behavior-loading", _("LOADING")) + + f.form(method:"post",name:"config",action:"configure") { + Functions.getSortedDescriptorsForGlobalConfig(my.FILTER).each { Descriptor descriptor -> + set("descriptor",descriptor) + set("instance",descriptor) + f.rowSet(name:descriptor.jsonSafeClassName) { + st.include(from:descriptor, page:descriptor.globalConfigPage) + } + } + + f.bottomButtonBar { + f.submit(value:_("Save")) + f.apply() + } + } + + st.adjunct(includes: "lib.form.confirm") + } +}