├── .github
├── CODEOWNERS
├── dependabot.yml
├── release-drafter.yml
└── workflows
│ ├── cd.yaml
│ └── jenkins-security-scan.yml
├── .gitignore
├── .gitpod.yml
├── .mvn
├── extensions.xml
└── maven.config
├── Jenkinsfile
├── README.adoc
├── docs
└── images
│ ├── job_disabled_slice.png
│ ├── manage_jenkins.png
│ ├── parameters_slicing_items.png
│ ├── parameters_slicing_string_parameters.png
│ ├── scm_timer_slice.png
│ ├── string_multiple_values.png
│ ├── string_slicing_multiple_builders.png
│ └── views.png
├── pom.xml
└── src
├── main
├── java
│ └── configurationslicing
│ │ ├── AbstractJob.java
│ │ ├── BooleanSlice.java
│ │ ├── BooleanSlicer.java
│ │ ├── ConfigurationSlicing.java
│ │ ├── ParametersStringSlice.java
│ │ ├── ParametersStringSliceSpec.java
│ │ ├── ParametersStringSlicer.java
│ │ ├── Slice.java
│ │ ├── Slicer.java
│ │ ├── SlicerLoader.java
│ │ ├── TopLevelItemSelector.java
│ │ ├── UnorderedStringSlice.java
│ │ ├── UnorderedStringSlicer.java
│ │ ├── blockbuild
│ │ ├── BlockBuildWhenDownstreamBuildingBoolSlicer.java
│ │ └── BlockBuildWhenUpstreamBuildingBoolSlicer.java
│ │ ├── buildtimeout
│ │ └── BuildTimeoutSlicer.java
│ │ ├── claim
│ │ └── ClaimSlicer.java
│ │ ├── concurrentbuilds
│ │ ├── ConcurrentBuildsBoolSlicer.java
│ │ └── ConcurrentBuildsStringSlicer.java
│ │ ├── customworkspace
│ │ └── CustomWorkspaceStringSlicer.java
│ │ ├── email
│ │ ├── AbstractEmailSliceSpec.java
│ │ ├── CoreEmailSlicer.java
│ │ ├── ExtEmailSlicer.java
│ │ └── ProjectHandler.java
│ │ ├── executeshell
│ │ ├── AbstractBuildCommandSlicer.java
│ │ ├── ExecuteJythonSlicer.java
│ │ ├── ExecuteJythonSlicerWrapper.java
│ │ ├── ExecutePythonSlicer.java
│ │ ├── ExecutePythonSlicerWrapper.java
│ │ ├── ExecuteShellSlicer.java
│ │ ├── ExecuteWindowsBatchSlicer.java
│ │ └── MavenTargetsSlicer.java
│ │ ├── jdk
│ │ └── JdkSlicer.java
│ │ ├── jobdisabled
│ │ ├── JobDisabledBoolSlicer.java
│ │ └── JobDisabledStringSlicer.java
│ │ ├── label
│ │ └── LabelSlicer.java
│ │ ├── logfilesizechecker
│ │ └── LogfilesizecheckerSlicer.java
│ │ ├── logrotator
│ │ └── LogRotationSlicer.java
│ │ ├── logstash
│ │ └── LogStashSlicer.java
│ │ ├── maven
│ │ ├── MavenGoals.java
│ │ ├── MavenIncremental.java
│ │ ├── MavenOptsSlicer.java
│ │ ├── MavenSnapshotBuildTrigger.java
│ │ └── MavenVersionSlicer.java
│ │ ├── parameters
│ │ └── ParametersSlicer.java
│ │ ├── pipeline
│ │ └── PipelineScriptSlicer.java
│ │ ├── prioritysorter
│ │ ├── PrioritySorterSlicer.java
│ │ └── PrioritySorterSlicerWrapper.java
│ │ ├── project
│ │ ├── AbstractSimpleProjectSlicer.java
│ │ └── QuietPeriodSlicer.java
│ │ ├── timer
│ │ ├── AbstractTimerSliceSpec.java
│ │ ├── SCMTimerSliceStringSlicer.java
│ │ └── TimerSliceStringSlicer.java
│ │ ├── timestamper
│ │ └── TimestamperSlicer.java
│ │ └── tools
│ │ ├── AbstractToolSlicer.java
│ │ ├── AbstractToolSlicerSpec.java
│ │ ├── AntSlicer.java
│ │ ├── GradleSlicer.java
│ │ ├── GradleSlicerWrapper.java
│ │ ├── GroovySlicer.java
│ │ └── GroovySlicerWrapper.java
└── resources
│ ├── configurationslicing
│ ├── BooleanSlice
│ │ └── sliceconfig.jelly
│ ├── ConfigurationSlicing
│ │ ├── SliceExecutor
│ │ │ ├── changesummary.jelly
│ │ │ ├── index.jelly
│ │ │ ├── index_fr.properties
│ │ │ └── sidepanel-executor.jelly
│ │ ├── index.jelly
│ │ └── sidepanel.jelly
│ ├── Messages.properties
│ ├── Messages_it.properties
│ ├── ParametersStringSlice
│ │ └── sliceconfig.jelly
│ ├── UnorderedStringSlice
│ │ └── sliceconfig.jelly
│ └── tools
│ │ └── Messages.properties
│ └── index.jelly
├── spotbugs
└── excludesFilter.xml
└── test
├── it
├── build-timeout-1.10
│ ├── pom.xml
│ └── src
│ │ └── test
│ │ └── java
│ │ └── configurationslicing
│ │ └── BuildTimeoutSlicerTest.java
└── pom.xml
└── java
└── configurationslicing
├── ChronSplittingTest.java
├── ConfigurationSlicingTest.java
├── EmailSlicerTest.java
├── JdkSlicerTest.java
├── LogRotationSlicerTest.java
├── LogfilesizecheckerSlicerTest.java
├── PythonTest.java
├── ShellTest.java
├── TimerSliceStringSlicerTest.java
├── claim
└── ClaimSlicerTest.java
└── maven
└── MavenSnapshotBuildTriggerTest.java
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | * @jenkinsci/configurationslicing-plugin-developers
2 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuring-dependabot-version-updates
2 |
3 | version: 2
4 | updates:
5 | - package-ecosystem: maven
6 | directory: /
7 | schedule:
8 | interval: monthly
9 | - package-ecosystem: github-actions
10 | directory: /
11 | schedule:
12 | interval: monthly
13 |
--------------------------------------------------------------------------------
/.github/release-drafter.yml:
--------------------------------------------------------------------------------
1 | _extends: .github
2 |
--------------------------------------------------------------------------------
/.github/workflows/cd.yaml:
--------------------------------------------------------------------------------
1 | # Note: additional setup is required, see https://www.jenkins.io/redirect/continuous-delivery-of-plugins
2 |
3 | name: cd
4 | on:
5 | workflow_dispatch:
6 | check_run:
7 | types:
8 | - completed
9 |
10 | jobs:
11 | maven-cd:
12 | uses: jenkins-infra/github-reusable-workflows/.github/workflows/maven-cd.yml@v1
13 | secrets:
14 | MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }}
15 | MAVEN_TOKEN: ${{ secrets.MAVEN_TOKEN }}
16 |
--------------------------------------------------------------------------------
/.github/workflows/jenkins-security-scan.yml:
--------------------------------------------------------------------------------
1 | name: Jenkins Security Scan
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | pull_request:
8 | types: [ opened, synchronize, reopened ]
9 | workflow_dispatch:
10 |
11 | permissions:
12 | security-events: write
13 | contents: read
14 | actions: read
15 |
16 | jobs:
17 | security-scan:
18 | uses: jenkins-infra/jenkins-security-scan/.github/workflows/jenkins-security-scan.yaml@v2
19 | with:
20 | java-cache: 'maven' # Optionally enable use of a build dependency cache. Specify 'maven' or 'gradle' as appropriate.
21 | # java-version: 21 # Optionally specify what version of Java to set up for the build, or remove to use a recent default.
22 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .classpath
2 | .project
3 | .settings/
4 | target/
5 | work/
6 | .factortypath
7 | .idea
--------------------------------------------------------------------------------
/.gitpod.yml:
--------------------------------------------------------------------------------
1 | tasks:
2 | - init: mvn clean verify
3 |
4 | vscode:
5 | extensions:
6 | - bierner.markdown-preview-github-styles
7 | - vscjava.vscode-java-pack
8 | - redhat.java
9 | - vscjava.vscode-java-debug
10 | - vscjava.vscode-java-dependency
11 | - vscjava.vscode-java-test
12 | - vscjava.vscode-maven
13 |
--------------------------------------------------------------------------------
/.mvn/extensions.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | io.jenkins.tools.incrementals
4 | git-changelist-maven-extension
5 | 1.8
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.mvn/maven.config:
--------------------------------------------------------------------------------
1 | -Pconsume-incrementals
2 | -Pmight-produce-incrementals
3 | -Dchangelist.format=%d.v%s
4 |
--------------------------------------------------------------------------------
/Jenkinsfile:
--------------------------------------------------------------------------------
1 | /*
2 | See the documentation for more options:
3 | https://github.com/jenkins-infra/pipeline-library/
4 | */
5 | buildPlugin(
6 | useContainerAgent: true, // Set to `false` if you need to use Docker for containerized tests
7 | configurations: [
8 | [platform: 'linux', jdk: 21],
9 | [platform: 'windows', jdk: 17],
10 | ])
11 |
--------------------------------------------------------------------------------
/README.adoc:
--------------------------------------------------------------------------------
1 | [[configurationslicing-plugin]]
2 | = Configuration slicing plugin
3 | :toc: macro
4 | :toc-title:
5 | ifdef::env-github[]
6 | :tip-caption: :bulb:
7 | :note-caption: :information_source:
8 | :important-caption: :heavy_exclamation_mark:
9 | :caution-caption: :fire:
10 | :warning-caption: :warning:
11 | endif::[]
12 |
13 | image:https://img.shields.io/jenkins/plugin/v/configurationslicing.svg[Jenkins Plugin,link=https://plugins.jenkins.io/configurationslicing]
14 | image:https://img.shields.io/github/release/jenkinsci/configurationslicing-plugin.svg?label=release[GitHub release,link=https://github.com/jenkinsci/configurationslicing-plugin/releases/latest]
15 | image:https://ci.jenkins.io/job/Plugins/job/configurationslicing-plugin/job/master/badge/icon[Build Status,link=https://ci.jenkins.io/job/Plugins/job/configurationslicing-plugin/job/master/]
16 |
17 | toc::[]
18 |
19 | == Plugin information
20 |
21 | Perform mass configuration of select project properties, including
22 | email, timer, discard old builds, and Maven configuration.It has a
23 | framework to make it very easy to add a configuration page for a new
24 | property. At present, two types of data can be mass-configured:
25 | booleans and strings.
26 |
27 | The plugin shows up in Jenkins' UI on the Manage Jenkins page - seen
28 | here near the bottom of the page: +
29 | image:docs/images/manage_jenkins.png[]
30 |
31 | The main page of the configuration slicing plugin shows all the
32 | properties that can be sliced - select one and you are presented with a
33 | screen showing how that value is set across the entire Jenkins instance.
34 | Many properties on Jenkins projects are useful to set this way, but the
35 | configuration slicing plugin can handle properties on any collection,
36 | such as slaves, or builds of a project.
37 |
38 | *The following functions are supported*
39 |
40 | * https://plugins.jenkins.io/ant/[Ant version per project]
41 | * Block Build when Downstream Building Slicer (bool)
42 | * Block Build when Upstream Building Slicer (bool)
43 | * https://plugins.jenkins.io/build-timeout/[Build Timeout]
44 | (does not support all features)
45 | * Custom Workspace Slicer (Advanced Project Options > Use custom
46 | workspace)
47 | * Discard Old Builds Slicer - Days to keep artifacts
48 | * Discard Old Builds Slicer - Days to keep builds
49 | * Discard Old Builds Slicer - Max # of builds to keep
50 | * Discard Old Builds Slicer - Max # of builds to keep with artifacts
51 | * E-mail Notification
52 | * https://plugins.jenkins.io/email-ext/[Editable Email Notification]
53 | (https://issues.jenkins-ci.org/browse/JENKINS-11774[recipient list only])
54 | * https://plugins.jenkins.io/jython/[Execute Jython script]
55 | * https://plugins.jenkins.io/python/[Execute Python script]
56 | * Execute shell slicer
57 | * Execute Windows batch command slicer
58 | * https://plugins.jenkins.io/gradle/[Gradle version per project]
59 | * https://plugins.jenkins.io/groovy/[Groovy version per project]
60 | * JDK per project
61 | * Job Disabled Build Slicer (bool)
62 | * Job Disabled Build Slicer (String)
63 | * https://plugins.jenkins.io/PrioritySorter/[Job Priority Slicer]
64 | * https://plugins.jenkins.io/logfilesizechecker/[Build log file size checker Plugin]
65 | * Maven "top-level" targets
66 | * Maven Goals and Options (Maven project)
67 | * Maven Version (Maven Projects)
68 | * MAVEN_OPTS per Maven project
69 | * Parameters
70 | * Quiet period
71 | * SCM Timer Trigger Slicer
72 | * Tied Label Slicer
73 | * Timer Trigger Slicer
74 | * https://plugins.jenkins.io/timestamper/[Timestamper Slicer]
75 | * https://plugins.jenkins.io/configurationslicing/[Configuration Slicer]
76 |
77 | === Boolean slicing
78 |
79 | In the case of booleans, the plugin presents a set of checkboxes and
80 | names. The user can then adjust that property and save the changes.
81 |
82 | image::docs/images/job_disabled_slice.png[]
83 |
84 | === String slicing
85 |
86 | Most of the slicing uses a GUI much like the following example. You can
87 | move the Item Names (i.e. Jobs) around within the boxes on the right to
88 | change which jobs have different settings. You can also alter the
89 | values on the left to change how jobs are configured. There will always
90 | be a blank set of boxes added to the bottom to allow you to create a new
91 | setting when you need it. For most of these screens, a value of
92 | "(Disabled)" will indicate that those jobs do not use this configuration
93 | at all. To disable jobs (e.g. for SCM Polling), move those job names
94 | into that "(Disabled)" box.
95 |
96 | image::docs/images/scm_timer_slice.png[]
97 |
98 | === String slicing multiple values
99 |
100 | Some slicers allow you to configure multiple values at a time. In those
101 | cases, the values are separated by a comma, and follow the given
102 | example.
103 |
104 | image::docs/images/string_multiple_values.png[]
105 |
106 | === String slicing multiple Builders
107 |
108 | For the Windows batch builder, Shell builders, and "Top-level Maven
109 | targets", a job can have multiple builders of each type. To configure
110 | jobs like this, you will be presented with an index next to the jobs
111 | names like "MyJob[0]" and "MyJob[1]". The index indicates which
112 | instance of the builder you are configuring.
113 |
114 | image::docs/images/string_slicing_multiple_builders.png[]
115 |
116 | This is available under these links
117 |
118 | * Execute shell slicer
119 | * Execute Windows batch command slicer
120 | * Maven "top-level" targets
121 |
122 | === Configuring parameters across multiple jobs
123 |
124 | Job Parameters (aka "This build is parameterized") can be configured
125 | across multiple jobs at one time through the "Parameters" link. To
126 | indicate which parameter you are configuring, note the
127 | "JobName[ParameterName]" syntax.
128 |
129 | image:docs/images/parameters_slicing_items.png[]
130 | image:docs/images/parameters_slicing_string_parameters.png[]
131 |
132 | === Slicing by View
133 |
134 | If you have many jobs, it can be difficult to perform the configuration
135 | slicing. To make it more granular, you can configure just the jobs
136 | within one view. Assuming you have organized your Jenkins installation
137 | to have useful views, this will allow you to configure jobs at the right
138 | granularity. To use this feature, first select the type of configuration
139 | (in this example "Custom Workspace") and then you will be given a list
140 | of views to choose from. You don't have to choose a view, as the default
141 | is to show all jobs. If you select one of the views on the left, your
142 | list of jobs is filtered down to just the jobs in that view.
143 |
144 | image::docs/images/views.png[]
145 |
146 | === Email Notifications and https://plugins.jenkins.io/email-ext/[Editable Email Notifications] (from 1.41 on)
147 |
148 | When editing recipient lists, Email notifications are only completely
149 | disabled when set to (Disabled).
150 |
151 | Setting a empty recipient list leaves existing email notifications to
152 | committers (Checkbox "Notify individuals who broke the build") in place.
153 |
154 | [[changelog]]
155 | == Changelog in https://github.com/jenkinsci/configurationslicing-plugin/releases[GitHub Releases]
156 |
157 | Release notes have been recorded in https://github.com/jenkinsci/configurationslicing-plugin/releases[GitHub] since configuration slicing plugin 1.50.
158 | Prior release notes were recorded in the repository link:https://github.com/jenkinsci/configurationslicing-plugin/blob/1.52.1/CHANGELOG.adoc[change log].
159 |
--------------------------------------------------------------------------------
/docs/images/job_disabled_slice.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenkinsci/configurationslicing-plugin/af0b5cac0f65c43f0a9f1508c606f1bdb6a214fb/docs/images/job_disabled_slice.png
--------------------------------------------------------------------------------
/docs/images/manage_jenkins.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenkinsci/configurationslicing-plugin/af0b5cac0f65c43f0a9f1508c606f1bdb6a214fb/docs/images/manage_jenkins.png
--------------------------------------------------------------------------------
/docs/images/parameters_slicing_items.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenkinsci/configurationslicing-plugin/af0b5cac0f65c43f0a9f1508c606f1bdb6a214fb/docs/images/parameters_slicing_items.png
--------------------------------------------------------------------------------
/docs/images/parameters_slicing_string_parameters.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenkinsci/configurationslicing-plugin/af0b5cac0f65c43f0a9f1508c606f1bdb6a214fb/docs/images/parameters_slicing_string_parameters.png
--------------------------------------------------------------------------------
/docs/images/scm_timer_slice.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenkinsci/configurationslicing-plugin/af0b5cac0f65c43f0a9f1508c606f1bdb6a214fb/docs/images/scm_timer_slice.png
--------------------------------------------------------------------------------
/docs/images/string_multiple_values.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenkinsci/configurationslicing-plugin/af0b5cac0f65c43f0a9f1508c606f1bdb6a214fb/docs/images/string_multiple_values.png
--------------------------------------------------------------------------------
/docs/images/string_slicing_multiple_builders.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenkinsci/configurationslicing-plugin/af0b5cac0f65c43f0a9f1508c606f1bdb6a214fb/docs/images/string_slicing_multiple_builders.png
--------------------------------------------------------------------------------
/docs/images/views.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenkinsci/configurationslicing-plugin/af0b5cac0f65c43f0a9f1508c606f1bdb6a214fb/docs/images/views.png
--------------------------------------------------------------------------------
/src/main/java/configurationslicing/AbstractJob.java:
--------------------------------------------------------------------------------
1 | package configurationslicing;
2 |
3 | import hudson.model.AbstractProject;
4 | import hudson.model.Job;
5 | import hudson.triggers.Trigger;
6 | import hudson.triggers.TriggerDescriptor;
7 | import java.io.IOException;
8 | import org.jenkinsci.plugins.workflow.job.WorkflowJob;
9 |
10 | /**
11 | * Object that tries to be missing link between {@link AbstractProject}
12 | * and {@link WorkflowJob} for the purpose of this plugin.
13 | *
14 | * @author Michal Slusarczyk
15 | */
16 | public class AbstractJob {
17 |
18 | private Job item;
19 |
20 | public AbstractJob(Job item) {
21 | this.item = item;
22 | }
23 |
24 | public static AbstractJob fix(Job item) {
25 | return new AbstractJob(item);
26 | }
27 |
28 | public boolean isConcurrentBuilds() {
29 | if (item instanceof AbstractProject, ?> project) return project.isConcurrentBuild();
30 | if (item instanceof WorkflowJob job) return job.isConcurrentBuild();
31 |
32 | return true;
33 | }
34 |
35 | public void makeConcurrentBuilds(boolean value) throws IOException {
36 | if (item instanceof AbstractProject, ?> project) project.setConcurrentBuild(value);
37 | if (item instanceof WorkflowJob job) job.setConcurrentBuild(value);
38 |
39 | throw new IOException("Unsupported job type");
40 | }
41 |
42 | @SuppressWarnings("unchecked")
43 | public T getTrigger(Class clazz) {
44 | if (item instanceof AbstractProject, ?> project) return (T) project.getTrigger(clazz);
45 | if (item instanceof WorkflowJob job) {
46 | return getTrigger(job, clazz);
47 | }
48 |
49 | return null;
50 | }
51 |
52 | public void removeTrigger(TriggerDescriptor trigger) throws IOException {
53 | if (item instanceof AbstractProject, ?> project) project.removeTrigger(trigger);
54 | if (item instanceof WorkflowJob job) {
55 | removeTrigger(job, trigger);
56 | }
57 | }
58 |
59 | public void addTrigger(Trigger> trigger) throws IOException {
60 | if (item instanceof AbstractProject, ?> project) project.addTrigger(trigger);
61 | if (item instanceof WorkflowJob job) {
62 | job.addTrigger(trigger);
63 | }
64 | }
65 |
66 | private T getTrigger(WorkflowJob pipeline, Class clazz) {
67 | for (Trigger p : pipeline.getTriggersJobProperty().getTriggers()) {
68 | if (clazz.isInstance(p)) return clazz.cast(p);
69 | }
70 | return null;
71 | }
72 |
73 | private void removeTrigger(WorkflowJob pipeline, TriggerDescriptor triggerDescriptor) {
74 | Trigger> trigger = pipeline.getTriggers().get(triggerDescriptor);
75 | if (trigger != null) {
76 | pipeline.getTriggersJobProperty().removeTrigger(trigger);
77 | }
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/main/java/configurationslicing/BooleanSlice.java:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | */
4 | package configurationslicing;
5 |
6 | import configurationslicing.BooleanSlicer.BooleanSlicerSpec;
7 | import hudson.model.Descriptor.FormException;
8 | import java.util.ArrayList;
9 | import java.util.HashMap;
10 | import java.util.List;
11 | import java.util.Map;
12 | import net.sf.json.JSONObject;
13 | import org.kohsuke.stapler.DataBoundConstructor;
14 | import org.kohsuke.stapler.StaplerRequest2;
15 |
16 | public class BooleanSlice extends Slice {
17 | private Map nameToValue;
18 | private BooleanSlicer.BooleanSlicerSpec spec;
19 |
20 | public BooleanSlice(BooleanSlicerSpec spec, List list) {
21 | this(spec);
22 | for (ItemState istate : list) {
23 | add(istate.itemname, istate.checked);
24 | }
25 | }
26 |
27 | public BooleanSlice(BooleanSlicerSpec spec) {
28 | nameToValue = new HashMap();
29 | this.spec = spec;
30 | }
31 |
32 | public void add(String name, boolean value) {
33 | nameToValue.put(name, value);
34 | }
35 |
36 | public boolean exists(String name) {
37 | return nameToValue.get(name) != null;
38 | }
39 |
40 | public boolean get(String name) {
41 | Boolean object = nameToValue.get(name);
42 | if (object == null) {
43 | return false;
44 | }
45 | return object.booleanValue();
46 | }
47 |
48 | public BooleanSlicerSpec getSpec() {
49 | return spec;
50 | }
51 |
52 | public List getConfiguredItems() {
53 | List items = new ArrayList();
54 | List all = spec.getWorkDomain();
55 | for (I i : all) {
56 | String name = spec.getName(i);
57 | if (nameToValue.containsKey(name)) {
58 | items.add(i);
59 | }
60 | }
61 | return items;
62 | }
63 |
64 | @Override
65 | public Slice newInstance(StaplerRequest2 req, JSONObject formData) throws FormException {
66 | return new BooleanSlice(
67 | BooleanSlice.this.spec, req.bindJSONToList(ItemState.class, formData.get("itemstate")));
68 | }
69 |
70 | public static class ItemState {
71 | private String itemname;
72 | private boolean checked;
73 |
74 | @DataBoundConstructor
75 | public ItemState(String itemname, boolean checked) {
76 | this.itemname = itemname;
77 | this.checked = checked;
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/src/main/java/configurationslicing/BooleanSlicer.java:
--------------------------------------------------------------------------------
1 | package configurationslicing;
2 |
3 | import java.util.List;
4 |
5 | public class BooleanSlicer implements Slicer, I> {
6 | public static interface BooleanSlicerSpec {
7 | public abstract String getName();
8 |
9 | public abstract String getUrl();
10 |
11 | public abstract List getWorkDomain();
12 |
13 | public abstract boolean getValue(I item);
14 |
15 | public abstract String getName(I item);
16 |
17 | public abstract boolean setValue(I item, boolean value);
18 | }
19 |
20 | private BooleanSlicerSpec spec;
21 |
22 | public BooleanSlicer(BooleanSlicerSpec spec) {
23 | this.spec = spec;
24 | }
25 |
26 | public boolean isLoaded() {
27 | return true;
28 | }
29 |
30 | public BooleanSlice getInitialAccumulator() {
31 | return new BooleanSlice(spec);
32 | }
33 |
34 | public BooleanSlice accumulate(BooleanSlice t, I i) {
35 | t.add(spec.getName(i), spec.getValue(i));
36 | return t;
37 | }
38 |
39 | public boolean transform(BooleanSlice t, I i) {
40 | if (t.exists(spec.getName(i))) {
41 | return spec.setValue(i, t.get(spec.getName(i)));
42 | } else {
43 | return false;
44 | }
45 | }
46 |
47 | public String getName() {
48 | return spec.getName();
49 | }
50 |
51 | public String getUrl() {
52 | return spec.getUrl();
53 | }
54 |
55 | public List getWorkDomain() {
56 | return spec.getWorkDomain();
57 | }
58 |
59 | public int compareTo(Slicer, I> o) {
60 | return getName().compareToIgnoreCase(o.getName());
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/java/configurationslicing/ParametersStringSlice.java:
--------------------------------------------------------------------------------
1 | package configurationslicing;
2 |
3 | import hudson.model.Descriptor.FormException;
4 | import java.util.ArrayList;
5 | import java.util.List;
6 | import java.util.logging.Logger;
7 | import net.sf.json.JSONObject;
8 | import org.kohsuke.stapler.StaplerRequest2;
9 |
10 | public class ParametersStringSlice extends UnorderedStringSlice {
11 |
12 | static Logger LOG = Logger.getLogger("ParametersStringSlicing");
13 |
14 | public ParametersStringSlice(ParametersStringSliceSpec spec) {
15 | super(spec);
16 | }
17 |
18 | public ParametersStringSliceSpec getParametersSliceSpec() {
19 | return (ParametersStringSliceSpec) getSpec();
20 | }
21 |
22 | public UnorderedStringSlice getInitialAccumulator() {
23 | return new ParametersStringSlice(getParametersSliceSpec());
24 | }
25 |
26 | @Override
27 | public Slice newInstance(StaplerRequest2 req, JSONObject formData) throws FormException {
28 | /*
29 | {"itemNames":
30 | ["MD\n","Secure-A-1\nSecure-A-2\nSecure-B-1\nSecure-B-2\n",""],
31 | "paramValue":["3","false","(Disabled)","(Disabled)","",""]
32 | }
33 | */
34 | LOG.warning("formData." + formData);
35 | List paramValues = getStringList(formData, "paramValue");
36 | List joinedValues = new ArrayList();
37 | int paramNamesCount = getParametersSliceSpec().getParamNamesCount();
38 | for (int i = 0; i < paramValues.size(); i += paramNamesCount) {
39 | StringBuilder buf = new StringBuilder();
40 | for (int j = 0; j < paramNamesCount; j++) {
41 | if (j > 0) {
42 | buf.append(ParametersStringSliceSpec.DELIM);
43 | }
44 | String value = paramValues.get(i + j);
45 | buf.append(value);
46 | }
47 | joinedValues.add(buf.toString());
48 | }
49 |
50 | return new UnorderedStringSlice(getSpec(), joinedValues, getStringList(formData, "itemNames"));
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/java/configurationslicing/ParametersStringSliceSpec.java:
--------------------------------------------------------------------------------
1 | package configurationslicing;
2 |
3 | import configurationslicing.UnorderedStringSlicer.UnorderedStringSlicerSpec;
4 | import java.util.ArrayList;
5 | import java.util.Arrays;
6 | import java.util.List;
7 | import java.util.logging.Logger;
8 | import org.apache.commons.lang.StringUtils;
9 |
10 | public abstract class ParametersStringSliceSpec extends UnorderedStringSlicerSpec {
11 |
12 | static Logger LOG = Logger.getLogger("ParametersStringSlicing");
13 |
14 | static final String DELIM = "@@//@@";
15 |
16 | public abstract List getParamNames();
17 |
18 | public final boolean setValues(I item, List set) {
19 | String value = set.get(0);
20 | String[] split = split(value);
21 | List splitList = Arrays.asList(split);
22 | return doSetValues(item, splitList);
23 | }
24 |
25 | public abstract boolean doSetValues(I item, List set);
26 |
27 | public final List getValues(I item) {
28 | List values = doGetValues(item);
29 | String joinString = StringUtils.join(values, DELIM);
30 | List joined = new ArrayList();
31 | joined.add(joinString);
32 | return joined;
33 | }
34 |
35 | public final String getDefaultValueString() {
36 | String value = doGetDefaultValueString();
37 | int count = getParamNamesCount();
38 | StringBuilder buf = new StringBuilder();
39 | for (int i = 0; i < count; i++) {
40 | if (i > 0) {
41 | buf.append(DELIM);
42 | }
43 | buf.append(value);
44 | }
45 | return buf.toString();
46 | }
47 |
48 | public abstract String doGetDefaultValueString();
49 |
50 | public abstract List doGetValues(I item);
51 |
52 | public String getParamValue(String paramName, String configuredValue) {
53 | LOG.warning("paramName." + paramName);
54 | LOG.warning("configuredValue." + configuredValue);
55 | List names = getParamNames();
56 | String[] values = split(configuredValue);
57 | for (int i = 0; i < names.size(); i++) {
58 | if (names.get(i).equals(paramName)) {
59 | if (i >= values.length) {
60 | LOG.warning("return blank");
61 | return "";
62 | }
63 | LOG.warning("return." + values[i]);
64 | return values[i];
65 | }
66 | }
67 | return null;
68 | }
69 |
70 | private String[] split(String configuredValue) {
71 | return configuredValue.split(DELIM);
72 | }
73 |
74 | public int getParamNamesCount() {
75 | return getParamNames().size();
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/main/java/configurationslicing/ParametersStringSlicer.java:
--------------------------------------------------------------------------------
1 | package configurationslicing;
2 |
3 | public class ParametersStringSlicer extends UnorderedStringSlicer {
4 |
5 | public ParametersStringSlicer(UnorderedStringSlicerSpec spec) {
6 | super(spec);
7 | }
8 |
9 | @Override
10 | public UnorderedStringSlice getInitialAccumulator() {
11 | return new ParametersStringSlice((ParametersStringSliceSpec) getSpec());
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/configurationslicing/Slice.java:
--------------------------------------------------------------------------------
1 | package configurationslicing;
2 |
3 | import hudson.model.Descriptor.FormException;
4 | import net.sf.json.JSONObject;
5 | import org.kohsuke.stapler.StaplerRequest2;
6 |
7 | public abstract class Slice {
8 | public abstract Slice newInstance(StaplerRequest2 req, JSONObject formData) throws FormException;
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/java/configurationslicing/Slicer.java:
--------------------------------------------------------------------------------
1 | package configurationslicing;
2 |
3 | import hudson.ExtensionPoint;
4 | import java.util.List;
5 |
6 | public interface Slicer extends ExtensionPoint, Comparable> {
7 | public String getName();
8 |
9 | public String getUrl();
10 |
11 | public List getWorkDomain();
12 |
13 | public T getInitialAccumulator();
14 |
15 | public T accumulate(T t, I i);
16 |
17 | public boolean transform(T t, I i);
18 |
19 | /**
20 | * This method makes it easy to provide "optional" slicers that will only show up
21 | * if that plugin is installed.
22 | */
23 | boolean isLoaded();
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/configurationslicing/SlicerLoader.java:
--------------------------------------------------------------------------------
1 | package configurationslicing;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | * Handles the problem with Slicers that have class loading issues.
7 | * @author jacob
8 | */
9 | public abstract class SlicerLoader implements Slicer {
10 |
11 | protected abstract Slicer buildDelegateOnConstruction() throws Throwable;
12 |
13 | private Slicer delegate;
14 |
15 | public SlicerLoader() {
16 | try {
17 | delegate = buildDelegateOnConstruction();
18 | } catch (Throwable t) {
19 | delegate = null;
20 | }
21 | }
22 |
23 | public boolean isLoaded() {
24 | return delegate != null && delegate.isLoaded();
25 | }
26 |
27 | public Slicer getDelegate() {
28 | return delegate;
29 | }
30 |
31 | public int compareTo(Slicer, I> o) {
32 | return 0;
33 | }
34 |
35 | public String getName() {
36 | return null;
37 | }
38 |
39 | public String getUrl() {
40 | return null;
41 | }
42 |
43 | public List getWorkDomain() {
44 | return null;
45 | }
46 |
47 | public T getInitialAccumulator() {
48 | return null;
49 | }
50 |
51 | public UnorderedStringSlice accumulate(UnorderedStringSlice t, I i) {
52 | return null;
53 | }
54 |
55 | public boolean transform(UnorderedStringSlice t, I i) {
56 | return false;
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/main/java/configurationslicing/TopLevelItemSelector.java:
--------------------------------------------------------------------------------
1 | package configurationslicing;
2 |
3 | import hudson.model.Item;
4 | import hudson.model.TopLevelItem;
5 | import java.util.List;
6 | import jenkins.model.Jenkins;
7 | import org.apache.commons.collections.CollectionUtils;
8 | import org.apache.commons.collections.Predicate;
9 |
10 | /**
11 | * Helper class to provide all top level items configured in Jenkins, excluding other items
12 | * held in folders, such as maven modules
13 | *
14 | */
15 | public class TopLevelItemSelector {
16 |
17 | // private constructor since we don't expect this class to be instantiated
18 | private TopLevelItemSelector() {}
19 |
20 | /**
21 | * Provide all top level items configured in Jenkins
22 | * @param clazz the type to search the ItemGroup for
23 | * @return all items in the Jenkins ItemGroup tree which are of type TopLevelItem
24 | */
25 | @SuppressWarnings({"unchecked", "rawtypes"})
26 | public static List getAllTopLevelItems(Class clazz) {
27 | List list = Jenkins.get().getAllItems(clazz);
28 | CollectionUtils.filter(list, new Predicate() {
29 | public boolean evaluate(Object object) {
30 | // exclude MatrixConfiguration, MavenModule, etc
31 | return object instanceof TopLevelItem;
32 | }
33 | });
34 | return list;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/java/configurationslicing/UnorderedStringSlice.java:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | */
4 | package configurationslicing;
5 |
6 | import configurationslicing.UnorderedStringSlicer.UnorderedStringSlicerSpec;
7 | import hudson.model.Descriptor.FormException;
8 | import java.util.ArrayList;
9 | import java.util.Collection;
10 | import java.util.Collections;
11 | import java.util.HashMap;
12 | import java.util.HashSet;
13 | import java.util.List;
14 | import java.util.Map;
15 | import java.util.Set;
16 | import java.util.logging.Logger;
17 | import net.sf.json.JSONArray;
18 | import net.sf.json.JSONObject;
19 | import org.kohsuke.stapler.StaplerRequest2;
20 |
21 | public class UnorderedStringSlice extends Slice {
22 |
23 | private static final Logger LOGGER = Logger.getLogger(UnorderedStringSlice.class.getName());
24 | private Map> nameToValues;
25 |
26 | private Map> valueToNames;
27 | private UnorderedStringSlicer.UnorderedStringSlicerSpec spec;
28 |
29 | // reconstruct our datastructure after the user has made changes
30 | public UnorderedStringSlice(
31 | UnorderedStringSlicerSpec spec, List configurationValues, List itemNames) {
32 | this(spec);
33 | nameToValues = new HashMap>();
34 | for (int i = 0; i < configurationValues.size(); i++) {
35 | String value = configurationValues.get(i);
36 | if (spec.isValueTrimmed()) {
37 | value = value.trim();
38 | }
39 | String namesString = itemNames.get(i);
40 | String[] namesSplit = namesString.split("\\n");
41 | List workDomain = spec.getWorkDomain();
42 | for (String itemName : namesSplit) {
43 | itemName = itemName.trim();
44 | if (itemName.length() > 0) {
45 | int index = 0;
46 | int bracket = itemName.indexOf('[');
47 | if (bracket > 0) {
48 | String indexString = itemName.substring(bracket + 1, itemName.length() - 1);
49 | itemName = itemName.substring(0, bracket);
50 | I item = getItem(itemName, workDomain);
51 | index = spec.getValueIndex(item, indexString);
52 | }
53 | addLine(nameToValues, itemName, value, index);
54 | }
55 | }
56 | }
57 | }
58 |
59 | public I getItem(String name, List workDomain) {
60 | for (I item : workDomain) {
61 | if (name.equals(spec.getName(item))) {
62 | return item;
63 | }
64 | }
65 | throw new IllegalArgumentException(name);
66 | }
67 |
68 | public UnorderedStringSlice(UnorderedStringSlicerSpec spec) {
69 | valueToNames = new HashMap>();
70 | this.spec = spec;
71 | }
72 |
73 | public void add(String name, Collection values) {
74 | for (String value : values) {
75 | addLineWithSets(valueToNames, value, name);
76 | }
77 | }
78 |
79 | private static void addLineWithSets(Map> map, String s, String name) {
80 | if (null == s) {
81 | LOGGER.severe("found illegal line with null value for name: " + name);
82 | // do nothing
83 | return;
84 | }
85 | if (!map.containsKey(s)) {
86 | map.put(s, new HashSet());
87 | }
88 | Set list = map.get(s);
89 | list.add(name);
90 | }
91 |
92 | private static void addLine(Map> map, String s, String name, int index) {
93 | if (!map.containsKey(s)) {
94 | map.put(s, new ArrayList());
95 | }
96 | List list = map.get(s);
97 | while (list.size() < index + 1) {
98 | // add a blank - this could happen if one of the indexed names was simply removed
99 | list.add("");
100 | }
101 |
102 | list.set(index, name);
103 | }
104 |
105 | public List get(String name) {
106 | return nameToValues.get(name);
107 | }
108 |
109 | public UnorderedStringSlicerSpec getSpec() {
110 | return spec;
111 | }
112 |
113 | public List getConfiguredValues() {
114 | String defaultValueString = spec.getDefaultValueString();
115 | List list = new ArrayList(valueToNames.keySet());
116 | if (list.contains(defaultValueString)) {
117 | list.remove(defaultValueString);
118 | }
119 | Collections.sort(list, String.CASE_INSENSITIVE_ORDER);
120 |
121 | // add any common values
122 | List commonValues = spec.getCommonValueStrings();
123 | if (commonValues != null) {
124 | for (String commonValue : commonValues) {
125 | if (!list.contains(commonValue)) {
126 | list.add(commonValue);
127 | }
128 | }
129 | }
130 |
131 | // add the default as second to last
132 | if (defaultValueString != null) {
133 | list.add(defaultValueString);
134 | }
135 | // we need this so you can add new items
136 | if (spec.isBlankNeededForValues() && !list.contains("")) {
137 | list.add("");
138 | }
139 | return list;
140 | }
141 |
142 | public String getItemNamesString(String configurationString) {
143 | List list = getItemNames(configurationString);
144 | StringBuilder buf = new StringBuilder();
145 | for (String job : list) {
146 | buf.append(job);
147 | // add it afterwards so we have an extra linefeed in the gui to make cut and paste easier
148 | buf.append("\n");
149 | }
150 | return buf.toString();
151 | }
152 |
153 | public List getItemNames(String configurationString) {
154 | Set set = valueToNames.get(configurationString);
155 | if (set == null) {
156 | // particularly applies to the empty option
157 | return new ArrayList();
158 | }
159 | List list = new ArrayList(set);
160 | Collections.sort(list, String.CASE_INSENSITIVE_ORDER);
161 | return list;
162 | }
163 |
164 | @Override
165 | public Slice newInstance(StaplerRequest2 req, JSONObject formData) throws FormException {
166 | return new UnorderedStringSlice(
167 | UnorderedStringSlice.this.spec,
168 | getStringList(formData, "configValue"),
169 | getStringList(formData, "itemNames"));
170 | }
171 |
172 | List getStringList(JSONObject formData, String key) {
173 | JSONArray array = formData.getJSONArray(key);
174 | List list = new ArrayList();
175 | for (Object o : array) {
176 | list.add((String) o);
177 | }
178 | return list;
179 | }
180 | }
181 |
--------------------------------------------------------------------------------
/src/main/java/configurationslicing/UnorderedStringSlicer.java:
--------------------------------------------------------------------------------
1 | package configurationslicing;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | public class UnorderedStringSlicer implements Slicer, I> {
7 | public abstract static class UnorderedStringSlicerSpec {
8 | public abstract String getName();
9 |
10 | public abstract String getUrl();
11 |
12 | public abstract List getWorkDomain();
13 |
14 | public abstract List getValues(I item);
15 |
16 | public abstract String getName(I item);
17 |
18 | public abstract boolean setValues(I item, List set);
19 |
20 | public abstract String getDefaultValueString();
21 | /**
22 | * Useful when there are common configurations we want to always be available.
23 | */
24 | public List getCommonValueStrings() {
25 | return null;
26 | }
27 |
28 | public String getConfiguredValueDescription() {
29 | return Messages.configurationSlicing_configuredValueDescription();
30 | }
31 | /**
32 | * Allows you to use "MyJob[0]" to indicate separate values
33 | */
34 | public boolean isIndexUsed(int count) {
35 | return false;
36 | }
37 |
38 | public String getValueIndex(I item, int index) {
39 | return String.valueOf(index);
40 | }
41 |
42 | public int getValueIndex(I item, String indexName) {
43 | return Integer.parseInt(indexName);
44 | }
45 |
46 | public boolean isBlankNeededForValues() {
47 | return true;
48 | }
49 |
50 | /**
51 | * Some cases we do not want to trim the value. For example, in Parameters this causes issues.
52 | * This just requires the user to be more conscientious when configuring parameters.
53 | * @return true always
54 | */
55 | public boolean isValueTrimmed() {
56 | return true;
57 | }
58 | }
59 |
60 | private UnorderedStringSlicerSpec spec;
61 |
62 | public UnorderedStringSlicer(UnorderedStringSlicerSpec spec) {
63 | this.spec = spec;
64 | }
65 |
66 | public UnorderedStringSlice getInitialAccumulator() {
67 | return new UnorderedStringSlice(spec);
68 | }
69 |
70 | public UnorderedStringSlicerSpec getSpec() {
71 | return spec;
72 | }
73 | /**
74 | * Override this with different behavior if needed.
75 | */
76 | public boolean isLoaded() {
77 | try {
78 | loadPluginDependencyClass();
79 | return true;
80 | } catch (Throwable t) {
81 | return false;
82 | }
83 | }
84 |
85 | /**
86 | * Override this with the right class if you want to use the default isLoaded behavior.
87 | */
88 | public void loadPluginDependencyClass() {}
89 |
90 | public UnorderedStringSlice accumulate(UnorderedStringSlice t, I item) {
91 | String name = spec.getName(item);
92 | List values = spec.getValues(item);
93 | if (spec.isIndexUsed(values.size())) {
94 | for (int i = 0; i < values.size(); i++) {
95 | List oneValueList = new ArrayList();
96 | oneValueList.add(values.get(i));
97 | String valueIndex = spec.getValueIndex(item, i);
98 | String oneName = name + "[" + valueIndex + "]";
99 | t.add(oneName, oneValueList);
100 | }
101 | } else {
102 | t.add(spec.getName(item), values);
103 | }
104 | return t;
105 | }
106 |
107 | public boolean transform(UnorderedStringSlice t, I i) {
108 | List set = t.get(spec.getName(i));
109 | if (set == null) {
110 | return false;
111 | } else {
112 | return spec.setValues(i, set);
113 | }
114 | }
115 |
116 | public String getName() {
117 | return spec.getName();
118 | }
119 |
120 | public String getUrl() {
121 | return spec.getUrl();
122 | }
123 |
124 | public List getWorkDomain() {
125 | return spec.getWorkDomain();
126 | }
127 |
128 | public int compareTo(Slicer, I> o) {
129 | return getName().compareToIgnoreCase(o.getName());
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/src/main/java/configurationslicing/blockbuild/BlockBuildWhenDownstreamBuildingBoolSlicer.java:
--------------------------------------------------------------------------------
1 | package configurationslicing.blockbuild;
2 |
3 | import configurationslicing.BooleanSlicer;
4 | import configurationslicing.TopLevelItemSelector;
5 | import hudson.Extension;
6 | import hudson.model.AbstractProject;
7 | import java.io.IOException;
8 | import java.util.List;
9 |
10 | @Extension
11 | public class BlockBuildWhenDownstreamBuildingBoolSlicer extends BooleanSlicer {
12 | public BlockBuildWhenDownstreamBuildingBoolSlicer() {
13 | super(new BlockBuildWhenDownstreamBuildingSpec());
14 | }
15 |
16 | public static class BlockBuildWhenDownstreamBuildingSpec
17 | implements BooleanSlicer.BooleanSlicerSpec {
18 | public String getName() {
19 | return "Block Build when Downstream Building Slicer (bool)";
20 | }
21 |
22 | public String getName(AbstractProject item) {
23 | return item.getFullName();
24 | }
25 |
26 | public String getUrl() {
27 | return "blockBuildWhenDownstreamBuilding";
28 | }
29 |
30 | public boolean getValue(AbstractProject item) {
31 | return item.blockBuildWhenDownstreamBuilding();
32 | }
33 |
34 | public List getWorkDomain() {
35 | return TopLevelItemSelector.getAllTopLevelItems(AbstractProject.class);
36 | }
37 |
38 | public boolean setValue(AbstractProject item, boolean value) {
39 | boolean oldval = item.blockBuildWhenDownstreamBuilding();
40 | try {
41 | item.setBlockBuildWhenDownstreamBuilding(value);
42 | } catch (IOException e) {
43 | return false;
44 | }
45 | return oldval != value;
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/java/configurationslicing/blockbuild/BlockBuildWhenUpstreamBuildingBoolSlicer.java:
--------------------------------------------------------------------------------
1 | package configurationslicing.blockbuild;
2 |
3 | import configurationslicing.BooleanSlicer;
4 | import configurationslicing.TopLevelItemSelector;
5 | import hudson.Extension;
6 | import hudson.model.AbstractProject;
7 | import java.io.IOException;
8 | import java.util.List;
9 |
10 | @Extension
11 | public class BlockBuildWhenUpstreamBuildingBoolSlicer extends BooleanSlicer {
12 | public BlockBuildWhenUpstreamBuildingBoolSlicer() {
13 | super(new BlockBuildWhenUpstreamBuildingSpec());
14 | }
15 |
16 | public static class BlockBuildWhenUpstreamBuildingSpec implements BooleanSlicer.BooleanSlicerSpec {
17 | public String getName() {
18 | return "Block Build when Upstream Building Slicer (bool)";
19 | }
20 |
21 | public String getName(AbstractProject item) {
22 | return item.getFullName();
23 | }
24 |
25 | public String getUrl() {
26 | return "blockBuildWhenUpstreamBuilding";
27 | }
28 |
29 | public boolean getValue(AbstractProject item) {
30 | return item.blockBuildWhenUpstreamBuilding();
31 | }
32 |
33 | public List getWorkDomain() {
34 | return TopLevelItemSelector.getAllTopLevelItems(AbstractProject.class);
35 | }
36 |
37 | public boolean setValue(AbstractProject item, boolean value) {
38 | boolean oldval = item.blockBuildWhenUpstreamBuilding();
39 | try {
40 | item.setBlockBuildWhenUpstreamBuilding(value);
41 | } catch (IOException e) {
42 | return false;
43 | }
44 | return oldval != value;
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/java/configurationslicing/buildtimeout/BuildTimeoutSlicer.java:
--------------------------------------------------------------------------------
1 | package configurationslicing.buildtimeout;
2 |
3 | import com.thoughtworks.xstream.XStreamException;
4 | import configurationslicing.TopLevelItemSelector;
5 | import configurationslicing.UnorderedStringSlicer;
6 | import hudson.Extension;
7 | import hudson.model.BuildableItemWithBuildWrappers;
8 | import hudson.model.Descriptor;
9 | import hudson.plugins.build_timeout.BuildTimeoutWrapper;
10 | import hudson.tasks.BuildWrapper;
11 | import hudson.util.DescribableList;
12 | import hudson.util.XStream2;
13 | import java.io.IOException;
14 | import java.io.StringWriter;
15 | import java.util.ArrayList;
16 | import java.util.List;
17 | import java.util.logging.Logger;
18 | import org.apache.commons.lang.StringUtils;
19 |
20 | @Extension(optional = true)
21 | public class BuildTimeoutSlicer extends UnorderedStringSlicer {
22 | private static final Logger LOGGER = Logger.getLogger(BuildTimeoutSlicer.class.getName());
23 |
24 | public BuildTimeoutSlicer() {
25 | super(new BuildTimeoutSliceSpec());
26 | }
27 |
28 | @Override
29 | public boolean isLoaded() {
30 | try {
31 | BuildTimeoutWrapper.class.toString();
32 | return true;
33 | } catch (Throwable t) {
34 | return false;
35 | }
36 | }
37 |
38 | public static class BuildTimeoutSliceSpec extends UnorderedStringSlicerSpec {
39 |
40 | private static final String DISABLED = "(Disabled)";
41 |
42 | @Override
43 | public String getName() {
44 | return "Build Timeout";
45 | }
46 |
47 | @Override
48 | public String getUrl() {
49 | return "buildtimeout";
50 | }
51 |
52 | @Override
53 | public List getWorkDomain() {
54 | return TopLevelItemSelector.getAllTopLevelItems(BuildableItemWithBuildWrappers.class);
55 | }
56 |
57 | @Override
58 | public List getValues(BuildableItemWithBuildWrappers item) {
59 | XStream2 xs = getXStream();
60 | BuildableItemWithBuildWrappers bi = (BuildableItemWithBuildWrappers) item;
61 | DescribableList> wrappers = bi.getBuildWrappersList();
62 | List values = new ArrayList();
63 | BuildTimeoutWrapper wrapper = wrappers.get(BuildTimeoutWrapper.class);
64 | if (wrapper != null) {
65 | StringWriter sw = new StringWriter();
66 | xs.toXML(wrapper, sw);
67 | String value = sw.toString();
68 |
69 | values.add(value);
70 | }
71 | if (values.isEmpty()) {
72 | values.add(DISABLED);
73 | }
74 | return values;
75 | }
76 |
77 | private XStream2 getXStream() {
78 | XStream2 xs = new XStream2();
79 | addSimpleAlias(xs, "hudson.plugins.build_timeout.BuildTimeoutWrapper");
80 | addSimpleAlias(xs, "hudson.plugins.build_timeout.impl.AbsoluteTimeOutStrategy");
81 | addSimpleAlias(xs, "hudson.plugins.build_timeout.impl.DeadlineTimeOutStrategy");
82 | addSimpleAlias(xs, "hudson.plugins.build_timeout.impl.ElasticTimeOutStrategy");
83 | addSimpleAlias(xs, "hudson.plugins.build_timeout.impl.LikelyStuckTimeOutStrategy");
84 | addSimpleAlias(xs, "hudson.plugins.build_timeout.impl.NoActivityTimeOutStrategy");
85 | addSimpleAlias(xs, "hudson.plugins.build_timeout.operations.AbortOperation");
86 | addSimpleAlias(xs, "hudson.plugins.build_timeout.operations.BuildStepOperation");
87 | addSimpleAlias(xs, "hudson.plugins.build_timeout.operations.FailOperation");
88 | addSimpleAlias(xs, "hudson.plugins.build_timeout.operations.WriteDescriptionOperation");
89 | return xs;
90 | }
91 |
92 | private void addSimpleAlias(XStream2 xs, String className) {
93 | Class> type;
94 | try {
95 | type = Class.forName(className);
96 | String name = type.getSimpleName();
97 | xs.alias(name, type);
98 | } catch (ClassNotFoundException e) {
99 | LOGGER.info("Cannot load " + className);
100 | }
101 | }
102 |
103 | @Override
104 | public boolean setValues(BuildableItemWithBuildWrappers item, List set) {
105 | LOGGER.info("BuildTimeoutSlicer.setValues for item " + item.getName());
106 | XStream2 xs = getXStream();
107 | BuildableItemWithBuildWrappers bi = (BuildableItemWithBuildWrappers) item;
108 | DescribableList> wrappers = bi.getBuildWrappersList();
109 | boolean changed = false;
110 | BuildTimeoutWrapper wrapper = wrappers.get(BuildTimeoutWrapper.class);
111 | BuildTimeoutWrapper newWrapper = null;
112 | boolean delete = false;
113 | String line = set.iterator().next();
114 | if (DISABLED.equals(line) || StringUtils.isEmpty(line)) {
115 | delete = true;
116 | } else {
117 | try {
118 | Object o = xs.fromXML(line);
119 | if (o instanceof BuildTimeoutWrapper timeoutWrapper) {
120 | newWrapper = timeoutWrapper;
121 | changed = true;
122 | }
123 | } catch (XStreamException xse) {
124 | LOGGER.warning("XStreamException parsing XML for BuildTimeoutSlicer: " + xse.getMessage());
125 | changed = false;
126 | }
127 | }
128 |
129 | if (delete) {
130 | if (wrapper != null) {
131 | wrappers.remove(wrapper);
132 | changed = true;
133 | }
134 | } else if (newWrapper != null && changed) {
135 | try {
136 | wrappers.replace(newWrapper);
137 | } catch (IOException e) {
138 | LOGGER.warning("IOException Thrown replacing wrapper value");
139 | return false;
140 | }
141 | }
142 |
143 | return changed;
144 | }
145 |
146 | @Override
147 | public String getName(BuildableItemWithBuildWrappers item) {
148 | return item.getFullName();
149 | }
150 |
151 | @Override
152 | public String getDefaultValueString() {
153 | return DISABLED;
154 | }
155 |
156 | @Override
157 | public String getConfiguredValueDescription() {
158 | return "Build Timeout XML";
159 | }
160 | }
161 | }
162 |
--------------------------------------------------------------------------------
/src/main/java/configurationslicing/claim/ClaimSlicer.java:
--------------------------------------------------------------------------------
1 | package configurationslicing.claim;
2 |
3 | import configurationslicing.BooleanSlicer;
4 | import configurationslicing.TopLevelItemSelector;
5 | import hudson.Extension;
6 | import hudson.model.AbstractProject;
7 | import hudson.model.Descriptor;
8 | import hudson.plugins.claim.ClaimPublisher;
9 | import hudson.tasks.Publisher;
10 | import hudson.util.DescribableList;
11 | import java.util.List;
12 |
13 | @Extension(optional = true)
14 | public class ClaimSlicer extends BooleanSlicer {
15 | public ClaimSlicer() {
16 | super(new ClaimSpec());
17 | }
18 |
19 | public boolean isLoaded() {
20 | try {
21 | new ClaimPublisher();
22 | return true;
23 | } catch (Throwable t) {
24 | return false;
25 | }
26 | }
27 |
28 | public static class ClaimSpec implements BooleanSlicer.BooleanSlicerSpec {
29 | public String getName() {
30 | return "Claim Slicer";
31 | }
32 |
33 | public String getName(AbstractProject item) {
34 | return item.getFullName();
35 | }
36 |
37 | public String getUrl() {
38 | return "claim";
39 | }
40 |
41 | public boolean getValue(AbstractProject item) {
42 |
43 | DescribableList> publishersList = item.getPublishersList();
44 | ClaimPublisher claimPublisher = publishersList.get(ClaimPublisher.class);
45 | return claimPublisher != null;
46 | }
47 |
48 | public List getWorkDomain() {
49 | return TopLevelItemSelector.getAllTopLevelItems(AbstractProject.class);
50 | }
51 |
52 | public boolean setValue(AbstractProject item, boolean value) {
53 | boolean oldval = getValue(item);
54 | if (value == oldval) {
55 | return true;
56 | } else if (value == false) { // request to remove the publisher
57 | DescribableList> publishersList = item.getPublishersList();
58 | ClaimPublisher claimPublisher = publishersList.get(ClaimPublisher.class);
59 | publishersList.remove(claimPublisher);
60 | return true;
61 | } else { // request to add the publisher
62 | DescribableList> publishersList = item.getPublishersList();
63 | publishersList.add(new ClaimPublisher());
64 | return true;
65 | }
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/src/main/java/configurationslicing/concurrentbuilds/ConcurrentBuildsBoolSlicer.java:
--------------------------------------------------------------------------------
1 | package configurationslicing.concurrentbuilds;
2 |
3 | import static configurationslicing.AbstractJob.fix;
4 |
5 | import configurationslicing.BooleanSlicer;
6 | import configurationslicing.TopLevelItemSelector;
7 | import hudson.Extension;
8 | import hudson.model.Job;
9 | import java.io.IOException;
10 | import java.util.List;
11 |
12 | @Extension
13 | public class ConcurrentBuildsBoolSlicer extends BooleanSlicer {
14 | public ConcurrentBuildsBoolSlicer() {
15 | super(new ConcurrentBuildsBoolSpec());
16 | }
17 |
18 | public static class ConcurrentBuildsBoolSpec implements BooleanSlicerSpec {
19 | public String getName() {
20 | return "Job Concurrent Builds Slicer (Bool)";
21 | }
22 |
23 | public String getName(Job item) {
24 | return item.getFullName();
25 | }
26 |
27 | public String getUrl() {
28 | return "concurrentbuildsbool";
29 | }
30 |
31 | public boolean getValue(Job item) {
32 | return fix(item).isConcurrentBuilds();
33 | }
34 |
35 | public List getWorkDomain() {
36 | return TopLevelItemSelector.getAllTopLevelItems(Job.class);
37 | }
38 |
39 | public boolean setValue(Job item, boolean value) {
40 | boolean oldval = fix(item).isConcurrentBuilds();
41 | if (oldval != value) {
42 | try {
43 | fix(item).makeConcurrentBuilds(value);
44 | } catch (IOException e) {
45 | return false;
46 | }
47 | return true;
48 | }
49 | return false;
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/java/configurationslicing/concurrentbuilds/ConcurrentBuildsStringSlicer.java:
--------------------------------------------------------------------------------
1 | package configurationslicing.concurrentbuilds;
2 |
3 | import static configurationslicing.AbstractJob.fix;
4 |
5 | import configurationslicing.TopLevelItemSelector;
6 | import configurationslicing.UnorderedStringSlicer;
7 | import hudson.Extension;
8 | import hudson.model.Job;
9 | import java.io.IOException;
10 | import java.util.ArrayList;
11 | import java.util.List;
12 |
13 | @Extension
14 | public class ConcurrentBuildsStringSlicer extends UnorderedStringSlicer {
15 |
16 | public ConcurrentBuildsStringSlicer() {
17 | super(new ConcurrentBuildsStringSliceSpec());
18 | }
19 |
20 | public static class ConcurrentBuildsStringSliceSpec extends UnorderedStringSlicerSpec {
21 |
22 | public String getDefaultValueString() {
23 | return null;
24 | }
25 |
26 | public String getName() {
27 | return "Job Concurrent Build Slicer (String)";
28 | }
29 |
30 | public String getName(Job item) {
31 | return item.getFullName();
32 | }
33 |
34 | public String getUrl() {
35 | return "concurrentbuildsstring";
36 | }
37 |
38 | @Override
39 | public boolean isBlankNeededForValues() {
40 | return false;
41 | }
42 |
43 | @Override
44 | public List getCommonValueStrings() {
45 | List values = new ArrayList();
46 | values.add(String.valueOf(true));
47 | values.add(String.valueOf(false));
48 | return values;
49 | }
50 |
51 | public List getValues(Job job) {
52 | List values = new ArrayList();
53 | boolean isConcurrent = fix(job).isConcurrentBuilds();
54 | values.add(String.valueOf(isConcurrent));
55 | return values;
56 | }
57 |
58 | public List getWorkDomain() {
59 | return TopLevelItemSelector.getAllTopLevelItems(Job.class);
60 | }
61 |
62 | public boolean setValues(Job job, List set) {
63 | String value = set.iterator().next();
64 |
65 | boolean oldConcurrent = fix(job).isConcurrentBuilds();
66 | boolean newConcurrent = Boolean.parseBoolean(value);
67 |
68 | if (oldConcurrent != newConcurrent) {
69 | try {
70 | fix(job).makeConcurrentBuilds(newConcurrent);
71 | } catch (IOException e) {
72 | return false;
73 | }
74 | return true;
75 | } else {
76 | return false;
77 | }
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/src/main/java/configurationslicing/customworkspace/CustomWorkspaceStringSlicer.java:
--------------------------------------------------------------------------------
1 | package configurationslicing.customworkspace;
2 |
3 | import configurationslicing.project.AbstractSimpleProjectSlicer;
4 | import hudson.Extension;
5 | import hudson.model.AbstractProject;
6 | import hudson.model.FreeStyleProject;
7 | import java.io.IOException;
8 |
9 | /**
10 | * @author jacob_robertson
11 | */
12 | @Extension
13 | public class CustomWorkspaceStringSlicer extends AbstractSimpleProjectSlicer {
14 |
15 | public CustomWorkspaceStringSlicer() {
16 | super(new CustomWorkspaceStringSliceSpec());
17 | }
18 |
19 | public static class CustomWorkspaceStringSliceSpec
20 | extends AbstractSimpleProjectSlicer.AbstractSimpleProjectSliceSpec {
21 |
22 | public String getName() {
23 | return "Custom Workspace Slicer";
24 | }
25 |
26 | public String getUrl() {
27 | return "customworkspace";
28 | }
29 |
30 | @Override
31 | protected String getValue(AbstractProject item) {
32 | if (item instanceof FreeStyleProject project) {
33 | String ws = project.getCustomWorkspace();
34 | return ws;
35 | } else {
36 | return null;
37 | }
38 | }
39 |
40 | @Override
41 | protected void setValue(AbstractProject item, String value) throws IOException {
42 | if (item instanceof FreeStyleProject project) {
43 | project.setCustomWorkspace(value);
44 | }
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/java/configurationslicing/email/AbstractEmailSliceSpec.java:
--------------------------------------------------------------------------------
1 | package configurationslicing.email;
2 |
3 | import configurationslicing.TopLevelItemSelector;
4 | import configurationslicing.UnorderedStringSlicer.UnorderedStringSlicerSpec;
5 | import hudson.model.AbstractProject;
6 | import java.io.IOException;
7 | import java.util.ArrayList;
8 | import java.util.Arrays;
9 | import java.util.Collection;
10 | import java.util.List;
11 | import org.apache.commons.lang.StringUtils;
12 |
13 | public abstract class AbstractEmailSliceSpec extends UnorderedStringSlicerSpec {
14 |
15 | public static final String DISABLED = "(Disabled)";
16 | private static final String EMPTY = "";
17 |
18 | private String joinString;
19 | private String name;
20 | private String url;
21 |
22 | protected AbstractEmailSliceSpec(String joinString, String name, String url) {
23 | this.joinString = joinString;
24 | this.name = name;
25 | this.url = url;
26 | }
27 |
28 | public List getValues(AbstractProject project) {
29 | ProjectHandler handler = getProjectHandler(project);
30 | String recipients = handler.getRecipients(project);
31 | recipients = normalize(recipients, "\n");
32 | if (recipients == null) {
33 | if (handler.sendToIndividuals(project)) {
34 | recipients = EMPTY;
35 | } else {
36 | recipients = DISABLED;
37 | }
38 | }
39 | List values = new ArrayList();
40 | values.add(recipients);
41 | return values;
42 | }
43 |
44 | public boolean setValues(AbstractProject project, List set) {
45 | String newEmail = join(set);
46 |
47 | // only regard explicit (disabled) [regardless of case]
48 | boolean disabled = (newEmail == null) ? false : (DISABLED.toLowerCase().equals(newEmail.toLowerCase()));
49 | boolean saved = false;
50 | ProjectHandler handler = getProjectHandler(project);
51 |
52 | try {
53 | if (disabled) {
54 | boolean oneSaved = handler.removeMailer(project);
55 | if (oneSaved) {
56 | saved = true;
57 | }
58 | } else {
59 | boolean oneSaved = handler.addMailer(project);
60 | if (oneSaved) {
61 | saved = true;
62 | }
63 | boolean wasSet = handler.setRecipients(project, newEmail);
64 | if (wasSet) {
65 | try {
66 | project.save();
67 | } catch (IOException e) {
68 | throw new RuntimeException(e);
69 | }
70 | saved = true;
71 | }
72 | }
73 | return saved;
74 | } catch (IOException e) {
75 | return false;
76 | }
77 | }
78 |
79 | public String normalize(String value, String joinString) {
80 | value = StringUtils.trimToNull(value);
81 | if (value == null) {
82 | return null;
83 | }
84 | // don't lowercase the templates
85 | if (value.startsWith("$")) {
86 | return value;
87 | }
88 | String[] split = value.split("[;,\\s]");
89 | Arrays.sort(split, String.CASE_INSENSITIVE_ORDER);
90 |
91 | StringBuffer buf = new StringBuffer();
92 | for (String s : split) {
93 | if (buf.length() > 0) {
94 | buf.append(joinString);
95 | }
96 | // TODO this strategy isn't really fair to admins that keep the proper-case names.
97 | // In a future release, I would like a more complex strategy to preserve the case wherever possible.
98 | s = s.toLowerCase();
99 | buf.append(s);
100 | }
101 | return buf.toString();
102 | }
103 |
104 | public String join(Collection set) {
105 | if (set.isEmpty()) {
106 | return null;
107 | }
108 | String value = set.iterator().next();
109 | if (!DISABLED.equals(value)) {
110 | value = normalize(value, joinString);
111 | }
112 | return value;
113 | }
114 |
115 | public List getWorkDomain() {
116 | return TopLevelItemSelector.getAllTopLevelItems(AbstractProject.class);
117 | }
118 |
119 | protected abstract ProjectHandler getProjectHandler(AbstractProject project);
120 |
121 | public String getDefaultValueString() {
122 | return DISABLED;
123 | }
124 |
125 | public String getName() {
126 | return name;
127 | }
128 |
129 | public String getName(AbstractProject item) {
130 | return item.getFullName();
131 | }
132 |
133 | public String getUrl() {
134 | return url;
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/src/main/java/configurationslicing/email/CoreEmailSlicer.java:
--------------------------------------------------------------------------------
1 | package configurationslicing.email;
2 |
3 | import configurationslicing.UnorderedStringSlicer;
4 | import hudson.Extension;
5 | import hudson.maven.MavenModuleSet;
6 | import hudson.maven.MavenReporter;
7 | import hudson.maven.reporters.MavenMailer;
8 | import hudson.model.AbstractProject;
9 | import hudson.model.Descriptor;
10 | import hudson.tasks.Mailer;
11 | import hudson.tasks.Publisher;
12 | import hudson.util.DescribableList;
13 | import java.io.IOException;
14 | import jenkins.model.Jenkins;
15 | import org.apache.commons.lang.StringUtils;
16 |
17 | @Extension(optional = true)
18 | public class CoreEmailSlicer extends UnorderedStringSlicer {
19 |
20 | public CoreEmailSlicer() {
21 | super(new CoreEmailSliceSpec());
22 | }
23 |
24 | @SuppressWarnings("unchecked")
25 | public static class CoreEmailSliceSpec extends AbstractEmailSliceSpec {
26 |
27 | public CoreEmailSliceSpec() {
28 | super(" ", "E-mail Notification", "mailer");
29 | }
30 |
31 | @Override
32 | protected ProjectHandler getProjectHandler(AbstractProject project) {
33 | if (project instanceof MavenModuleSet) {
34 | return MavenEmailProjectHandler.INSTANCE;
35 | } else {
36 | return CoreEmailProjectHandler.INSTANCE;
37 | }
38 | }
39 | }
40 |
41 | @SuppressWarnings("unchecked")
42 | private static class CoreEmailProjectHandler implements ProjectHandler {
43 | public static final CoreEmailProjectHandler INSTANCE = new CoreEmailProjectHandler();
44 |
45 | public String getRecipients(AbstractProject project) {
46 | Mailer mailer = getMailer(project);
47 | if (mailer != null) {
48 | return mailer.recipients;
49 | } else {
50 | return null;
51 | }
52 | }
53 |
54 | private Mailer getMailer(AbstractProject project) {
55 | DescribableList> publishers = project.getPublishersList();
56 | Descriptor descriptor = Jenkins.get().getDescriptor(Mailer.class);
57 | Publisher emailPublisher = publishers.get(descriptor);
58 | return (Mailer) emailPublisher;
59 | }
60 |
61 | public boolean setRecipients(AbstractProject project, String value) {
62 | Mailer mailer = getMailer(project);
63 | if (!StringUtils.equals(value, mailer.recipients)) {
64 | mailer.recipients = value;
65 | return true;
66 | } else {
67 | return false;
68 | }
69 | }
70 |
71 | public boolean addMailer(AbstractProject project) throws IOException {
72 | Mailer mailer = getMailer(project);
73 | if (mailer == null) {
74 | DescribableList> publishers = project.getPublishersList();
75 | publishers.add(new Mailer());
76 | return true;
77 | } else {
78 | return false;
79 | }
80 | }
81 |
82 | public boolean removeMailer(AbstractProject project) throws IOException {
83 | Mailer mailer = getMailer(project);
84 | if (mailer != null) {
85 | DescribableList> publishers = project.getPublishersList();
86 | publishers.remove(mailer);
87 | return true;
88 | } else {
89 | return false;
90 | }
91 | }
92 |
93 | public boolean sendToIndividuals(AbstractProject project) {
94 | Mailer mailer = getMailer(project);
95 | if (mailer != null) {
96 | return mailer.sendToIndividuals;
97 | } else {
98 | return false;
99 | }
100 | }
101 | }
102 |
103 | @SuppressWarnings("unchecked")
104 | private static class MavenEmailProjectHandler implements ProjectHandler {
105 | public static final MavenEmailProjectHandler INSTANCE = new MavenEmailProjectHandler();
106 |
107 | public String getRecipients(AbstractProject project) {
108 | MavenMailer mailer = getMailer(project);
109 | if (mailer != null) {
110 | return mailer.recipients;
111 | } else {
112 | return null;
113 | }
114 | }
115 |
116 | private MavenMailer getMailer(AbstractProject project) {
117 | MavenModuleSet mavenProject = (MavenModuleSet) project;
118 | DescribableList> reporters = mavenProject.getReporters();
119 | Descriptor descriptor = Jenkins.get().getDescriptor(MavenMailer.class);
120 | MavenReporter emailReporter = reporters.get(descriptor);
121 | return (MavenMailer) emailReporter;
122 | }
123 |
124 | public boolean setRecipients(AbstractProject project, String value) {
125 | MavenMailer mailer = getMailer(project);
126 | if (!StringUtils.equals(value, mailer.recipients)) {
127 | mailer.recipients = value;
128 | return true;
129 | } else {
130 | return false;
131 | }
132 | }
133 |
134 | public boolean addMailer(AbstractProject project) throws IOException {
135 | MavenMailer mailer = getMailer(project);
136 | if (mailer == null) {
137 | MavenModuleSet mavenProject = (MavenModuleSet) project;
138 | DescribableList> reporters = mavenProject.getReporters();
139 | reporters.add(new MavenMailer());
140 | return true;
141 | } else {
142 | return false;
143 | }
144 | }
145 |
146 | public boolean removeMailer(AbstractProject project) throws IOException {
147 | MavenMailer mailer = getMailer(project);
148 | if (mailer != null) {
149 | MavenModuleSet mavenProject = (MavenModuleSet) project;
150 | DescribableList> reporters = mavenProject.getReporters();
151 | reporters.remove(mailer);
152 | return true;
153 | } else {
154 | return false;
155 | }
156 | }
157 |
158 | public boolean sendToIndividuals(AbstractProject project) {
159 | MavenMailer mailer = getMailer(project);
160 | if (mailer != null) {
161 | return mailer.sendToIndividuals;
162 | } else {
163 | return false;
164 | }
165 | }
166 | }
167 | }
168 |
--------------------------------------------------------------------------------
/src/main/java/configurationslicing/email/ExtEmailSlicer.java:
--------------------------------------------------------------------------------
1 | package configurationslicing.email;
2 |
3 | import configurationslicing.UnorderedStringSlicer;
4 | import hudson.Extension;
5 | import hudson.model.AbstractProject;
6 | import hudson.model.Descriptor;
7 | import hudson.plugins.emailext.EmailType;
8 | import hudson.plugins.emailext.ExtendedEmailPublisher;
9 | import hudson.plugins.emailext.plugins.EmailTrigger;
10 | import hudson.plugins.emailext.plugins.trigger.FailureTrigger;
11 | import hudson.tasks.Publisher;
12 | import hudson.util.DescribableList;
13 | import java.io.IOException;
14 | import java.util.ArrayList;
15 | import java.util.List;
16 | import jenkins.model.Jenkins;
17 | import org.apache.commons.lang.StringUtils;
18 |
19 | @Extension(optional = true)
20 | public class ExtEmailSlicer extends UnorderedStringSlicer {
21 |
22 | public ExtEmailSlicer() {
23 | super(new ExtEmailSliceSpec());
24 | }
25 |
26 | public boolean isLoaded() {
27 | try {
28 | new EmailType();
29 | return true;
30 | } catch (Throwable t) {
31 | return false;
32 | }
33 | }
34 |
35 | @SuppressWarnings("unchecked")
36 | public static class ExtEmailSliceSpec extends AbstractEmailSliceSpec implements ProjectHandler {
37 |
38 | public ExtEmailSliceSpec() {
39 | super(",", "Editable Email Notification", "emailext");
40 | }
41 |
42 | @Override
43 | protected ProjectHandler getProjectHandler(AbstractProject project) {
44 | return this;
45 | }
46 |
47 | @Override
48 | public List getCommonValueStrings() {
49 | List values = new ArrayList();
50 | values.add("$DEFAULT_RECIPIENTS");
51 | return values;
52 | }
53 |
54 | public String getRecipients(AbstractProject project) {
55 | ExtendedEmailPublisher mailer = getMailer(project);
56 | if (mailer != null) {
57 | return mailer.recipientList;
58 | } else {
59 | return null;
60 | }
61 | }
62 |
63 | private ExtendedEmailPublisher getMailer(AbstractProject project) {
64 | DescribableList> publishers = project.getPublishersList();
65 | Descriptor descriptor = Jenkins.get().getDescriptor(ExtendedEmailPublisher.class);
66 | Publisher emailPublisher = publishers.get(descriptor);
67 | return (ExtendedEmailPublisher) emailPublisher;
68 | }
69 |
70 | public boolean setRecipients(AbstractProject project, String value) {
71 | ExtendedEmailPublisher mailer = getMailer(project);
72 | if (!StringUtils.equals(value, mailer.recipientList)) {
73 | mailer.recipientList = value;
74 | return true;
75 | } else {
76 | return false;
77 | }
78 | }
79 |
80 | public boolean addMailer(AbstractProject project) throws IOException {
81 | ExtendedEmailPublisher mailer = getMailer(project);
82 | if (mailer == null) {
83 | DescribableList> publishers = project.getPublishersList();
84 | ExtendedEmailPublisher publisher = new ExtendedEmailPublisher();
85 | FailureTrigger trigger = FailureTrigger.createDefault();
86 | EmailType email = new EmailType();
87 | email.setSendToDevelopers(true);
88 | email.setSendToRecipientList(true);
89 | trigger.setEmail(email);
90 | publisher.getConfiguredTriggers().add(trigger);
91 |
92 | // there is no way to get this text from the plugin itself
93 | publisher.defaultContent = "$DEFAULT_CONTENT";
94 | publisher.defaultSubject = "$DEFAULT_SUBJECT";
95 |
96 | publishers.add(publisher);
97 | return true;
98 | } else {
99 | return false;
100 | }
101 | }
102 |
103 | public boolean removeMailer(AbstractProject project) throws IOException {
104 | ExtendedEmailPublisher mailer = getMailer(project);
105 | if (mailer != null) {
106 | DescribableList> publishers = project.getPublishersList();
107 | publishers.remove(mailer);
108 | return true;
109 | } else {
110 | return false;
111 | }
112 | }
113 |
114 | /**
115 | * not yet implemented for ExtendedEmailPublisher
116 | */
117 | public boolean sendToIndividuals(AbstractProject project) {
118 | boolean result = false;
119 | ExtendedEmailPublisher mailer = getMailer(project);
120 | if (mailer != null) {
121 | for (EmailTrigger trigger : mailer.getConfiguredTriggers()) {
122 | if (trigger.getEmail().getSendToDevelopers()) {
123 | result = true;
124 | break;
125 | }
126 | }
127 | }
128 | return result;
129 | }
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/src/main/java/configurationslicing/email/ProjectHandler.java:
--------------------------------------------------------------------------------
1 | package configurationslicing.email;
2 |
3 | import hudson.model.AbstractProject;
4 | import java.io.IOException;
5 |
6 | public interface ProjectHandler {
7 |
8 | String getRecipients(AbstractProject project);
9 |
10 | boolean removeMailer(AbstractProject project) throws IOException;
11 |
12 | boolean addMailer(AbstractProject project) throws IOException;
13 |
14 | boolean setRecipients(AbstractProject project, String recipients) throws IOException;
15 |
16 | boolean sendToIndividuals(AbstractProject project);
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/configurationslicing/executeshell/AbstractBuildCommandSlicer.java:
--------------------------------------------------------------------------------
1 | package configurationslicing.executeshell;
2 |
3 | import configurationslicing.UnorderedStringSlicer;
4 | import hudson.matrix.MatrixProject;
5 | import hudson.model.AbstractProject;
6 | import hudson.model.Descriptor;
7 | import hudson.model.Project;
8 | import hudson.tasks.Builder;
9 | import hudson.util.DescribableList;
10 | import java.util.ArrayList;
11 | import java.util.List;
12 | import jenkins.model.Jenkins;
13 |
14 | /**
15 | * @author Jacob Robertson
16 | */
17 | public abstract class AbstractBuildCommandSlicer extends UnorderedStringSlicer {
18 |
19 | public AbstractBuildCommandSlicer(AbstractBuildCommandSliceSpec spec) {
20 | super(spec);
21 | }
22 |
23 | public abstract static class AbstractBuildCommandSliceSpec
24 | extends UnorderedStringSlicerSpec {
25 |
26 | public static final String NOTHING = "(nothing)";
27 |
28 | public String getDefaultValueString() {
29 | return NOTHING;
30 | }
31 |
32 | public String getName(AbstractProject item) {
33 | return item.getFullName();
34 | }
35 |
36 | @Override
37 | public boolean isIndexUsed(int count) {
38 | return count > 1;
39 | }
40 |
41 | public List getValues(AbstractProject item) {
42 | List content = new ArrayList();
43 | DescribableList> buildersList = getBuildersList(item);
44 |
45 | List builders = getConcreteBuildersList(buildersList);
46 | for (B builder : builders) {
47 | content.add(getCommand(builder));
48 | }
49 | if (content.isEmpty()) {
50 | content.add(NOTHING);
51 | }
52 |
53 | return content;
54 | }
55 |
56 | public abstract List getConcreteBuildersList(DescribableList> buildersList);
57 |
58 | public abstract String getCommand(B builder);
59 |
60 | public abstract B[] createBuilderArray(int len);
61 |
62 | public abstract B createBuilder(String command, List existingBuilders, B oldBuilder);
63 |
64 | @SuppressWarnings("unchecked")
65 | public List getWorkDomain() {
66 | List list = new ArrayList();
67 | List temp = Jenkins.get().getAllItems(AbstractProject.class);
68 | for (AbstractProject p : temp) {
69 | if (p instanceof Project || p instanceof MatrixProject) {
70 | list.add(p);
71 | }
72 | }
73 | return list;
74 | }
75 |
76 | @SuppressWarnings("unchecked")
77 | public static DescribableList> getBuildersList(AbstractProject item) {
78 | if (item instanceof Project, ?> project) {
79 | return project.getBuildersList();
80 | } else if (item instanceof MatrixProject project) {
81 | return project.getBuildersList();
82 | } else {
83 | return null;
84 | }
85 | }
86 |
87 | public boolean setValues(AbstractProject item, List list) {
88 | DescribableList> buildersList = getBuildersList(item);
89 | List builders = getConcreteBuildersList(buildersList);
90 |
91 | int maxLen = Math.max(list.size(), builders.size());
92 | B[] oldBuilders = createBuilderArray(maxLen);
93 | B[] newBuilders = createBuilderArray(maxLen);
94 |
95 | for (int i = 0; i < builders.size(); i++) {
96 | oldBuilders[i] = builders.get(i);
97 | }
98 |
99 | for (int i = 0; i < list.size(); i++) {
100 | String command = list.get(i);
101 | if (!command.equals(NOTHING) && !command.equals("")) {
102 | if (oldBuilders[i] != null && getCommand(oldBuilders[i]).equals(command)) {
103 | newBuilders[i] = oldBuilders[i];
104 | } else {
105 | newBuilders[i] = createBuilder(command, builders, oldBuilders[i]);
106 | }
107 | }
108 | }
109 |
110 | // perform any replacements
111 | for (int i = 0; i < maxLen; i++) {
112 | if (oldBuilders[i] != null && newBuilders[i] != null && oldBuilders[i] != newBuilders[i]) {
113 | replaceBuilder(buildersList, oldBuilders[i], newBuilders[i]);
114 | }
115 | }
116 |
117 | // add any new ones (should always add to the end, but might not if the original command was empty)
118 | for (int i = 0; i < maxLen; i++) {
119 | if (oldBuilders[i] == null && newBuilders[i] != null) {
120 | buildersList.add(newBuilders[i]);
121 | }
122 | }
123 |
124 | // delete any old ones
125 | for (int i = 0; i < maxLen; i++) {
126 | if (oldBuilders[i] != null && newBuilders[i] == null) {
127 | // the remove command will persist the project
128 | buildersList.remove(oldBuilders[i]);
129 | }
130 | }
131 |
132 | return true;
133 | }
134 |
135 | /**
136 | * If we do other builders, publishers, etc - this should be the pattern to use.
137 | */
138 | public static boolean replaceBuilder(
139 | DescribableList> builders, Builder oldBuilder, Builder newBuilder) {
140 | List newList = new ArrayList(builders.toList());
141 | for (int i = 0; i < newList.size(); i++) {
142 | Builder b = newList.get(i);
143 | if (b == oldBuilder) {
144 | newList.set(i, newBuilder);
145 | }
146 | }
147 | try {
148 | builders.replaceBy(newList);
149 | return true;
150 | } catch (java.io.IOException e) {
151 | System.err.println("IOException Thrown replacing builder list");
152 | return false;
153 | }
154 | }
155 | }
156 | }
157 |
--------------------------------------------------------------------------------
/src/main/java/configurationslicing/executeshell/ExecuteJythonSlicer.java:
--------------------------------------------------------------------------------
1 | package configurationslicing.executeshell;
2 |
3 | import hudson.model.Descriptor;
4 | import hudson.tasks.Builder;
5 | import hudson.util.DescribableList;
6 | import java.util.List;
7 | import net.sf.json.JSONObject;
8 | import org.jvnet.hudson.plugins.Jython;
9 | import org.kohsuke.stapler.StaplerRequest2;
10 |
11 | /**
12 | * Slicer for the jython builder
13 | *
14 | * @author Jacob Robertson
15 | */
16 | public class ExecuteJythonSlicer extends AbstractBuildCommandSlicer {
17 |
18 | public ExecuteJythonSlicer() {
19 | super(new ExecuteJythonSliceSpec());
20 | }
21 |
22 | @Override
23 | public void loadPluginDependencyClass() {
24 | // this is just to demonstrate that the Jython plugin is loaded
25 | Jython.class.getClass();
26 | }
27 |
28 | private static final Jython.DescriptorImpl JYTHON_DESCRIPTOR = new Jython.DescriptorImpl();
29 |
30 | public static class ExecuteJythonSliceSpec extends AbstractBuildCommandSliceSpec {
31 |
32 | public String getName() {
33 | return "Execute Jython script";
34 | }
35 |
36 | public String getUrl() {
37 | return "executejythonslice";
38 | }
39 |
40 | @Override
41 | public Jython createBuilder(String command, List existingBuilders, Jython oldBuilder) {
42 | // this is an unfortunate workaround that is necessary due to the Jython constructor being private
43 | StaplerRequest2 req = null;
44 | JSONObject formData = new JSONObject();
45 | formData.put("jython", command);
46 | try {
47 | return (Jython) JYTHON_DESCRIPTOR.newInstance(req, formData);
48 | } catch (Descriptor.FormException e) {
49 | throw new RuntimeException(e);
50 | }
51 | }
52 |
53 | @Override
54 | public Jython[] createBuilderArray(int len) {
55 | return new Jython[len];
56 | }
57 |
58 | @Override
59 | public String getCommand(Jython builder) {
60 | return builder.getCommand();
61 | }
62 |
63 | @Override
64 | public List getConcreteBuildersList(DescribableList> buildersList) {
65 | return buildersList.getAll(Jython.class);
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/src/main/java/configurationslicing/executeshell/ExecuteJythonSlicerWrapper.java:
--------------------------------------------------------------------------------
1 | package configurationslicing.executeshell;
2 |
3 | import configurationslicing.Slicer;
4 | import configurationslicing.SlicerLoader;
5 | import configurationslicing.UnorderedStringSlice;
6 | import hudson.Extension;
7 | import hudson.model.AbstractProject;
8 |
9 | @Extension
10 | public class ExecuteJythonSlicerWrapper extends SlicerLoader, AbstractProject> {
11 | protected Slicer, AbstractProject> buildDelegateOnConstruction()
12 | throws Throwable {
13 | return new ExecuteJythonSlicer();
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/configurationslicing/executeshell/ExecutePythonSlicer.java:
--------------------------------------------------------------------------------
1 | package configurationslicing.executeshell;
2 |
3 | import hudson.model.Descriptor;
4 | import hudson.model.Descriptor.FormException;
5 | import hudson.plugins.python.Python;
6 | import hudson.tasks.Builder;
7 | import hudson.util.DescribableList;
8 | import java.lang.reflect.Constructor;
9 | import java.lang.reflect.Modifier;
10 | import java.util.List;
11 | import net.sf.json.JSONObject;
12 | import org.kohsuke.stapler.StaplerRequest2;
13 |
14 | /**
15 | * Slicer for the python builder
16 | *
17 | * @author Jacob Robertson
18 | */
19 | public class ExecutePythonSlicer extends AbstractBuildCommandSlicer {
20 |
21 | public ExecutePythonSlicer() {
22 | super(new ExecutePythonSliceSpec());
23 | }
24 |
25 | @Override
26 | public void loadPluginDependencyClass() {
27 | // this is just to demonstrate that the Python plugin is loaded
28 | Python.class.getClass();
29 | }
30 |
31 | private static final Python.DescriptorImpl PYTHON_DESCRIPTOR = new Python.DescriptorImpl();
32 |
33 | public static class ExecutePythonSliceSpec extends AbstractBuildCommandSliceSpec {
34 |
35 | public String getName() {
36 | return "Execute Python script";
37 | }
38 |
39 | public String getUrl() {
40 | return "executepythonslice";
41 | }
42 |
43 | @SuppressWarnings({"rawtypes"})
44 | @Override
45 | public Python createBuilder(String command, List existingBuilders, Python oldBuilder) {
46 | Python python = null;
47 | Constructor[] cons = Python.class.getConstructors();
48 | if (cons.length > 0) {
49 | try {
50 | if (!Modifier.isPublic(cons[0].getModifiers())) {
51 | cons[0].setAccessible(true);
52 | }
53 | python = (Python) cons[0].newInstance(command);
54 | } catch (Exception e) {
55 | // we'll try another way to get it
56 | python = null;
57 | }
58 | }
59 | if (python == null) {
60 | // this is an unfortunate workaround that is necessary due to the Python constructor being private in
61 | // certain versions
62 | StaplerRequest2 req = null;
63 | JSONObject formData = new JSONObject();
64 | formData.put("python", command);
65 | try {
66 | python = (Python) PYTHON_DESCRIPTOR.newInstance(req, formData);
67 | } catch (FormException e) {
68 | python = null;
69 | }
70 | }
71 | return python;
72 | }
73 |
74 | @Override
75 | public Python[] createBuilderArray(int len) {
76 | return new Python[len];
77 | }
78 |
79 | @Override
80 | public String getCommand(Python builder) {
81 | return builder.getCommand();
82 | }
83 |
84 | @Override
85 | public List getConcreteBuildersList(DescribableList> buildersList) {
86 | return buildersList.getAll(Python.class);
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/src/main/java/configurationslicing/executeshell/ExecutePythonSlicerWrapper.java:
--------------------------------------------------------------------------------
1 | package configurationslicing.executeshell;
2 |
3 | import configurationslicing.Slicer;
4 | import configurationslicing.SlicerLoader;
5 | import configurationslicing.UnorderedStringSlice;
6 | import hudson.Extension;
7 | import hudson.model.AbstractProject;
8 |
9 | @Extension
10 | public class ExecutePythonSlicerWrapper extends SlicerLoader, AbstractProject> {
11 | protected Slicer, AbstractProject> buildDelegateOnConstruction()
12 | throws Throwable {
13 | return new ExecutePythonSlicer();
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/configurationslicing/executeshell/ExecuteShellSlicer.java:
--------------------------------------------------------------------------------
1 | package configurationslicing.executeshell;
2 |
3 | import hudson.Extension;
4 | import hudson.model.Descriptor;
5 | import hudson.tasks.Builder;
6 | import hudson.tasks.Shell;
7 | import hudson.util.DescribableList;
8 | import java.util.List;
9 |
10 | /**
11 | * Slicer for the shell builder
12 | */
13 | @Extension
14 | public class ExecuteShellSlicer extends AbstractBuildCommandSlicer {
15 |
16 | public ExecuteShellSlicer() {
17 | super(new ExecuteShellSliceSpec());
18 | }
19 |
20 | public static class ExecuteShellSliceSpec extends AbstractBuildCommandSliceSpec {
21 |
22 | public String getName() {
23 | return "Execute shell slicer";
24 | }
25 |
26 | public String getUrl() {
27 | return "executeshellslicestring";
28 | }
29 |
30 | @Override
31 | public Shell createBuilder(String command, List existingBuilders, Shell oldBuilder) {
32 | return new Shell(command);
33 | }
34 |
35 | @Override
36 | public Shell[] createBuilderArray(int len) {
37 | return new Shell[len];
38 | }
39 |
40 | @Override
41 | public String getCommand(Shell builder) {
42 | return builder.getCommand();
43 | }
44 |
45 | @Override
46 | public List getConcreteBuildersList(DescribableList> buildersList) {
47 | return buildersList.getAll(Shell.class);
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/java/configurationslicing/executeshell/ExecuteWindowsBatchSlicer.java:
--------------------------------------------------------------------------------
1 | package configurationslicing.executeshell;
2 |
3 | import hudson.Extension;
4 | import hudson.model.Descriptor;
5 | import hudson.tasks.BatchFile;
6 | import hudson.tasks.Builder;
7 | import hudson.util.DescribableList;
8 | import java.util.List;
9 |
10 | /**
11 | * Slicer for the windows batch builder
12 | *
13 | * @author Jacob Robertson
14 | */
15 | @Extension
16 | public class ExecuteWindowsBatchSlicer extends AbstractBuildCommandSlicer {
17 |
18 | public ExecuteWindowsBatchSlicer() {
19 | super(new ExecuteWindowsBatchSliceSpec());
20 | }
21 |
22 | public static class ExecuteWindowsBatchSliceSpec extends AbstractBuildCommandSliceSpec {
23 |
24 | public String getName() {
25 | return "Execute Windows batch command slicer";
26 | }
27 |
28 | public String getUrl() {
29 | return "windowsbatchslice";
30 | }
31 |
32 | @Override
33 | public BatchFile createBuilder(String command, List existingBuilders, BatchFile oldBuilder) {
34 | return new BatchFile(command);
35 | }
36 |
37 | @Override
38 | public BatchFile[] createBuilderArray(int len) {
39 | return new BatchFile[len];
40 | }
41 |
42 | @Override
43 | public String getCommand(BatchFile builder) {
44 | return builder.getCommand();
45 | }
46 |
47 | @Override
48 | public List getConcreteBuildersList(DescribableList> buildersList) {
49 | return buildersList.getAll(BatchFile.class);
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/java/configurationslicing/executeshell/MavenTargetsSlicer.java:
--------------------------------------------------------------------------------
1 | package configurationslicing.executeshell;
2 |
3 | import hudson.Extension;
4 | import hudson.maven.MavenModuleSet;
5 | import hudson.model.Descriptor;
6 | import hudson.tasks.Builder;
7 | import hudson.tasks.Maven;
8 | import hudson.tasks.Maven.MavenInstallation;
9 | import hudson.util.DescribableList;
10 | import java.util.List;
11 |
12 | /**
13 | * @author Jacob Robertson
14 | */
15 | @Extension
16 | public class MavenTargetsSlicer extends AbstractBuildCommandSlicer {
17 |
18 | public MavenTargetsSlicer() {
19 | super(new MavenTargetsSliceSpec());
20 | }
21 |
22 | @Override
23 | public void loadPluginDependencyClass() {
24 | MavenModuleSet.class.getClass();
25 | }
26 |
27 | public static class MavenTargetsSliceSpec extends AbstractBuildCommandSliceSpec {
28 |
29 | private static final String DEFAULT_MAVEN = "(Default)";
30 |
31 | public String getName() {
32 | return "Maven top-level targets";
33 | }
34 |
35 | public String getUrl() {
36 | return "maventopleveltargets";
37 | }
38 |
39 | @Override
40 | public Maven createBuilder(String command, List existingBuilders, Maven oldBuilder) {
41 | if (oldBuilder != null) {
42 | MavenInstallation mavenInstall = oldBuilder.getMaven();
43 | String mavenName = mavenInstall == null ? null : mavenInstall.getName();
44 | return new Maven(
45 | command,
46 | mavenName,
47 | oldBuilder.pom,
48 | oldBuilder.properties,
49 | oldBuilder.jvmOptions,
50 | oldBuilder.usePrivateRepository,
51 | oldBuilder.getSettings(),
52 | oldBuilder.getGlobalSettings());
53 | } else {
54 | // if the job already has another maven command, use the right version of maven
55 | String mavenName = DEFAULT_MAVEN;
56 | for (Maven maven : existingBuilders) {
57 | MavenInstallation install = maven.getMaven();
58 | if (install != null) {
59 | mavenName = install.getName();
60 | break;
61 | }
62 | }
63 | return new Maven(command, mavenName);
64 | }
65 | }
66 |
67 | @Override
68 | public Maven[] createBuilderArray(int len) {
69 | return new Maven[len];
70 | }
71 |
72 | @Override
73 | public String getCommand(Maven builder) {
74 | return builder.getTargets();
75 | }
76 |
77 | @Override
78 | public List getConcreteBuildersList(DescribableList> buildersList) {
79 | return buildersList.getAll(Maven.class);
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/main/java/configurationslicing/jdk/JdkSlicer.java:
--------------------------------------------------------------------------------
1 | package configurationslicing.jdk;
2 |
3 | import configurationslicing.TopLevelItemSelector;
4 | import configurationslicing.UnorderedStringSlicer;
5 | import hudson.Extension;
6 | import hudson.model.AbstractProject;
7 | import hudson.model.JDK;
8 | import java.io.IOException;
9 | import java.util.ArrayList;
10 | import java.util.List;
11 | import jenkins.model.Jenkins;
12 | import org.apache.commons.lang.ObjectUtils;
13 | import org.apache.commons.lang.StringUtils;
14 |
15 | @Extension
16 | public class JdkSlicer extends UnorderedStringSlicer {
17 |
18 | public JdkSlicer() {
19 | super(new JdkSlicerSpec());
20 | }
21 |
22 | public static class JdkSlicerSpec extends UnorderedStringSlicerSpec {
23 | private static final String DEFAULT = "(Default)";
24 |
25 | public String getDefaultValueString() {
26 | return DEFAULT;
27 | }
28 |
29 | public String getName() {
30 | return "JDK per project";
31 | }
32 |
33 | public String getName(AbstractProject item) {
34 | return item.getFullName();
35 | }
36 |
37 | public String getUrl() {
38 | return "projectjdk";
39 | }
40 |
41 | public List getValues(AbstractProject item) {
42 | List ret = new ArrayList();
43 | JDK jdk = item.getJDK();
44 | String name = jdk == null ? DEFAULT : jdk.getName();
45 | ret.add(name);
46 | return ret;
47 | }
48 |
49 | public List getWorkDomain() {
50 | return TopLevelItemSelector.getAllTopLevelItems(AbstractProject.class);
51 | }
52 |
53 | public boolean setValues(AbstractProject item, List set) {
54 | if (set.size() == 0) return false;
55 | Jenkins hudson = Jenkins.get();
56 | JDK jdk = null;
57 | for (String val : set) {
58 | jdk = hudson.getJDK(val);
59 | if (jdk != null) break;
60 | }
61 | JDK oldJdk = item.getJDK();
62 | if (!equals(oldJdk, jdk)) {
63 | try {
64 | if (jdk != null) {
65 | item.setJDK(jdk);
66 | }
67 | return true;
68 | } catch (IOException e) {
69 | e.printStackTrace();
70 | return false;
71 | }
72 | } else {
73 | return false;
74 | }
75 | }
76 |
77 | public static boolean equals(JDK j1, JDK j2) {
78 | if (ObjectUtils.equals(j1, j2)) {
79 | return true;
80 | }
81 | if (j1 == null || j2 == null) {
82 | return false;
83 | }
84 | if (!StringUtils.equals(j1.getHome(), j2.getHome())) {
85 | return false;
86 | }
87 | if (!StringUtils.equals(j1.getName(), j2.getName())) {
88 | return false;
89 | }
90 | return true;
91 | }
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/src/main/java/configurationslicing/jobdisabled/JobDisabledBoolSlicer.java:
--------------------------------------------------------------------------------
1 | package configurationslicing.jobdisabled;
2 |
3 | import configurationslicing.BooleanSlicer;
4 | import configurationslicing.TopLevelItemSelector;
5 | import hudson.Extension;
6 | import hudson.model.AbstractProject;
7 | import java.io.IOException;
8 | import java.util.List;
9 |
10 | @Extension
11 | public class JobDisabledBoolSlicer extends BooleanSlicer {
12 | public JobDisabledBoolSlicer() {
13 | super(new JobDisabledSpec());
14 | }
15 |
16 | public static class JobDisabledSpec implements BooleanSlicer.BooleanSlicerSpec {
17 | public String getName() {
18 | return "Job Disabled Build Slicer (bool)";
19 | }
20 |
21 | public String getName(AbstractProject item) {
22 | return item.getFullName();
23 | }
24 |
25 | public String getUrl() {
26 | return "jobdisabledbool";
27 | }
28 |
29 | public boolean getValue(AbstractProject item) {
30 | return item.isDisabled();
31 | }
32 |
33 | public List getWorkDomain() {
34 | return TopLevelItemSelector.getAllTopLevelItems(AbstractProject.class);
35 | }
36 |
37 | public boolean setValue(AbstractProject item, boolean value) {
38 | boolean oldval = item.isDisabled();
39 | try {
40 | item.makeDisabled(value);
41 | } catch (IOException e) {
42 | return false;
43 | }
44 | return oldval != value;
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/java/configurationslicing/jobdisabled/JobDisabledStringSlicer.java:
--------------------------------------------------------------------------------
1 | package configurationslicing.jobdisabled;
2 |
3 | import configurationslicing.TopLevelItemSelector;
4 | import configurationslicing.UnorderedStringSlicer;
5 | import hudson.Extension;
6 | import hudson.model.AbstractProject;
7 | import java.io.IOException;
8 | import java.util.ArrayList;
9 | import java.util.List;
10 |
11 | /**
12 | * @author jacob_robertson
13 | */
14 | @Extension
15 | public class JobDisabledStringSlicer extends UnorderedStringSlicer {
16 |
17 | public JobDisabledStringSlicer() {
18 | super(new JobDisabledStringSliceSpec());
19 | }
20 |
21 | public static class JobDisabledStringSliceSpec extends UnorderedStringSlicerSpec