Skip to content

Commit

Permalink
[FIX JENKINS-14538] Move tool configuration to separate page
Browse files Browse the repository at this point in the history
  • Loading branch information
daniel-beck committed Feb 3, 2016
1 parent 9cab873 commit ea5b2a7
Show file tree
Hide file tree
Showing 9 changed files with 199 additions and 15 deletions.
6 changes: 4 additions & 2 deletions core/src/main/java/hudson/Functions.java
Expand Up @@ -956,11 +956,13 @@ public static Collection<Descriptor> getSortedDescriptorsForGlobalConfig(Predica
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);
Expand Down
15 changes: 14 additions & 1 deletion core/src/main/java/hudson/model/Descriptor.java
Expand Up @@ -36,6 +36,8 @@
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;
Expand Down Expand Up @@ -807,7 +809,18 @@ public String getConfigPage() {
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);
}
Expand Down
8 changes: 8 additions & 0 deletions core/src/main/java/hudson/tools/ToolDescriptor.java
Expand Up @@ -34,6 +34,8 @@
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;
Expand Down Expand Up @@ -89,6 +91,12 @@ public List<ToolPropertyDescriptor> getPropertyDescriptors() {
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,
Expand Down
9 changes: 0 additions & 9 deletions core/src/main/java/jenkins/model/GlobalConfiguration.java
Expand Up @@ -42,15 +42,6 @@ public final Descriptor<GlobalConfiguration> getDescriptor() {
return this;
}

/**
* Every {@link GlobalConfiguration} belongs to a specific category.
*
* @return never null, always the same value for a given instance of {@link GlobalConfiguration}.
*/
public GlobalConfigurationCategory getCategory() {
return GlobalConfigurationCategory.get(GlobalConfigurationCategory.Unclassified.class);
}

@Override
public String getGlobalConfigPage() {
return getConfigPage();
Expand Down
21 changes: 18 additions & 3 deletions core/src/main/java/jenkins/model/GlobalConfigurationCategory.java
Expand Up @@ -4,8 +4,6 @@
import hudson.ExtensionList;
import hudson.ExtensionPoint;
import hudson.model.ModelObject;
import hudson.security.*;
import hudson.security.Messages;

/**
* Grouping of related {@link GlobalConfiguration}s.
Expand Down Expand Up @@ -73,11 +71,28 @@ public String getDisplayName() {
public static class Security extends GlobalConfigurationCategory {
@Override
public String getShortDescription() {
return Messages.GlobalSecurityConfiguration_Description();
return hudson.security.Messages.GlobalSecurityConfiguration_Description();
}

public String getDisplayName() {
return hudson.security.Messages.GlobalSecurityConfiguration_DisplayName();
}
}

/**
* Global configuration of tool locations and installers.
*
* @since TODO
*/
@Extension
public static class Tools extends GlobalConfigurationCategory {
@Override
public String getShortDescription() {
return jenkins.management.Messages.ConfigureTools_Description();
}

public String getDisplayName() {
return jenkins.management.Messages.ConfigureTools_DisplayName();
}
}
}
102 changes: 102 additions & 0 deletions core/src/main/java/jenkins/model/GlobalToolConfiguration.java
@@ -0,0 +1,102 @@
/*
* The MIT License
*
* Copyright (c) 2016 CloudBees, Inc.
*
* 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 jenkins.model;

import com.google.common.base.Predicate;
import hudson.Extension;
import hudson.Functions;
import hudson.model.Descriptor;
import hudson.model.ManagementLink;
import hudson.security.Permission;
import hudson.util.FormApply;
import net.sf.json.JSONObject;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;

import javax.servlet.ServletException;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;

@Extension(ordinal = Integer.MAX_VALUE - 220)
public class GlobalToolConfiguration extends ManagementLink {

@Override
public String getIconFileName() {
return "setting.png"; // TODO more appropriate icon
}

@Override
public String getDisplayName() {
return jenkins.management.Messages.ConfigureTools_DisplayName();
}

@Override
public String getDescription() {
return jenkins.management.Messages.ConfigureTools_Description();
}

@Override
public String getUrlName() {
return "configureTools";
}

@Override
public Permission getRequiredPermission() {
return Jenkins.ADMINISTER;
}

public synchronized void doConfigure(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException, Descriptor.FormException {
boolean result = configure(req, req.getSubmittedForm());
LOGGER.log(Level.FINE, "tools saved: "+result);
FormApply.success(req.getContextPath() + "/manage").generateResponse(req, rsp, null);
}

private boolean configure(StaplerRequest req, JSONObject json) throws hudson.model.Descriptor.FormException {
Jenkins j = Jenkins.getInstance();
j.checkPermission(Jenkins.ADMINISTER);

boolean result = true;
for(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<GlobalConfigurationCategory> FILTER = new Predicate<GlobalConfigurationCategory>() {
public boolean apply(GlobalConfigurationCategory input) {
return input instanceof GlobalConfigurationCategory.Tools;
}
};

private static final Logger LOGGER = Logger.getLogger(GlobalToolConfiguration.class.getName());
}
6 changes: 6 additions & 0 deletions core/src/main/java/jenkins/mvn/GlobalMavenConfig.java
Expand Up @@ -2,6 +2,7 @@

import hudson.Extension;
import jenkins.model.GlobalConfiguration;
import jenkins.model.GlobalConfigurationCategory;
import net.sf.json.JSONObject;

import org.kohsuke.stapler.StaplerRequest;
Expand All @@ -16,6 +17,11 @@ public GlobalMavenConfig() {
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);
Expand Down
Expand Up @@ -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.
Expand Down
@@ -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")
}
}

0 comments on commit ea5b2a7

Please sign in to comment.