Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[FIXED JENKINS-27375] Enables to disable specific choice list provide…
…rs in system configuration page.
  • Loading branch information
ikedam committed Apr 26, 2015
1 parent dcbbb6c commit f7e23a3
Show file tree
Hide file tree
Showing 13 changed files with 852 additions and 448 deletions.
@@ -0,0 +1,91 @@
/*
* The MIT License
*
* Copyright (c) 2014 IKEDA Yasuyuki
*
* 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 jp.ikedam.jenkins.plugins.extensible_choice_parameter;

import hudson.model.Descriptor;

/**
* Descriptor for {@link ChoiceListProvider}s.
*/
public abstract class ChoiceListProviderDescriptor extends Descriptor<ChoiceListProvider>
{
protected ChoiceListProviderDescriptor()
{
super();
}

/**
* @param clazz
*/
protected ChoiceListProviderDescriptor(Class<? extends ChoiceListProvider> clazz)
{
super(clazz);
}


/**
* Returns whether this provider should be enabled by default (that is, just after that provider is installed).
*
* Override this method and return false if you want to disable your provider
* and want administrators enable that explicitly.
*
* @return
*/
public boolean isEnabledByDefault()
{
return true;
}

/**
* Disables the global configuration page and replaces with {@link #getGlobalConfigPageForChoiceListProvider()}
*
* @return false
* @see hudson.model.Descriptor#getGlobalConfigPage()
*/
@Override
public String getGlobalConfigPage()
{
return null;
}

/**
* @return a view page displayed in the system configuration page under the section of {@link ExtensibleChoiceParameterDefinition}
*/
public String getGlobalConfigPageForChoiceListProvider()
{
for (String cand: getPossibleViewNames("global")) {
String page = getViewPage(clazz, cand);
// Unfortunately, Descriptor#getViewPage returns passed value
// when that view is not found.
// When found, path to that file is returned,
// so I can check whether found
// by comparing passing value and returned value.
if (page != null && !page.equals(cand)) {
return page;
}
}
return null;
}
}
Expand Up @@ -24,8 +24,13 @@
package jp.ikedam.jenkins.plugins.extensible_choice_parameter;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;

import jenkins.model.Jenkins;
Expand All @@ -34,6 +39,7 @@
import hudson.Util;
import hudson.model.Descriptor;
import hudson.model.Describable;
import hudson.model.DescriptorVisibilityFilter;
import hudson.model.ParameterValue;
import hudson.model.StringParameterValue;
import hudson.model.SimpleParameterDefinition;
Expand All @@ -54,6 +60,7 @@
public class ExtensibleChoiceParameterDefinition extends SimpleParameterDefinition
{
private static final long serialVersionUID = 1L;
private static final Logger LOGGER = Logger.getLogger(ExtensibleChoiceParameterDefinition.class.getName());

private static final Pattern namePattern = Pattern.compile("[A-Za-z_][A-Za-z_0-9]*");

Expand Down Expand Up @@ -81,38 +88,62 @@ public static Pattern getNamePattern()
@Extension
public static class DescriptorImpl extends ParameterDescriptor
{
private List<String> disabledChoiceLists;
private Map<String,Boolean> choiceListEnabledMap;

public DescriptorImpl()
{
disabledChoiceLists = Collections.emptyList();
setChoiceListEnabledMap(Collections.<String, Boolean>emptyMap());
load();
}

protected void setChoiceListEnabledMap(Map<String, Boolean> choiceListEnabledMap)
{
this.choiceListEnabledMap = choiceListEnabledMap;
}

protected Map<String, Boolean> getChoiceListEnabledMap()
{
return choiceListEnabledMap;
}

@Override
public boolean configure(StaplerRequest req, JSONObject json) throws hudson.model.Descriptor.FormException
{
List<String> configuredToDisableChoiceLists = new ArrayList<String>();
Map<String, Boolean> configuredChoiceListEnableMap = new HashMap<String, Boolean>();
for(Descriptor<ChoiceListProvider> d: getChoiceListProviderList())
{
String name = d.getJsonSafeClassName();
JSONObject o = json.optJSONObject(name);

if(o == null)
if(o != null)
{
configuredToDisableChoiceLists.add(d.getId());
configuredChoiceListEnableMap.put(d.getId(), true);
d.configure(req, o);
}
else
{
configuredChoiceListEnableMap.put(d.getId(), false);
}
}
disabledChoiceLists = configuredToDisableChoiceLists;
setChoiceListEnabledMap(configuredChoiceListEnableMap);

save();

return super.configure(req, json);
}

public boolean isProviderEnabled(Descriptor<ChoiceListProvider> d)
public boolean isProviderEnabled(Descriptor<?> d)
{
return !disabledChoiceLists.contains(d.getId());
Boolean b = getChoiceListEnabledMap().get(d.getId());
if(b != null)
{
return b.booleanValue();
}
if(!(d instanceof ChoiceListProviderDescriptor))
{
return true;
}
return ((ChoiceListProviderDescriptor)d).isEnabledByDefault();
}

/**
Expand Down Expand Up @@ -197,15 +228,25 @@ public String getDisplayName()
/**
* Returns all the available methods to provide choices.
*
* Used for showing dropdown for users to select a choice provider.
*
* @return DescriptorExtensionList of ChoiceListProvider subclasses.
*/
public DescriptorExtensionList<ChoiceListProvider,Descriptor<ChoiceListProvider>> getChoiceListProviderList()
{
return ChoiceListProvider.all();
}

/**
* Returns all the available methods to provide choices that are enabled in the global configuration.
*
* Used for showing dropdown for users to select a choice provider.
*
* @return DescriptorExtensionList of ChoiceListProvider subclasses.
*/
public List<Descriptor<ChoiceListProvider>> getEnabledChoiceListProviderList()
{
return DescriptorVisibilityFilter.apply(this, ChoiceListProvider.all());
}

public FormValidation doCheckName(@QueryParameter String name){
if(StringUtils.isBlank(name))
{
Expand Down Expand Up @@ -238,6 +279,21 @@ public String resolve(String name)
}
}

@Extension
public static class DescriptorVisibilityFilterImpl extends DescriptorVisibilityFilter
{
@SuppressWarnings("unchecked")
@Override
public boolean filter(Object context, @SuppressWarnings("rawtypes") Descriptor descriptor)
{
if(!(context instanceof DescriptorImpl))
{
return true;
}
return ((DescriptorImpl)context).isProviderEnabled(descriptor);
}
}

private boolean editable = false;

/**
Expand All @@ -262,14 +318,39 @@ public ChoiceListProvider getChoiceListProvider()
return choiceListProvider;
}

/**
* @return choice provider only when it's enabled
* @see DescriptorImpl#isProviderEnabled(Descriptor)
*/
public ChoiceListProvider getEnabledChoiceListProvider()
{
ChoiceListProvider p = getChoiceListProvider();
if(p == null)
{
return null;
}

// filter providers.
List<Descriptor<ChoiceListProvider>> testList = DescriptorVisibilityFilter.apply(
getDescriptor(),
Arrays.asList(p.getDescriptor())
);
if(testList.isEmpty())
{
LOGGER.log(Level.WARNING, "{0} is configured but disabled in the system configuration.", p.getDescriptor().getDisplayName());
return null;
}
return p;
}

/**
* Return choices available for this parameter.
*
* @return list of choices. never null.
*/
public List<String> getChoiceList()
{
ChoiceListProvider provider = getChoiceListProvider();
ChoiceListProvider provider = getEnabledChoiceListProvider();
List<String> choiceList = (provider != null)?provider.getChoiceList():null;
return (choiceList != null)?choiceList:new ArrayList<String>(0);
}
Expand Down Expand Up @@ -359,7 +440,8 @@ public ParameterValue createValue(String value) throws IllegalArgumentException
@Override
public ParameterValue getDefaultParameterValue()
{
String defaultChoice = (getChoiceListProvider() != null)?getChoiceListProvider().getDefaultChoice():null;
ChoiceListProvider p = getEnabledChoiceListProvider();
String defaultChoice = (p != null)?p.getDefaultChoice():null;
if(defaultChoice != null)
{
return createValue(defaultChoice);
Expand Down
Expand Up @@ -31,7 +31,6 @@

import hudson.Extension;
import hudson.model.AbstractProject;
import hudson.model.Descriptor;
import hudson.util.ListBoxModel;

import org.apache.commons.collections.CollectionUtils;
Expand Down Expand Up @@ -73,7 +72,7 @@ public class GlobalTextareaChoiceListProvider extends AddEditedChoiceListProvide
* </dl>
*/
@Extension
public static class DescriptorImpl extends Descriptor<ChoiceListProvider>
public static class DescriptorImpl extends ChoiceListProviderDescriptor
{
/**
* Restore from the global configuration
Expand Down
Expand Up @@ -34,7 +34,7 @@ THE SOFTWARE.
<f:dropdownList title="${%Choice Provider}" name="choiceListProvider" help="${descriptor.getHelpFile('choiceListProvider')}">
<j:forEach
var="curDescriptor"
items="${descriptor.choiceListProviderList.iterator()}"
items="${descriptor.enabledChoiceListProviderList.iterator()}"
varStatus="loop">
<j:scope>
<j:set
Expand Down
Expand Up @@ -28,7 +28,15 @@ THE SOFTWARE.
-->
<f:section title="${descriptor.displayName}">
<j:forEach var="d" items="${instance.choiceListProviderList}">
<f:optionalBlock name="${d.jsonSafeClassName}" checked="${instance.isProviderEnabled(d)}" help="${d.helpFile}" title="${d.displayName}" />
<f:optionalBlock name="${d.jsonSafeClassName}" checked="${instance.isProviderEnabled(d)}" help="${d.helpFile}" title="${d.displayName}">
<j:if test="${d.globalConfigPageForChoiceListProvider != null}">
<j:scope>
<j:set var="descriptor" value="${d}" />
<j:set var="instance" value="${descriptor}" />
<st:include page="${d.globalConfigPageForChoiceListProvider}" from="${d}" />
</j:scope>
</j:if>
</f:optionalBlock>
</j:forEach>
</f:section>
</j:jelly>
@@ -0,0 +1 @@
testtest
Expand Up @@ -26,13 +26,11 @@ THE SOFTWARE.
The view shown in the System Configuration.
Input fields are located in config.jelly of GlobalTextChoiceListEntry.
-->
<f:section title="${%Global Choice Parameter}">
<f:block>
<f:repeatableProperty
field="choiceListEntryList"
add="${%Add New Choice List}"
header="${descriptor.displayName}"
/>
</f:block>
</f:section>
</j:jelly>

0 comments on commit f7e23a3

Please sign in to comment.