├── .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 { 22 | 23 | public String getDefaultValueString() { 24 | return null; 25 | } 26 | 27 | public String getName() { 28 | return "Job Disabled Build Slicer (String)"; 29 | } 30 | 31 | public String getName(AbstractProject item) { 32 | return item.getFullName(); 33 | } 34 | 35 | public String getUrl() { 36 | return "jobdisabledstring"; 37 | } 38 | 39 | @Override 40 | public boolean isBlankNeededForValues() { 41 | return false; 42 | } 43 | 44 | @Override 45 | public List getCommonValueStrings() { 46 | List values = new ArrayList(); 47 | values.add(String.valueOf(true)); 48 | values.add(String.valueOf(false)); 49 | return values; 50 | } 51 | 52 | public List getValues(AbstractProject job) { 53 | List values = new ArrayList(); 54 | boolean isDisabled = job.isDisabled(); 55 | values.add(String.valueOf(isDisabled)); 56 | return values; 57 | } 58 | 59 | public List getWorkDomain() { 60 | return TopLevelItemSelector.getAllTopLevelItems(AbstractProject.class); 61 | } 62 | 63 | public boolean setValues(AbstractProject job, List set) { 64 | String value = set.iterator().next(); 65 | 66 | boolean oldDisabled = job.isDisabled(); 67 | boolean newDisabled = Boolean.parseBoolean(value); 68 | 69 | if (oldDisabled != newDisabled) { 70 | try { 71 | job.makeDisabled(newDisabled); 72 | } catch (IOException e) { 73 | return false; 74 | } 75 | return true; 76 | } else { 77 | return false; 78 | } 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/configurationslicing/label/LabelSlicer.java: -------------------------------------------------------------------------------- 1 | package configurationslicing.label; 2 | 3 | import configurationslicing.TopLevelItemSelector; 4 | import configurationslicing.UnorderedStringSlicer; 5 | import hudson.Extension; 6 | import hudson.model.AbstractProject; 7 | import hudson.model.Label; 8 | import java.io.IOException; 9 | import java.util.Collections; 10 | import java.util.List; 11 | import jenkins.model.Jenkins; 12 | 13 | @Extension 14 | public class LabelSlicer extends UnorderedStringSlicer { 15 | 16 | public LabelSlicer() { 17 | super(new LabelSliceSpec()); 18 | } 19 | 20 | public static class LabelSliceSpec extends UnorderedStringSlicerSpec { 21 | 22 | private static final String ROAMING = "(Roaming)"; 23 | 24 | public String getDefaultValueString() { 25 | return ROAMING; 26 | } 27 | 28 | public String getName() { 29 | return "Tied Label Slicer"; 30 | } 31 | 32 | public String getName(AbstractProject item) { 33 | return item.getFullName(); 34 | } 35 | 36 | public String getUrl() { 37 | return "labelslicestring"; 38 | } 39 | 40 | public List getValues(AbstractProject item) { 41 | Label label = item.getAssignedLabel(); 42 | String labelName = label == null ? ROAMING : label.getName(); 43 | return Collections.singletonList(labelName); 44 | } 45 | 46 | public List getWorkDomain() { 47 | return TopLevelItemSelector.getAllTopLevelItems(AbstractProject.class); 48 | } 49 | 50 | public boolean setValues(AbstractProject item, List set) { 51 | // can only have one label at a time. do nothing if a node has zero 52 | // or multiple labels 53 | if (set.isEmpty() || set.size() > 1) return false; 54 | 55 | Label label = null; 56 | String labelName = set.iterator().next(); 57 | if (ROAMING.equals(labelName)) { 58 | label = null; 59 | } else { 60 | label = Jenkins.get().getLabel(labelName); 61 | if (label == null) return false; 62 | } 63 | try { 64 | item.setAssignedLabel(label); 65 | return true; 66 | } catch (IOException e) { 67 | return false; 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/configurationslicing/logfilesizechecker/LogfilesizecheckerSlicer.java: -------------------------------------------------------------------------------- 1 | package configurationslicing.logfilesizechecker; 2 | 3 | import configurationslicing.TopLevelItemSelector; 4 | import configurationslicing.UnorderedStringSlicer; 5 | import hudson.Extension; 6 | import hudson.model.BuildableItemWithBuildWrappers; 7 | import hudson.model.Descriptor; 8 | import hudson.plugins.logfilesizechecker.LogfilesizecheckerWrapper; 9 | import hudson.tasks.BuildWrapper; 10 | import hudson.util.DescribableList; 11 | import java.io.IOException; 12 | import java.lang.reflect.Constructor; 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | import org.apache.commons.lang.StringUtils; 16 | 17 | /** 18 | * Slicing the configuration of the Logfilesizechecker plugin. 19 | * @author kstutz 20 | */ 21 | @Extension(optional = true) 22 | public class LogfilesizecheckerSlicer extends UnorderedStringSlicer { 23 | 24 | public LogfilesizecheckerSlicer() { 25 | super(new LogfilesizeSliceSpec()); 26 | } 27 | 28 | @Override 29 | public boolean isLoaded() { 30 | try { 31 | LogfilesizeSliceSpec.newLogfilesizecheckerWrapper(0, false, false); 32 | return true; 33 | } catch (Throwable t) { 34 | return false; 35 | } 36 | } 37 | 38 | public static class LogfilesizeSliceSpec extends UnorderedStringSlicerSpec { 39 | private static final String DISABLED = "(Disabled)"; 40 | private static final String SEPARATOR = ","; 41 | 42 | @Override 43 | public String getName() { 44 | return "Log File Size"; 45 | } 46 | 47 | @Override 48 | public String getUrl() { 49 | return "logfilesize"; 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 | final BuildableItemWithBuildWrappers bi = (BuildableItemWithBuildWrappers) item; 60 | final DescribableList> wrappers = bi.getBuildWrappersList(); 61 | final List values = new ArrayList(); 62 | final LogfilesizecheckerWrapper wrapper = wrappers.get(LogfilesizecheckerWrapper.class); 63 | if (wrapper != null) { 64 | final String value = wrapper.setOwn + SEPARATOR + wrapper.maxLogSize + SEPARATOR + wrapper.failBuild; 65 | values.add(value); 66 | } 67 | if (values.isEmpty()) { 68 | values.add(DISABLED); 69 | } 70 | return values; 71 | } 72 | 73 | @Override 74 | public boolean setValues(BuildableItemWithBuildWrappers item, List set) { 75 | final BuildableItemWithBuildWrappers bi = (BuildableItemWithBuildWrappers) item; 76 | final DescribableList> wrappers = bi.getBuildWrappersList(); 77 | boolean changed = false; 78 | LogfilesizecheckerWrapper wrapper = wrappers.get(LogfilesizecheckerWrapper.class); 79 | 80 | boolean delete = false; 81 | boolean newSetOwn = false; 82 | boolean newFail = false; 83 | int newMaxLogSize = 0; 84 | final String line = set.iterator().next(); 85 | if (DISABLED.equals(line) || StringUtils.isEmpty(line)) { 86 | delete = true; 87 | } else { 88 | final String[] split = line.split(SEPARATOR); 89 | newSetOwn = Boolean.parseBoolean(split[0]); 90 | newMaxLogSize = Integer.parseInt(split[1]); 91 | newFail = Boolean.parseBoolean(split[2]); 92 | } 93 | 94 | if (wrapper != null) { 95 | final boolean oldSetOwn = wrapper.setOwn; 96 | final int oldMaxLogSize = wrapper.maxLogSize; 97 | final boolean oldFail = wrapper.failBuild; 98 | if (newMaxLogSize != oldMaxLogSize || newFail != oldFail || newSetOwn != oldSetOwn) { 99 | changed = true; 100 | } 101 | } else { 102 | changed = true; 103 | } 104 | 105 | if (delete) { 106 | if (wrapper != null) { 107 | wrappers.remove(wrapper); 108 | } 109 | } else if (changed) { 110 | try { 111 | wrapper = newLogfilesizecheckerWrapper(newMaxLogSize, newFail, newSetOwn); 112 | wrappers.replace(wrapper); 113 | } catch (IOException e) { 114 | System.err.println("IOException thrown replacing wrapper value"); 115 | return false; 116 | } 117 | } 118 | 119 | return changed; 120 | } 121 | 122 | @Override 123 | public String getName(BuildableItemWithBuildWrappers item) { 124 | return item.getName(); 125 | } 126 | 127 | @Override 128 | public String getDefaultValueString() { 129 | return DISABLED; 130 | } 131 | 132 | @Override 133 | public String getConfiguredValueDescription() { 134 | return "SetOwn, MaxLogSize in MB, Fail (e.g. true,7,false)" 135 | + "
  • Set your own maximum log size instead of using default (true/false)
  • " 136 | + "
  • Maximum log size (int) (use 0 to use global default)
  • " 137 | + "
  • Mark build as failed instead of aborted (true/false)
"; 138 | } 139 | 140 | public static LogfilesizecheckerWrapper newLogfilesizecheckerWrapper( 141 | int maxLogSize, boolean failBuild, boolean setOwn) { 142 | final Class cls = LogfilesizecheckerWrapper.class; 143 | final Class[] types = new Class[] {Integer.TYPE, Boolean.TYPE, Boolean.TYPE}; 144 | Constructor cons; 145 | try { 146 | cons = cls.getDeclaredConstructor(types); 147 | } catch (Exception e) { 148 | throw new UnsupportedClassVersionError( 149 | "Cannot find a version of LogfilesizecheckerWrapper constructor that can be used:" 150 | + e.getMessage()); 151 | } 152 | 153 | Object[] args = null; 154 | if (cons != null) { 155 | args = new Object[] {maxLogSize, failBuild, setOwn}; 156 | } 157 | 158 | LogfilesizecheckerWrapper wrapper; 159 | try { 160 | wrapper = (LogfilesizecheckerWrapper) cons.newInstance(args); 161 | } catch (Exception e) { 162 | throw new UnsupportedClassVersionError( 163 | "Cannot find a version of LogfilesizecheckerWrapper constructor that can be used:" 164 | + e.getMessage()); 165 | } 166 | return wrapper; 167 | } 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /src/main/java/configurationslicing/logstash/LogStashSlicer.java: -------------------------------------------------------------------------------- 1 | package configurationslicing.logstash; 2 | 3 | import configurationslicing.BooleanSlicer; 4 | import configurationslicing.TopLevelItemSelector; 5 | import hudson.Extension; 6 | import hudson.Util; 7 | import hudson.maven.MavenModuleSet; 8 | import hudson.model.AbstractProject; 9 | import hudson.model.Descriptor; 10 | import hudson.model.Project; 11 | import hudson.tasks.BuildWrapper; 12 | import hudson.util.DescribableList; 13 | import java.util.List; 14 | import jenkins.plugins.logstash.LogstashBuildWrapper; 15 | 16 | @Extension(optional = true) 17 | public class LogStashSlicer extends BooleanSlicer { 18 | public LogStashSlicer() { 19 | super(new LogstashSpec()); 20 | } 21 | 22 | public static class LogstashSpec implements BooleanSlicer.BooleanSlicerSpec { 23 | 24 | @Override 25 | public String getName() { 26 | return "Logstash Slicer"; 27 | } 28 | 29 | @Override 30 | public String getUrl() { 31 | return "logstash"; 32 | } 33 | 34 | public List getWorkDomain() { 35 | return TopLevelItemSelector.getAllTopLevelItems(AbstractProject.class); 36 | } 37 | 38 | public boolean getValue(AbstractProject item) { 39 | DescribableList> buildWrappersList = getBuildWrappers(item); 40 | if (buildWrappersList == null) { 41 | return false; 42 | } 43 | return !buildWrappersList.getAll(LogstashBuildWrapper.class).isEmpty(); 44 | } 45 | 46 | private DescribableList> getBuildWrappers(AbstractProject item) { 47 | if (item instanceof Project project) { 48 | return project.getBuildWrappersList(); 49 | } else if (item instanceof MavenModuleSet set) { 50 | return set.getBuildWrappersList(); 51 | } else { 52 | return null; 53 | } 54 | } 55 | 56 | @Override 57 | public String getName(AbstractProject item) { 58 | return item.getName(); 59 | } 60 | 61 | @Override 62 | public boolean setValue(AbstractProject item, boolean value) { 63 | LogstashBuildWrapper logstashWrapper = new LogstashBuildWrapper(); 64 | if (item instanceof Project project) { 65 | DescribableList bwList = project.getBuildWrappersList(); 66 | List lsList = Util.filter(bwList, LogstashBuildWrapper.class); 67 | if (lsList.isEmpty() != value) { 68 | // already matches value. Do nothing. 69 | return false; 70 | } 71 | if (value) { 72 | bwList.add(new LogstashBuildWrapper()); 73 | } else { 74 | bwList.removeAll(lsList); 75 | } 76 | return true; 77 | } else if (item instanceof MavenModuleSet set) { 78 | DescribableList bwList = set.getBuildWrappersList(); 79 | List lsList = Util.filter(bwList, LogstashBuildWrapper.class); 80 | if (lsList.isEmpty() != value) { 81 | // already matches value. Do nothing. 82 | return false; 83 | } 84 | if (value) { 85 | bwList.add(new LogstashBuildWrapper()); 86 | } else { 87 | bwList.removeAll(lsList); 88 | } 89 | return true; 90 | } else { 91 | return false; 92 | } 93 | } 94 | } 95 | 96 | public boolean isLoaded() { 97 | try { 98 | new LogstashBuildWrapper(); 99 | return true; 100 | } catch (Throwable t) { 101 | return false; 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/main/java/configurationslicing/maven/MavenGoals.java: -------------------------------------------------------------------------------- 1 | package configurationslicing.maven; 2 | 3 | import configurationslicing.UnorderedStringSlicer; 4 | import hudson.Extension; 5 | import hudson.maven.MavenModuleSet; 6 | import java.io.IOException; 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | import jenkins.model.Jenkins; 10 | 11 | @Extension(optional = true) 12 | public class MavenGoals extends UnorderedStringSlicer { 13 | 14 | public MavenGoals() { 15 | super(new MavenGoalsSlicerSpec()); 16 | } 17 | 18 | @Override 19 | public void loadPluginDependencyClass() { 20 | // this is just to demonstrate that the Maven plugin is loaded 21 | MavenModuleSet.class.getClass(); 22 | } 23 | 24 | public static class MavenGoalsSlicerSpec extends UnorderedStringSlicerSpec { 25 | private static final String DEFAULT = "(Default)"; 26 | 27 | public String getDefaultValueString() { 28 | return DEFAULT; 29 | } 30 | 31 | public String getName() { 32 | return "Maven Goals and Options (Maven project)"; 33 | } 34 | 35 | public String getName(MavenModuleSet item) { 36 | return item.getFullName(); 37 | } 38 | 39 | public String getUrl() { 40 | return "mavengoals"; 41 | } 42 | 43 | public List getValues(MavenModuleSet item) { 44 | List ret = new ArrayList(); 45 | String goals = item.getUserConfiguredGoals(); 46 | ret.add(goals == null ? DEFAULT : goals); 47 | return ret; 48 | } 49 | 50 | @SuppressWarnings("unchecked") 51 | public List getWorkDomain() { 52 | return (List) Jenkins.get().getAllItems(MavenModuleSet.class); 53 | } 54 | 55 | public boolean setValues(MavenModuleSet item, List set) { 56 | if (set.isEmpty()) return false; 57 | String value = set.iterator().next(); 58 | if (DEFAULT.equalsIgnoreCase(value)) { 59 | item.setGoals(null); 60 | } else { 61 | item.setGoals(value); 62 | } 63 | try { 64 | item.save(); 65 | } catch (IOException e) { 66 | return false; 67 | } 68 | return true; 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/configurationslicing/maven/MavenIncremental.java: -------------------------------------------------------------------------------- 1 | package configurationslicing.maven; 2 | 3 | import configurationslicing.BooleanSlicer; 4 | import hudson.Extension; 5 | import hudson.maven.MavenModuleSet; 6 | import java.util.List; 7 | import jenkins.model.Jenkins; 8 | 9 | @Extension(optional = true) 10 | public class MavenIncremental extends BooleanSlicer { 11 | 12 | public MavenIncremental() { 13 | super(new MavenIncrementalSlicerSpec()); 14 | } 15 | 16 | public static class MavenIncrementalSlicerSpec implements BooleanSlicerSpec { 17 | 18 | public String getName() { 19 | return "Maven Incremental Build"; 20 | } 21 | 22 | public String getName(MavenModuleSet item) { 23 | return item.getFullName(); 24 | } 25 | 26 | public String getUrl() { 27 | return "mavenincremental"; 28 | } 29 | 30 | @SuppressWarnings("unchecked") 31 | public List getWorkDomain() { 32 | return (List) Jenkins.get().getAllItems(MavenModuleSet.class); 33 | } 34 | 35 | @Override 36 | public boolean getValue(MavenModuleSet item) { 37 | return item.isIncrementalBuild(); 38 | } 39 | 40 | @Override 41 | public boolean setValue(MavenModuleSet item, boolean value) { 42 | item.setIncrementalBuild(value); 43 | return true; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/configurationslicing/maven/MavenOptsSlicer.java: -------------------------------------------------------------------------------- 1 | package configurationslicing.maven; 2 | 3 | import configurationslicing.UnorderedStringSlicer; 4 | import hudson.Extension; 5 | import hudson.maven.MavenModuleSet; 6 | import hudson.maven.MavenModuleSet.DescriptorImpl; 7 | import java.io.IOException; 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | import jenkins.model.Jenkins; 11 | 12 | @Extension(optional = true) 13 | public class MavenOptsSlicer extends UnorderedStringSlicer { 14 | 15 | public MavenOptsSlicer() { 16 | super(new MavenOptsSlicerSpec()); 17 | } 18 | 19 | @Override 20 | public void loadPluginDependencyClass() { 21 | // this is just to demonstrate that the Maven plugin is loaded 22 | MavenModuleSet.class.getClass(); 23 | } 24 | 25 | public static class MavenOptsSlicerSpec extends UnorderedStringSlicerSpec { 26 | 27 | public String getDefaultValueString() { 28 | return null; 29 | } 30 | 31 | public String getName() { 32 | return "MAVEN_OPTS per Maven project"; 33 | } 34 | 35 | public String getName(MavenModuleSet item) { 36 | return item.getFullName(); 37 | } 38 | 39 | public String getUrl() { 40 | return "mavenopts"; 41 | } 42 | 43 | public List getValues(MavenModuleSet item) { 44 | List ret = new ArrayList(); 45 | String mavenOpts = item.getMavenOpts(); 46 | ret.add(mavenOpts); 47 | return ret; 48 | } 49 | 50 | @SuppressWarnings("unchecked") 51 | public List getWorkDomain() { 52 | return (List) Jenkins.get().getAllItems(MavenModuleSet.class); 53 | } 54 | 55 | public boolean setValues(MavenModuleSet item, List set) { 56 | if (set.isEmpty()) return false; 57 | String value = set.iterator().next(); 58 | DescriptorImpl descriptor = Jenkins.get().getDescriptorByType(MavenModuleSet.DescriptorImpl.class); 59 | if (value.equals(descriptor.getGlobalMavenOpts())) { 60 | item.setMavenOpts(null); 61 | } else { 62 | item.setMavenOpts(value); 63 | } 64 | try { 65 | item.save(); 66 | } catch (IOException e) { 67 | return false; 68 | } 69 | return true; 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/configurationslicing/maven/MavenSnapshotBuildTrigger.java: -------------------------------------------------------------------------------- 1 | package configurationslicing.maven; 2 | 3 | import configurationslicing.BooleanSlicer; 4 | import hudson.Extension; 5 | import hudson.maven.MavenModuleSet; 6 | import java.util.List; 7 | import jenkins.model.Jenkins; 8 | 9 | /** 10 | * A simple boolean configuration slicer to set the "Build whenever a SNAPSHOT dependency is built" build trigger in Maven projects 11 | * Created by Jeff Bischoff on 4/12/16. 12 | */ 13 | @Extension(optional = true) 14 | public class MavenSnapshotBuildTrigger extends BooleanSlicer { 15 | 16 | public MavenSnapshotBuildTrigger() { 17 | super(new MavenSnapshotBuildTriggerSlicerSpec()); 18 | } 19 | 20 | public static class MavenSnapshotBuildTriggerSlicerSpec implements BooleanSlicerSpec { 21 | 22 | public String getName() { 23 | return "Maven Snapshot dependency Build Trigger"; 24 | } 25 | 26 | public String getName(MavenModuleSet item) { 27 | return item.getFullName(); 28 | } 29 | 30 | public String getUrl() { 31 | return "mavenSnapshotBuildTrigger"; 32 | } 33 | 34 | @SuppressWarnings("unchecked") 35 | public List getWorkDomain() { 36 | return (List) Jenkins.get().getAllItems(MavenModuleSet.class); 37 | } 38 | 39 | @Override 40 | public boolean getValue(MavenModuleSet item) { 41 | // The UI displays the box checked if upstream builds are *not* ignored, so this slicer should match that 42 | // behavior 43 | return !item.ignoreUpstremChanges(); 44 | } 45 | 46 | @Override 47 | public boolean setValue(MavenModuleSet item, boolean value) { 48 | // The UI displays the box checked if upstream builds are *not* ignored, so this slicer should match that 49 | // behavior 50 | boolean ignored = !value; 51 | item.setIgnoreUpstremChanges(ignored); 52 | return true; 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/configurationslicing/maven/MavenVersionSlicer.java: -------------------------------------------------------------------------------- 1 | package configurationslicing.maven; 2 | 3 | import configurationslicing.UnorderedStringSlicer; 4 | import configurationslicing.executeshell.AbstractBuildCommandSlicer.AbstractBuildCommandSliceSpec; 5 | import hudson.Extension; 6 | import hudson.maven.MavenModuleSet; 7 | import hudson.model.AbstractProject; 8 | import hudson.model.Descriptor; 9 | import hudson.model.TopLevelItem; 10 | import hudson.tasks.Builder; 11 | import hudson.tasks.Maven; 12 | import hudson.tasks.Maven.DescriptorImpl; 13 | import hudson.tasks.Maven.MavenInstallation; 14 | import hudson.util.DescribableList; 15 | import java.io.IOException; 16 | import java.util.ArrayList; 17 | import java.util.HashSet; 18 | import java.util.List; 19 | import java.util.Set; 20 | import jenkins.model.Jenkins; 21 | import org.apache.commons.collections.CollectionUtils; 22 | import org.apache.commons.collections.Predicate; 23 | 24 | @SuppressWarnings("unchecked") 25 | @Extension(optional = true) 26 | public class MavenVersionSlicer extends UnorderedStringSlicer { 27 | 28 | public MavenVersionSlicer() { 29 | super(new MavenVersionSlicerSpec()); 30 | } 31 | 32 | @Override 33 | public void loadPluginDependencyClass() { 34 | MavenModuleSet.class.getClass(); 35 | } 36 | 37 | public static class MavenVersionSlicerSpec extends UnorderedStringSlicerSpec { 38 | private static final String DEFAULT = "(Default)"; 39 | private static final String MULTIPLE = "(MULTIPLE)"; 40 | 41 | public String getDefaultValueString() { 42 | return DEFAULT; 43 | } 44 | 45 | public String getName() { 46 | return "Maven Version"; 47 | } 48 | 49 | public String getName(AbstractProject item) { 50 | return item.getFullName(); 51 | } 52 | 53 | public String getUrl() { 54 | return "mavenversion"; 55 | } 56 | 57 | public List getValues(AbstractProject item) { 58 | if (item instanceof MavenModuleSet set) { 59 | return getValues(set); 60 | } else { 61 | List ret = new ArrayList(); 62 | List builders = getBuilders(item); 63 | if (builders == null || builders.isEmpty()) { 64 | return ret; 65 | } 66 | String last = null; 67 | Set all = new HashSet(); 68 | for (Maven builder : builders) { 69 | last = builder.mavenName; 70 | all.add(last); 71 | } 72 | if (all.size() > 1) { 73 | ret.add(MULTIPLE); 74 | } else if (last != null) { 75 | ret.add(last); 76 | } else { 77 | ret.add(DEFAULT); 78 | } 79 | return ret; 80 | } 81 | } 82 | 83 | private List getBuilders(AbstractProject item) { 84 | DescribableList> buildersList = 85 | AbstractBuildCommandSliceSpec.getBuildersList(item); 86 | // JENKINS-18794 - couldn't reproduce, but this is the problematic line 87 | if (buildersList == null) { 88 | return null; 89 | } 90 | List builders = buildersList.getAll(Maven.class); 91 | return builders; 92 | } 93 | 94 | public List getValues(MavenModuleSet item) { 95 | List ret = new ArrayList(); 96 | MavenInstallation itemMaven = item.getMaven(); 97 | if (itemMaven != null) { 98 | String itemMavenName = itemMaven.getName(); 99 | DescriptorImpl descriptorByType = Jenkins.get().getDescriptorByType(Maven.DescriptorImpl.class); 100 | MavenInstallation[] installations = descriptorByType.getInstallations(); 101 | for (MavenInstallation maven : installations) { 102 | String mavenName = maven.getName(); 103 | if (itemMavenName.equals(mavenName)) { 104 | ret.add(itemMavenName); 105 | } 106 | } 107 | } 108 | return ret; 109 | } 110 | 111 | public List getWorkDomain() { 112 | List list = new ArrayList(); 113 | 114 | // AbstractProject includes both FreeStyle/Matrix to have Maven build step and MavenModuleSet projects 115 | list.addAll(Jenkins.get().getAllItems(AbstractProject.class)); 116 | 117 | CollectionUtils.filter(list, new Predicate() { 118 | public boolean evaluate(Object object) { 119 | // exclude MatrixConfiguration, MavenModule, etc 120 | return object instanceof TopLevelItem; 121 | } 122 | }); 123 | return list; 124 | } 125 | 126 | public boolean setValues(AbstractProject item, List set) { 127 | String mavenVersion = null; 128 | if (!set.isEmpty()) { 129 | mavenVersion = set.iterator().next(); 130 | } 131 | // do not attempt to update the multiple versions at all 132 | if (MULTIPLE.equals(mavenVersion)) { 133 | return true; 134 | } 135 | if (item instanceof MavenModuleSet moduleSet) { 136 | return setValues(moduleSet, mavenVersion); 137 | } else { 138 | List builders = getBuilders(item); 139 | DescribableList> buildersList = 140 | AbstractBuildCommandSliceSpec.getBuildersList(item); 141 | for (Maven builder : builders) { 142 | String oldName = builder.mavenName; 143 | if (oldName == null) { 144 | oldName = DEFAULT; 145 | } 146 | if (!oldName.equals(mavenVersion)) { 147 | Maven newMaven = new Maven( 148 | builder.targets, 149 | mavenVersion, 150 | builder.pom, 151 | builder.properties, 152 | builder.jvmOptions, 153 | builder.usePrivateRepository); 154 | AbstractBuildCommandSliceSpec.replaceBuilder(buildersList, builder, newMaven); 155 | } 156 | } 157 | return true; 158 | } 159 | } 160 | 161 | public boolean setValues(MavenModuleSet item, String mavenVersion) { 162 | MavenInstallation old = item.getMaven(); 163 | String oldName = null; 164 | if (old != null) { 165 | oldName = old.getName(); 166 | } 167 | if (mavenVersion.trim().length() == 0 || DEFAULT.equals(mavenVersion)) { 168 | mavenVersion = null; 169 | } 170 | boolean save = false; 171 | if (mavenVersion == null) { 172 | if (oldName != null) { 173 | save = true; 174 | } 175 | } else if (!mavenVersion.equals(oldName)) { 176 | save = true; 177 | } 178 | if (save) { 179 | item.setMaven(mavenVersion); 180 | try { 181 | item.save(); 182 | return true; 183 | } catch (IOException e) { 184 | return false; 185 | } 186 | } 187 | return false; 188 | } 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /src/main/java/configurationslicing/pipeline/PipelineScriptSlicer.java: -------------------------------------------------------------------------------- 1 | package configurationslicing.pipeline; 2 | 3 | import static org.apache.commons.lang.StringUtils.isEmpty; 4 | 5 | import configurationslicing.TopLevelItemSelector; 6 | import configurationslicing.UnorderedStringSlicer; 7 | import hudson.Extension; 8 | import java.util.Collections; 9 | import java.util.List; 10 | import java.util.logging.Level; 11 | import java.util.logging.Logger; 12 | import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition; 13 | import org.jenkinsci.plugins.workflow.flow.FlowDefinition; 14 | import org.jenkinsci.plugins.workflow.job.WorkflowJob; 15 | 16 | @Extension(optional = true) 17 | public class PipelineScriptSlicer extends UnorderedStringSlicer { 18 | private static final Logger LOGGER = Logger.getLogger(PipelineScriptSlicer.class.getName()); 19 | 20 | public PipelineScriptSlicer() { 21 | super(new PipelineScriptSliceSpec()); 22 | } 23 | 24 | @Override 25 | public void loadPluginDependencyClass() { 26 | CpsFlowDefinition.class.getClass(); 27 | } 28 | 29 | public static class PipelineScriptSliceSpec extends UnorderedStringSlicerSpec { 30 | 31 | private static final String DEFINED_IN_SCM = "(Defined in SCM)"; 32 | private static final String EMPTY = "(Empty)"; 33 | 34 | public String getDefaultValueString() { 35 | return DEFINED_IN_SCM; 36 | } 37 | 38 | public String getName() { 39 | return "Pipeline Script Slicer"; 40 | } 41 | 42 | public String getName(WorkflowJob item) { 43 | return item.getFullName(); 44 | } 45 | 46 | public String getUrl() { 47 | return "pipelinescriptslicestring"; 48 | } 49 | 50 | public List getValues(WorkflowJob item) { 51 | FlowDefinition definition = item.getDefinition(); 52 | String flow = definition == null ? EMPTY : DEFINED_IN_SCM; 53 | if (definition instanceof CpsFlowDefinition flowDefinition) { 54 | flow = flowDefinition.getScript(); 55 | if (isEmpty(flow)) { 56 | flow = EMPTY; 57 | } 58 | } 59 | return Collections.singletonList(flow); 60 | } 61 | 62 | public List getWorkDomain() { 63 | return TopLevelItemSelector.getAllTopLevelItems(WorkflowJob.class); 64 | } 65 | 66 | private void setDefinition(WorkflowJob item, String definition) { 67 | try { 68 | item.setDefinition(new CpsFlowDefinition(definition, true)); 69 | } catch (hudson.model.Descriptor.FormException e) { 70 | LOGGER.log(Level.FINE, "Cannot set definition", e); 71 | } 72 | } 73 | 74 | public boolean setValues(WorkflowJob item, List set) { 75 | if (set.isEmpty() || set.size() > 1) { 76 | return false; 77 | } 78 | 79 | String oldValue = getValues(item).iterator().next(); 80 | String newValue = set.iterator().next(); 81 | 82 | if (!oldValue.equals(newValue)) { 83 | switch (newValue) { 84 | case DEFINED_IN_SCM: 85 | break; 86 | case EMPTY: 87 | setDefinition(item, ""); 88 | default: 89 | setDefinition(item, newValue); 90 | } 91 | } 92 | return false; // for some reason setDefinition is already saving the job 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/configurationslicing/prioritysorter/PrioritySorterSlicer.java: -------------------------------------------------------------------------------- 1 | package configurationslicing.prioritysorter; 2 | 3 | import configurationslicing.TopLevelItemSelector; 4 | import configurationslicing.UnorderedStringSlicer; 5 | import hudson.model.Job; 6 | import hudson.model.JobProperty; 7 | import hudson.queueSorter.PrioritySorterJobProperty; 8 | import java.io.IOException; 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | /** 13 | * @author jacob_robertson 14 | */ 15 | public class PrioritySorterSlicer extends UnorderedStringSlicer> { 16 | 17 | public PrioritySorterSlicer() { 18 | super(new PrioritySorterSliceSpec()); 19 | } 20 | 21 | @Override 22 | public void loadPluginDependencyClass() { 23 | // this is just to demonstrate that the PrioritySorter plugin is loaded 24 | PrioritySorterJobProperty.class.getClass(); 25 | } 26 | 27 | public static class PrioritySorterSliceSpec extends UnorderedStringSlicerSpec> { 28 | 29 | // cannot get this default from the class itself, as it is a package-level field 30 | private static final int DEFAULT_PRIORITY_INT = 100; 31 | private static final String DEFAULT_PRIORITY = String.valueOf(DEFAULT_PRIORITY_INT); 32 | 33 | public String getDefaultValueString() { 34 | return DEFAULT_PRIORITY; 35 | } 36 | 37 | public String getName() { 38 | return "Job Priority Slicer"; 39 | } 40 | 41 | public String getName(Job item) { 42 | return item.getFullName(); 43 | } 44 | 45 | public String getUrl() { 46 | return "jobpriority"; 47 | } 48 | 49 | public List getValues(Job job) { 50 | List values = new ArrayList(); 51 | PrioritySorterJobProperty prop = job.getProperty(PrioritySorterJobProperty.class); 52 | if (prop != null) { 53 | values.add(String.valueOf(prop.priority)); 54 | } else { 55 | values.add(DEFAULT_PRIORITY); 56 | } 57 | return values; 58 | } 59 | 60 | @SuppressWarnings({"unchecked", "rawtypes"}) 61 | public List> getWorkDomain() { 62 | return (List) TopLevelItemSelector.getAllTopLevelItems(Job.class); 63 | } 64 | 65 | @SuppressWarnings("unchecked") 66 | public boolean setValues(Job job, List set) { 67 | String value = set.iterator().next(); 68 | 69 | int priority; 70 | try { 71 | priority = Integer.parseInt(value); 72 | } catch (NumberFormatException nfe) { 73 | priority = DEFAULT_PRIORITY_INT; 74 | } 75 | boolean changed; 76 | PrioritySorterJobProperty prop = job.getProperty(PrioritySorterJobProperty.class); 77 | if (prop == null) { 78 | changed = (priority != DEFAULT_PRIORITY_INT); 79 | if (changed) { 80 | try { 81 | prop = new PrioritySorterJobProperty(priority); 82 | job.addProperty((JobProperty) prop); 83 | } catch (IOException e) { 84 | return false; 85 | } 86 | } 87 | } else { 88 | int oldPriority = prop.priority; 89 | changed = (oldPriority != priority); 90 | if (changed) { 91 | try { 92 | job.removeProperty((JobProperty) prop); 93 | prop = new PrioritySorterJobProperty(priority); 94 | job.addProperty((JobProperty) prop); 95 | } catch (IOException e) { 96 | return false; 97 | } 98 | } 99 | } 100 | return changed; 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/main/java/configurationslicing/prioritysorter/PrioritySorterSlicerWrapper.java: -------------------------------------------------------------------------------- 1 | package configurationslicing.prioritysorter; 2 | 3 | import configurationslicing.Slicer; 4 | import configurationslicing.SlicerLoader; 5 | import configurationslicing.UnorderedStringSlice; 6 | import hudson.Extension; 7 | import hudson.model.Job; 8 | 9 | @Extension 10 | public class PrioritySorterSlicerWrapper extends SlicerLoader>, Job> { 11 | protected Slicer>, Job> buildDelegateOnConstruction() throws Throwable { 12 | return new PrioritySorterSlicer(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/configurationslicing/project/AbstractSimpleProjectSlicer.java: -------------------------------------------------------------------------------- 1 | package configurationslicing.project; 2 | 3 | import configurationslicing.UnorderedStringSlicer; 4 | import hudson.model.AbstractProject; 5 | import hudson.model.FreeStyleProject; 6 | import hudson.model.Item; 7 | import java.io.IOException; 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | import jenkins.model.Jenkins; 11 | import org.apache.commons.lang.StringUtils; 12 | 13 | public abstract class AbstractSimpleProjectSlicer extends UnorderedStringSlicer { 14 | 15 | public AbstractSimpleProjectSlicer(AbstractSimpleProjectSliceSpec spec) { 16 | super(spec); 17 | } 18 | 19 | public abstract static class AbstractSimpleProjectSliceSpec extends UnorderedStringSlicerSpec { 20 | 21 | private static final String DISABLED = "(Disabled)"; 22 | 23 | public String getDefaultValueString() { 24 | return DISABLED; 25 | } 26 | 27 | public String getName(AbstractProject item) { 28 | return item.getFullName(); 29 | } 30 | 31 | public List getValues(AbstractProject item) { 32 | List values = new ArrayList(); 33 | String value = getValue(item); 34 | if (value != null) { 35 | values.add(value); 36 | } 37 | if (values.isEmpty()) { 38 | values.add(DISABLED); 39 | } 40 | return values; 41 | } 42 | 43 | protected abstract String getValue(AbstractProject project); 44 | 45 | @SuppressWarnings({"unchecked"}) 46 | public List getWorkDomain() { 47 | return (List) Jenkins.get().getAllItems(getWorkDomainClass()); 48 | } 49 | /** 50 | * Override if needed. 51 | */ 52 | protected Class getWorkDomainClass() { 53 | return FreeStyleProject.class; 54 | } 55 | 56 | public boolean setValues(AbstractProject item, List set) { 57 | try { 58 | String value; 59 | if (set.isEmpty()) { 60 | value = null; 61 | } else { 62 | value = set.iterator().next(); 63 | } 64 | if (DISABLED.equals(value)) { 65 | value = null; 66 | } 67 | String old = getValue(item); 68 | // check for equal - we don't want to trigger a change for no reason 69 | if (!StringUtils.equals(value, old)) { 70 | setValue(item, value); 71 | } 72 | return true; 73 | } catch (IOException ioe) { 74 | return false; 75 | } 76 | } 77 | /** 78 | * @throws IOException for the save operation 79 | */ 80 | protected abstract void setValue(AbstractProject project, String value) throws IOException; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/configurationslicing/project/QuietPeriodSlicer.java: -------------------------------------------------------------------------------- 1 | package configurationslicing.project; 2 | 3 | import hudson.Extension; 4 | import hudson.model.AbstractProject; 5 | import java.io.IOException; 6 | 7 | @Extension 8 | public class QuietPeriodSlicer extends AbstractSimpleProjectSlicer { 9 | 10 | public QuietPeriodSlicer() { 11 | super(new QuietPeriodSliceSpec()); 12 | } 13 | 14 | public static class QuietPeriodSliceSpec extends AbstractSimpleProjectSlicer.AbstractSimpleProjectSliceSpec { 15 | 16 | public String getName() { 17 | return "Quiet Period Slicer"; 18 | } 19 | 20 | public String getUrl() { 21 | return "quietperiod"; 22 | } 23 | 24 | @Override 25 | protected String getValue(AbstractProject project) { 26 | int q = project.getQuietPeriod(); 27 | return String.valueOf(q); 28 | } 29 | 30 | @Override 31 | protected void setValue(AbstractProject project, String value) throws IOException { 32 | Integer q; 33 | try { 34 | q = Integer.parseInt(value); 35 | } catch (NumberFormatException e) { 36 | q = null; 37 | } 38 | project.setQuietPeriod(q); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/configurationslicing/timer/AbstractTimerSliceSpec.java: -------------------------------------------------------------------------------- 1 | package configurationslicing.timer; 2 | 3 | import static configurationslicing.AbstractJob.fix; 4 | 5 | import configurationslicing.TopLevelItemSelector; 6 | import configurationslicing.UnorderedStringSlicer.UnorderedStringSlicerSpec; 7 | import hudson.model.Job; 8 | import hudson.triggers.Trigger; 9 | import java.io.IOException; 10 | import java.util.ArrayList; 11 | import java.util.Collections; 12 | import java.util.List; 13 | 14 | @SuppressWarnings("unchecked") 15 | public abstract class AbstractTimerSliceSpec extends UnorderedStringSlicerSpec { 16 | 17 | public static final String DISABLED = "(Disabled)"; 18 | 19 | private Class triggerClass; 20 | 21 | protected AbstractTimerSliceSpec(Class triggerClass) { 22 | this.triggerClass = triggerClass; 23 | } 24 | 25 | public String getDefaultValueString() { 26 | return DISABLED; 27 | } 28 | 29 | public Class getTriggerClass() { 30 | return triggerClass; 31 | } 32 | 33 | public String getName(Job item) { 34 | return item.getFullName(); 35 | } 36 | 37 | public List getValues(Job item) { 38 | Trigger trigger = fix(item).getTrigger(triggerClass); 39 | return getValues(trigger); 40 | } 41 | 42 | public static List getValues(Trigger trigger) { 43 | if (trigger == null) { 44 | return Collections.singletonList(DISABLED); 45 | } 46 | String spec = trigger.getSpec(); 47 | return splitChronSpec(spec); 48 | } 49 | 50 | public List getWorkDomain() { 51 | return TopLevelItemSelector.getAllTopLevelItems(Job.class); 52 | } 53 | 54 | public abstract Trigger newTrigger(String spec, Trigger oldTrigger); 55 | 56 | public boolean setValues(Job item, List set) { 57 | if (set.isEmpty()) return false; 58 | 59 | List list = new ArrayList(set); 60 | String spec = joinChronSpec(list); 61 | boolean disabled = DISABLED.equals(spec); 62 | 63 | Trigger oldTrigger = fix(item).getTrigger(triggerClass); 64 | 65 | // see if there are any changes 66 | if (oldTrigger != null) { 67 | String oldSpec = oldTrigger.getSpec(); 68 | if (oldSpec.equals(spec)) { 69 | return false; 70 | } 71 | } 72 | 73 | // now do the transformation 74 | try { 75 | Trigger newtrigger = null; 76 | if (!disabled) { 77 | newtrigger = newTrigger(spec, oldTrigger); 78 | } 79 | if (oldTrigger != null) { 80 | fix(item).removeTrigger(oldTrigger.getDescriptor()); 81 | } 82 | if (newtrigger != null) { 83 | fix(item).addTrigger(newtrigger); 84 | // this is necessary, otherwise the trigger has a null job 85 | // this method as currently implemented in Trigger does nothing more than save the job 86 | newtrigger.start(item, true); 87 | } 88 | return true; 89 | } catch (IllegalArgumentException e) { 90 | // need to log this 91 | return false; 92 | } catch (IOException e) { 93 | // need to log this 94 | return false; 95 | } 96 | } 97 | 98 | /** 99 | * Will both split and normalize, then return one spec per string, with 100 | * comments above. 101 | */ 102 | public static List splitChronSpec(String spec) { 103 | String[] split = spec.trim().split("\n"); 104 | List specs = new ArrayList(); 105 | 106 | boolean lastWasComment = false; 107 | StringBuilder currentSpec = new StringBuilder(); 108 | for (String line : split) { 109 | line = line.trim(); 110 | if (line.length() == 0) { 111 | continue; 112 | } 113 | boolean isComment = line.startsWith("#"); 114 | if (currentSpec.length() > 0) { 115 | // check for ends of specs 116 | boolean startNew = !isComment && !lastWasComment || isComment && !lastWasComment; 117 | if (startNew) { 118 | specs.add(currentSpec.toString().trim()); 119 | currentSpec = new StringBuilder(); 120 | } 121 | } 122 | currentSpec.append(line); 123 | currentSpec.append("\n"); 124 | lastWasComment = isComment; 125 | } 126 | if (currentSpec.length() > 0) { 127 | specs.add(currentSpec.toString().trim()); 128 | } 129 | 130 | return specs; 131 | } 132 | 133 | public static String joinChronSpec(List lines) { 134 | // because we're coming back from what was entered in the gui - 135 | // normalize first 136 | StringBuilder builder = new StringBuilder(); 137 | for (String line : lines) { 138 | List splitOne = splitChronSpec(line); 139 | for (String one : splitOne) { 140 | if (builder.length() > 0) { 141 | builder.append("\n\n"); 142 | } 143 | builder.append(one); 144 | } 145 | } 146 | return builder.toString(); 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /src/main/java/configurationslicing/timer/SCMTimerSliceStringSlicer.java: -------------------------------------------------------------------------------- 1 | package configurationslicing.timer; 2 | 3 | import configurationslicing.UnorderedStringSlicer; 4 | import hudson.Extension; 5 | import hudson.model.Job; 6 | import hudson.triggers.SCMTrigger; 7 | import hudson.triggers.Trigger; 8 | 9 | @Extension 10 | public class SCMTimerSliceStringSlicer extends UnorderedStringSlicer { 11 | 12 | public SCMTimerSliceStringSlicer() { 13 | super(new SCMTimerSliceSpec()); 14 | } 15 | 16 | public static class SCMTimerSliceSpec extends AbstractTimerSliceSpec { 17 | 18 | public SCMTimerSliceSpec() { 19 | super(SCMTrigger.class); 20 | } 21 | 22 | public String getName() { 23 | return "SCM Timer Trigger Slicer"; 24 | } 25 | 26 | public String getUrl() { 27 | return "scmtimerslicestring"; 28 | } 29 | 30 | @SuppressWarnings("unchecked") 31 | public Trigger newTrigger(String spec, Trigger oldTrigger) { 32 | boolean ignorePostCommitHooks = false; 33 | if (oldTrigger instanceof SCMTrigger trigger) { 34 | ignorePostCommitHooks = trigger.isIgnorePostCommitHooks(); 35 | } 36 | return new SCMTrigger(spec, ignorePostCommitHooks); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/configurationslicing/timer/TimerSliceStringSlicer.java: -------------------------------------------------------------------------------- 1 | package configurationslicing.timer; 2 | 3 | import configurationslicing.UnorderedStringSlicer; 4 | import hudson.Extension; 5 | import hudson.model.Job; 6 | import hudson.triggers.TimerTrigger; 7 | import hudson.triggers.Trigger; 8 | 9 | @Extension 10 | public class TimerSliceStringSlicer extends UnorderedStringSlicer { 11 | 12 | public TimerSliceStringSlicer() { 13 | super(new TimerSliceSpec()); 14 | } 15 | 16 | public static class TimerSliceSpec extends AbstractTimerSliceSpec { 17 | 18 | public TimerSliceSpec() { 19 | super(TimerTrigger.class); 20 | } 21 | 22 | public String getName() { 23 | return "Timer Trigger Slicer"; 24 | } 25 | 26 | public String getUrl() { 27 | return "timerslicestring"; 28 | } 29 | 30 | @SuppressWarnings("unchecked") 31 | public Trigger newTrigger(String spec, Trigger oldTrigger) { 32 | return new TimerTrigger(spec); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/configurationslicing/timestamper/TimestamperSlicer.java: -------------------------------------------------------------------------------- 1 | package configurationslicing.timestamper; 2 | 3 | import configurationslicing.TopLevelItemSelector; 4 | import configurationslicing.UnorderedStringSlicer; 5 | import hudson.Extension; 6 | import hudson.model.BuildableItemWithBuildWrappers; 7 | import hudson.plugins.timestamper.TimestamperBuildWrapper; 8 | import java.io.IOException; 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | /** 13 | * @author jacob_robertson 14 | */ 15 | @Extension(optional = true) 16 | public class TimestamperSlicer extends UnorderedStringSlicer { 17 | 18 | public TimestamperSlicer() { 19 | super(new TimestamperSliceSpec()); 20 | } 21 | 22 | @Override 23 | public void loadPluginDependencyClass() { 24 | // this is just to demonstrate that the Timestamper plugin is loaded 25 | TimestamperBuildWrapper.class.getClass(); 26 | } 27 | 28 | public static class TimestamperSliceSpec extends UnorderedStringSlicerSpec { 29 | 30 | private static final String DISABLED = Boolean.FALSE.toString(); 31 | 32 | public List getCommonValueStrings() { 33 | List booleans = new ArrayList(); 34 | booleans.add(Boolean.TRUE.toString()); 35 | return booleans; 36 | } 37 | 38 | public String getDefaultValueString() { 39 | return DISABLED; 40 | } 41 | 42 | public String getName() { 43 | return "Timestamper Slicer"; 44 | } 45 | 46 | public String getName(BuildableItemWithBuildWrappers item) { 47 | return item.getFullName(); 48 | } 49 | 50 | public String getUrl() { 51 | return "timestamper"; 52 | } 53 | 54 | @Override 55 | public boolean isBlankNeededForValues() { 56 | return false; 57 | } 58 | 59 | public List getValues(BuildableItemWithBuildWrappers item) { 60 | BuildableItemWithBuildWrappers project = (BuildableItemWithBuildWrappers) item; 61 | 62 | String value; 63 | TimestamperBuildWrapper wrapper = 64 | (TimestamperBuildWrapper) project.getBuildWrappersList().get(TimestamperBuildWrapper.class); 65 | if (wrapper != null) { 66 | value = Boolean.TRUE.toString(); 67 | } else { 68 | value = DISABLED; 69 | } 70 | 71 | List booleans = new ArrayList(); 72 | booleans.add(value); 73 | return booleans; 74 | } 75 | 76 | public List getWorkDomain() { 77 | return TopLevelItemSelector.getAllTopLevelItems(BuildableItemWithBuildWrappers.class); 78 | } 79 | 80 | public boolean setValues(BuildableItemWithBuildWrappers item, List set) { 81 | BuildableItemWithBuildWrappers project = (BuildableItemWithBuildWrappers) item; 82 | String value = set.iterator().next(); 83 | 84 | boolean isTimestampWanted = Boolean.parseBoolean(value); 85 | 86 | boolean changed; 87 | 88 | TimestamperBuildWrapper wrapper = 89 | (TimestamperBuildWrapper) project.getBuildWrappersList().get(TimestamperBuildWrapper.class); 90 | boolean isTimestampPresent = (wrapper != null); 91 | 92 | if (isTimestampPresent && !isTimestampWanted) { 93 | changed = true; 94 | try { 95 | project.getBuildWrappersList().remove(TimestamperBuildWrapper.class); 96 | } catch (IOException e) { 97 | return false; 98 | } 99 | } else if (!isTimestampPresent && isTimestampWanted) { 100 | changed = true; 101 | project.getBuildWrappersList().add(new TimestamperBuildWrapper()); 102 | } else { 103 | changed = false; 104 | } 105 | 106 | return changed; 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/main/java/configurationslicing/tools/AbstractToolSlicer.java: -------------------------------------------------------------------------------- 1 | package configurationslicing.tools; 2 | 3 | import configurationslicing.UnorderedStringSlicer; 4 | import hudson.model.AbstractProject; 5 | import hudson.tasks.Builder; 6 | 7 | /** 8 | * @author Maarten Dirkse 9 | */ 10 | public abstract class AbstractToolSlicer extends UnorderedStringSlicer { 11 | 12 | public AbstractToolSlicer(UnorderedStringSlicerSpec spec) { 13 | super(spec); 14 | } 15 | 16 | @Override 17 | public boolean isLoaded() { 18 | // Attempt to load a class from the plugin 19 | try { 20 | getPluginClass(); 21 | return true; 22 | } catch (Throwable e) { 23 | return false; 24 | } 25 | } 26 | 27 | /** 28 | * Method meant to let extending classes load a class that might not be present (because it's in a 29 | * plugin) in order to either succeed or force an error. 30 | * 31 | * @return a Builder class that is only found in the plugin 32 | */ 33 | protected abstract Class getPluginClass(); 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/configurationslicing/tools/AbstractToolSlicerSpec.java: -------------------------------------------------------------------------------- 1 | package configurationslicing.tools; 2 | 3 | import configurationslicing.TopLevelItemSelector; 4 | import configurationslicing.UnorderedStringSlicer.UnorderedStringSlicerSpec; 5 | import hudson.model.AbstractProject; 6 | import hudson.model.Project; 7 | import hudson.tasks.Builder; 8 | import hudson.tools.ToolInstallation; 9 | import hudson.util.DescribableList; 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | import java.util.logging.Level; 13 | import java.util.logging.Logger; 14 | import org.apache.commons.lang.StringUtils; 15 | 16 | /** 17 | * @author Maarten Dirkse 18 | */ 19 | public abstract class AbstractToolSlicerSpec extends UnorderedStringSlicerSpec { 20 | private static final Logger LOGGER = Logger.getLogger(AbstractToolSlicerSpec.class.getName()); 21 | 22 | @Override 23 | public abstract String getDefaultValueString(); 24 | 25 | protected abstract Class getBuilderClass(); 26 | 27 | protected abstract String getToolName(Builder builder); 28 | 29 | protected abstract ToolInstallation[] getToolInstallations(); 30 | 31 | protected abstract Builder getNewBuilder(Builder oldBuilder, String toolInstallationName); 32 | 33 | @Override 34 | public String getName(AbstractProject item) { 35 | return item.getFullName(); 36 | } 37 | 38 | @Override 39 | public List getWorkDomain() { 40 | return TopLevelItemSelector.getAllTopLevelItems(AbstractProject.class); 41 | } 42 | 43 | @Override 44 | public List getValues(AbstractProject item) { 45 | List ret = new ArrayList(); 46 | if (!(item instanceof Project)) { 47 | return ret; 48 | } 49 | 50 | List builders = ((Project) item).getBuildersList().getAll(getBuilderClass()); 51 | for (Builder builder : builders) { 52 | ret.add(getToolName(builder)); 53 | } 54 | 55 | return ret; 56 | } 57 | 58 | @Override 59 | public boolean setValues(AbstractProject item, List set) { 60 | if (!(item instanceof Project) || set.size() == 0) return false; 61 | 62 | DescribableList dl = ((Project) item).getBuildersList(); 63 | List builders = dl.getAll(getBuilderClass()); 64 | 65 | if (LOGGER.isLoggable(Level.FINE)) LOGGER.fine(builders.toString() + " : " + set.toString()); 66 | 67 | String[] builderNames = new String[set.size()]; 68 | set.toArray(builderNames); 69 | 70 | // If the number of builders and gradle install names don't match, something went wrong 71 | if (builders.size() != builderNames.length) return false; 72 | 73 | for (int i = 0; i < builderNames.length; i++) { 74 | Builder oldBuilder = builders.get(i); 75 | // Check that the given gradle install name actually references a different installed gradle version, and, 76 | // if so, set it 77 | if (StringUtils.equals(getToolName(oldBuilder), builderNames[i])) continue; 78 | 79 | if (null == getInstallations(builderNames[i])) return false; 80 | 81 | /* 82 | * If we're explicitly setting the gradle version, we don't want to use the wrapper, but since 83 | * it's inexplicably set using a !boolean construct, we have to pass in "true" :S 84 | */ 85 | Builder newBuilder = getNewBuilder(oldBuilder, builderNames[i]); 86 | 87 | // Using this rather roundabout method as there seems to be no way to order a DescribableList 88 | List newBuilderList = new ArrayList(dl.toList()); 89 | newBuilderList.add(newBuilderList.indexOf(oldBuilder), newBuilder); 90 | newBuilderList.remove(oldBuilder); 91 | 92 | dl.clear(); 93 | dl.addAll(newBuilderList); 94 | } 95 | 96 | return true; 97 | } 98 | 99 | protected ToolInstallation getInstallations(String installationName) { 100 | for (ToolInstallation ti : getToolInstallations()) { 101 | if (StringUtils.equals(ti.getName(), installationName)) return ti; 102 | } 103 | return null; 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/main/java/configurationslicing/tools/AntSlicer.java: -------------------------------------------------------------------------------- 1 | package configurationslicing.tools; 2 | 3 | import hudson.Extension; 4 | import hudson.tasks.Ant; 5 | import hudson.tasks.Ant.DescriptorImpl; 6 | import hudson.tasks.Builder; 7 | import hudson.tools.ToolInstallation; 8 | 9 | /** 10 | * @author Maarten Dirkse 11 | */ 12 | @Extension(optional = true) 13 | public class AntSlicer extends AbstractToolSlicer { 14 | 15 | public AntSlicer() { 16 | super(new AntSlicerSpec()); 17 | } 18 | 19 | @Override 20 | protected Class getPluginClass() { 21 | return Ant.class; 22 | } 23 | 24 | public static class AntSlicerSpec extends AbstractToolSlicerSpec { 25 | @Override 26 | public String getDefaultValueString() { 27 | return "Default"; 28 | } 29 | 30 | @Override 31 | public String getName() { 32 | return Messages.antSlicer_name(); 33 | } 34 | 35 | @Override 36 | public String getUrl() { 37 | return "projectant"; 38 | } 39 | 40 | @Override 41 | protected Class getBuilderClass() { 42 | return Ant.class; 43 | } 44 | 45 | @Override 46 | protected Builder getNewBuilder(Builder oldBuilder, String toolInstallationName) { 47 | Ant oldAnt = (Ant) oldBuilder; 48 | return new Ant( 49 | oldAnt.getTargets(), 50 | toolInstallationName, 51 | oldAnt.getAntOpts(), 52 | oldAnt.getBuildFile(), 53 | oldAnt.getProperties()); 54 | } 55 | 56 | @Override 57 | protected ToolInstallation[] getToolInstallations() { 58 | return new DescriptorImpl().getInstallations(); 59 | } 60 | 61 | @Override 62 | protected String getToolName(Builder builder) { 63 | return ((Ant) builder).getAnt() == null 64 | ? getDefaultValueString() 65 | : ((Ant) builder).getAnt().getName(); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/configurationslicing/tools/GradleSlicer.java: -------------------------------------------------------------------------------- 1 | package configurationslicing.tools; 2 | 3 | import hudson.plugins.gradle.Gradle; 4 | import hudson.plugins.gradle.Gradle.DescriptorImpl; 5 | import hudson.tasks.Builder; 6 | import hudson.tools.ToolInstallation; 7 | 8 | /** 9 | * @author Maarten Dirkse 10 | */ 11 | public class GradleSlicer extends AbstractToolSlicer { 12 | 13 | public GradleSlicer() { 14 | super(new GradleSlicerSpec()); 15 | } 16 | 17 | @Override 18 | protected Class getPluginClass() { 19 | return Gradle.class; 20 | } 21 | 22 | public static class GradleSlicerSpec extends AbstractToolSlicerSpec { 23 | @Override 24 | public String getDefaultValueString() { 25 | return "(Default)"; 26 | } 27 | 28 | @Override 29 | public String getName() { 30 | return "Gradle version per project"; 31 | } 32 | 33 | @Override 34 | public String getUrl() { 35 | return "projectgradle"; 36 | } 37 | 38 | @Override 39 | protected Class getBuilderClass() { 40 | return Gradle.class; 41 | } 42 | 43 | @Override 44 | protected ToolInstallation[] getToolInstallations() { 45 | return new DescriptorImpl().getInstallations(); 46 | } 47 | 48 | @Override 49 | protected Builder getNewBuilder(Builder oldBuilder, String toolInstallationName) { 50 | Gradle oldGradle = (Gradle) oldBuilder; 51 | return new Gradle( 52 | oldGradle.getSwitches(), 53 | oldGradle.getTasks(), 54 | oldGradle.getRootBuildScriptDir(), 55 | oldGradle.getBuildFile(), 56 | toolInstallationName, 57 | false, 58 | oldGradle.isMakeExecutable(), 59 | oldGradle.getRootBuildScriptDir(), 60 | oldGradle.isUseWorkspaceAsHome(), 61 | oldGradle.isPassAllAsSystemProperties()); 62 | } 63 | 64 | @Override 65 | protected String getToolName(Builder builder) { 66 | return ((Gradle) builder).getGradleName(); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/configurationslicing/tools/GradleSlicerWrapper.java: -------------------------------------------------------------------------------- 1 | package configurationslicing.tools; 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 GradleSlicerWrapper extends SlicerLoader, AbstractProject> { 11 | protected Slicer, AbstractProject> buildDelegateOnConstruction() 12 | throws Throwable { 13 | return new GradleSlicer(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/configurationslicing/tools/GroovySlicer.java: -------------------------------------------------------------------------------- 1 | package configurationslicing.tools; 2 | 3 | import hudson.plugins.groovy.Groovy; 4 | import hudson.tasks.Builder; 5 | import hudson.tools.ToolInstallation; 6 | import jenkins.model.Jenkins; 7 | 8 | /** 9 | * @author Maarten Dirkse 10 | */ 11 | public class GroovySlicer extends AbstractToolSlicer { 12 | 13 | public GroovySlicer() { 14 | super(new GroovySlicerSpec()); 15 | } 16 | 17 | @Override 18 | protected Class getPluginClass() { 19 | return Groovy.class; 20 | } 21 | 22 | public static class GroovySlicerSpec extends AbstractToolSlicerSpec { 23 | 24 | @Override 25 | public String getDefaultValueString() { 26 | return "(Default)"; 27 | } 28 | 29 | @Override 30 | public String getName() { 31 | return "Groovy version per project"; 32 | } 33 | 34 | @Override 35 | public String getUrl() { 36 | return "projectgroovy"; 37 | } 38 | 39 | @Override 40 | protected Class getBuilderClass() { 41 | return Groovy.class; 42 | } 43 | 44 | @Override 45 | protected Builder getNewBuilder(Builder oldInstall, String installationName) { 46 | Groovy oldGroovy = (Groovy) oldInstall; 47 | return new Groovy( 48 | oldGroovy.getScriptSource(), 49 | installationName, 50 | oldGroovy.getParameters(), 51 | oldGroovy.getScriptParameters(), 52 | oldGroovy.getProperties(), 53 | oldGroovy.getJavaOpts(), 54 | oldGroovy.getClassPath()); 55 | } 56 | 57 | @Override 58 | protected String getToolName(Builder builder) { 59 | return ((Groovy) builder).getGroovyName(); 60 | } 61 | 62 | @Override 63 | protected ToolInstallation[] getToolInstallations() { 64 | return Jenkins.get() 65 | .getDescriptorByType(Groovy.DescriptorImpl.class) 66 | .getInstallations(); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/configurationslicing/tools/GroovySlicerWrapper.java: -------------------------------------------------------------------------------- 1 | package configurationslicing.tools; 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 GroovySlicerWrapper extends SlicerLoader, AbstractProject> { 11 | protected Slicer, AbstractProject> buildDelegateOnConstruction() 12 | throws Throwable { 13 | return new GroovySlicer(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/resources/configurationslicing/BooleanSlice/sliceconfig.jelly: -------------------------------------------------------------------------------- 1 | 2 | 3 | ${it.spec.name} 4 |

5 | 6 |
7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 |
-------------------------------------------------------------------------------- /src/main/resources/configurationslicing/ConfigurationSlicing/SliceExecutor/changesummary.jelly: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |

Updated ${item.name}

8 |
9 |
10 |
11 |
-------------------------------------------------------------------------------- /src/main/resources/configurationslicing/ConfigurationSlicing/SliceExecutor/index.jelly: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 | 16 |
17 |
18 |
19 |
20 |
21 |
22 |
-------------------------------------------------------------------------------- /src/main/resources/configurationslicing/ConfigurationSlicing/SliceExecutor/index_fr.properties: -------------------------------------------------------------------------------- 1 | # The MIT License 2 | # 3 | # Copyright (c) 2004-2010, Sun Microsystems, Inc. 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in 13 | # all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | # THE SOFTWARE. 22 | 23 | Save=Enregistrer 24 | -------------------------------------------------------------------------------- /src/main/resources/configurationslicing/ConfigurationSlicing/SliceExecutor/sidepanel-executor.jelly: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/main/resources/configurationslicing/ConfigurationSlicing/index.jelly: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |

${axis.name}

8 |
9 |
10 |
11 |
-------------------------------------------------------------------------------- /src/main/resources/configurationslicing/ConfigurationSlicing/sidepanel.jelly: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/main/resources/configurationslicing/Messages.properties: -------------------------------------------------------------------------------- 1 | configurationSlicing.displayName=Configuration Slicing 2 | configurationSlicing.description=Configure a single aspect across a group of items, in contrast to the traditional configuration of all aspects of a single item 3 | configurationSlicing.configuredValueDescription=Configured Value -------------------------------------------------------------------------------- /src/main/resources/configurationslicing/Messages_it.properties: -------------------------------------------------------------------------------- 1 | configurationSlicing.displayName=Configurazione di affettatura 2 | configurationSlicing.description=Configurare un singolo aspetto in un gruppo di elementi, in contrasto con la configurazione tradizionale di tutti gli aspetti di un singolo elemento -------------------------------------------------------------------------------- /src/main/resources/configurationslicing/ParametersStringSlice/sliceconfig.jelly: -------------------------------------------------------------------------------- 1 | 2 | 3 | ${it.spec.name}${viewDisplayPart} 4 | 5 | 8 | 9 | 10 | 11 | 21 | 22 | 23 | 24 |
6 | ${it.spec.configuredValueDescription} 7 | Item Names
12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
${paramName}
20 |
25 |
-------------------------------------------------------------------------------- /src/main/resources/configurationslicing/UnorderedStringSlice/sliceconfig.jelly: -------------------------------------------------------------------------------- 1 | 2 | 3 | ${it.spec.name}${viewDisplayPart} 4 | 5 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
6 | ${it.spec.configuredValueDescription} 7 | Item Names
18 |
-------------------------------------------------------------------------------- /src/main/resources/configurationslicing/tools/Messages.properties: -------------------------------------------------------------------------------- 1 | antSlicer.name=Ant version per project -------------------------------------------------------------------------------- /src/main/resources/index.jelly: -------------------------------------------------------------------------------- 1 | 2 |
3 | Allows configuration of a single property across a group of projects 4 |
5 | -------------------------------------------------------------------------------- /src/spotbugs/excludesFilter.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /src/test/it/build-timeout-1.10/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | org.jvnet.hudson.plugins 6 | configurationslicing-it-buildtimeoutslicer110 7 | 1.34-SNAPSHOT 8 | 9 | 10 | 11 | org.jenkins-ci.plugins 12 | build-timeout 13 | 1.10 14 | compile 15 | true 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/test/it/build-timeout-1.10/src/test/java/configurationslicing/BuildTimeoutSlicerTest.java: -------------------------------------------------------------------------------- 1 | package configurationslicing; 2 | 3 | import configurationslicing.buildtimeout.BuildTimeoutSlicer; 4 | import hudson.plugins.build_timeout.BuildTimeoutWrapper; 5 | import junit.framework.TestCase; 6 | 7 | public class BuildTimeoutSlicerTest extends TestCase { 8 | 9 | int timeoutMinutes = 123; 10 | boolean failBuild = true; 11 | 12 | public void testNewBuildTimeoutWrapper() { 13 | BuildTimeoutWrapper wrapper = BuildTimeoutSlicer.BuildTimeoutSliceSpec.newBuildTimeoutWrapper(timeoutMinutes, failBuild, "absolute"); 14 | assertEquals(timeoutMinutes, wrapper.timeoutMinutes); 15 | assertEquals(failBuild, wrapper.failBuild); 16 | } 17 | public void testBuildTimeoutWrapperConstructor() { 18 | BuildTimeoutWrapper wrapper = new BuildTimeoutWrapper(timeoutMinutes, failBuild, false, 1, 1, ""); 19 | assertEquals(timeoutMinutes, wrapper.timeoutMinutes); 20 | assertEquals(failBuild, wrapper.failBuild); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/test/it/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 4.0.0 5 | 6 | org.jvnet.hudson.plugins 7 | configurationslicing-it 8 | 1.34-SNAPSHOT 9 | pom 10 | 11 | 12 | 13 | 31 | 32 | -------------------------------------------------------------------------------- /src/test/java/configurationslicing/ChronSplittingTest.java: -------------------------------------------------------------------------------- 1 | package configurationslicing; 2 | 3 | import static configurationslicing.timer.AbstractTimerSliceSpec.joinChronSpec; 4 | import static configurationslicing.timer.AbstractTimerSliceSpec.splitChronSpec; 5 | import static org.junit.jupiter.api.Assertions.assertEquals; 6 | 7 | import java.util.List; 8 | import org.junit.jupiter.api.Test; 9 | 10 | class ChronSplittingTest { 11 | 12 | @Test 13 | void testNoSplit() { 14 | String noSplit = "0 * * * *"; 15 | List lines = splitChronSpec(noSplit); 16 | assertEquals(1, lines.size()); 17 | 18 | String join = joinChronSpec(lines); 19 | assertEquals(noSplit, join); 20 | } 21 | 22 | @Test 23 | void testSimpleSplit() { 24 | String line1 = "#comment 1\n0 * * * *"; 25 | String line2 = "#comment 2\n10 * * * *"; 26 | String simpleSplit = line1 + "\n\n" + line2; 27 | List lines = splitChronSpec(simpleSplit); 28 | assertEquals(2, lines.size()); 29 | assertEquals(line1, lines.get(0)); 30 | assertEquals(line2, lines.get(1)); 31 | 32 | String join = joinChronSpec(lines); 33 | assertEquals(simpleSplit, join); 34 | } 35 | 36 | @Test 37 | void testComplexSplit() { 38 | String complexSplit = "\n#comment 1\n0 * * * *\n15 * * * *\n#something\n#comment 2\n\n10 * * * *\n\n"; 39 | List lines = splitChronSpec(complexSplit); 40 | assertEquals(3, lines.size()); 41 | assertEquals("#comment 1\n0 * * * *", lines.get(0)); 42 | assertEquals("15 * * * *", lines.get(1)); 43 | assertEquals("#something\n#comment 2\n10 * * * *", lines.get(2)); 44 | 45 | String join = joinChronSpec(lines); 46 | String normalized = "#comment 1\n0 * * * *\n\n15 * * * *\n\n#something\n#comment 2\n10 * * * *"; 47 | assertEquals(normalized, join); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/test/java/configurationslicing/ConfigurationSlicingTest.java: -------------------------------------------------------------------------------- 1 | package configurationslicing; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertThrows; 5 | 6 | import jenkins.model.Jenkins; 7 | import org.htmlunit.FailingHttpStatusCodeException; 8 | import org.junit.jupiter.api.BeforeEach; 9 | import org.junit.jupiter.api.Test; 10 | import org.jvnet.hudson.test.JenkinsRule; 11 | import org.jvnet.hudson.test.MockAuthorizationStrategy; 12 | import org.jvnet.hudson.test.junit.jupiter.WithJenkins; 13 | 14 | @WithJenkins 15 | class ConfigurationSlicingTest { 16 | 17 | private JenkinsRule j; 18 | 19 | @BeforeEach 20 | void setUp(JenkinsRule rule) { 21 | j = rule; 22 | } 23 | 24 | @Test 25 | void ensureManagementLinkRequiresAdministerPermission() throws Exception { 26 | j.jenkins.setSecurityRealm(j.createDummySecurityRealm()); 27 | j.jenkins.setAuthorizationStrategy(new MockAuthorizationStrategy() 28 | .grant(Jenkins.READ) 29 | .everywhere() 30 | .toAuthenticated() 31 | .grant(Jenkins.ADMINISTER) 32 | .everywhere() 33 | .to("root")); 34 | 35 | FailingHttpStatusCodeException ex = assertThrows( 36 | FailingHttpStatusCodeException.class, 37 | () -> j.createWebClient().login("user").goTo("slicing")); 38 | assertEquals(403, ex.getStatusCode()); 39 | 40 | j.createWebClient().login("root").goTo("slicing"); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/test/java/configurationslicing/JdkSlicerTest.java: -------------------------------------------------------------------------------- 1 | package configurationslicing; 2 | 3 | import static org.junit.jupiter.api.Assertions.*; 4 | 5 | import configurationslicing.jdk.JdkSlicer; 6 | import hudson.model.JDK; 7 | import org.junit.jupiter.api.Test; 8 | 9 | class JdkSlicerTest { 10 | 11 | @Test 12 | void testJdkEquals() { 13 | doTestJdkEquals("h1", "h2", "n1", "n2", false); 14 | doTestJdkEquals("h1", "h1", "n1", "n2", false); 15 | doTestJdkEquals("h1", "h2", "n1", "n1", false); 16 | doTestJdkEquals("h1", "h1", "n1", "n1", true); 17 | 18 | doTestJdkEquals(null, null, null, null, true); 19 | doTestJdkEquals("h1", null, null, null, false); 20 | doTestJdkEquals(null, null, "n1", null, false); 21 | } 22 | 23 | private void doTestJdkEquals(String h1, String h2, String n1, String n2, boolean expect) { 24 | JDK j1 = new JDK(n1, h1); 25 | JDK j2 = new JDK(n2, h2); 26 | assertEquals(expect, JdkSlicer.JdkSlicerSpec.equals(j1, j2)); 27 | 28 | assertTrue(JdkSlicer.JdkSlicerSpec.equals(j1, j1)); 29 | assertTrue(JdkSlicer.JdkSlicerSpec.equals(j2, j2)); 30 | assertTrue(JdkSlicer.JdkSlicerSpec.equals(null, null)); 31 | 32 | assertFalse(JdkSlicer.JdkSlicerSpec.equals(j1, null)); 33 | assertFalse(JdkSlicer.JdkSlicerSpec.equals(j2, null)); 34 | assertFalse(JdkSlicer.JdkSlicerSpec.equals(null, j1)); 35 | assertFalse(JdkSlicer.JdkSlicerSpec.equals(null, j2)); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/test/java/configurationslicing/LogRotationSlicerTest.java: -------------------------------------------------------------------------------- 1 | package configurationslicing; 2 | 3 | import static org.junit.jupiter.api.Assertions.*; 4 | 5 | import configurationslicing.logrotator.LogRotationSlicer; 6 | import configurationslicing.logrotator.LogRotationSlicer.LogRotationBuildsSliceSpec; 7 | import configurationslicing.logrotator.LogRotationSlicer.LogRotationDaysSliceSpec; 8 | import hudson.model.AbstractProject; 9 | import hudson.tasks.LogRotator; 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | import org.junit.jupiter.api.BeforeEach; 13 | import org.junit.jupiter.api.Test; 14 | import org.jvnet.hudson.test.JenkinsRule; 15 | import org.jvnet.hudson.test.junit.jupiter.WithJenkins; 16 | 17 | @WithJenkins 18 | class LogRotationSlicerTest { 19 | 20 | private JenkinsRule r; 21 | 22 | @BeforeEach 23 | void setUp(JenkinsRule rule) { 24 | r = rule; 25 | } 26 | 27 | @Test 28 | void testSetValues() throws Exception { 29 | AbstractProject item = r.createFreeStyleProject(); 30 | 31 | int daysToKeep = 111; 32 | int numToKeep = 222; 33 | int artifactDaysToKeep = 333; 34 | int artifactNumToKeep = 444; 35 | 36 | LogRotator lr = new LogRotator(daysToKeep, numToKeep, artifactDaysToKeep, artifactNumToKeep); 37 | equalsLogRotator(lr, daysToKeep, numToKeep, artifactDaysToKeep, artifactNumToKeep); 38 | 39 | item.setLogRotator(lr); 40 | equalsLogRotator(item.getLogRotator(), daysToKeep, numToKeep, artifactDaysToKeep, artifactNumToKeep); 41 | 42 | numToKeep = 12345; 43 | List set = new ArrayList<>(); 44 | set.add(String.valueOf(numToKeep)); 45 | 46 | LogRotationBuildsSliceSpec buildsSpec = new LogRotationBuildsSliceSpec(); 47 | buildsSpec.setValues(item, set); 48 | equalsLogRotator(item.getLogRotator(), daysToKeep, numToKeep, artifactDaysToKeep, artifactNumToKeep); 49 | 50 | daysToKeep = 54321; 51 | set = new ArrayList<>(); 52 | set.add(String.valueOf(daysToKeep)); 53 | 54 | LogRotationDaysSliceSpec daysSpec = new LogRotationDaysSliceSpec(); 55 | daysSpec.setValues(item, set); 56 | equalsLogRotator(item.getLogRotator(), daysToKeep, numToKeep, artifactDaysToKeep, artifactNumToKeep); 57 | } 58 | 59 | private void equalsLogRotator( 60 | LogRotator lr, int daysToKeep, int numToKeep, int artifactDaysToKeep, int artifactNumToKeep) { 61 | assertEquals(daysToKeep, lr.getDaysToKeep()); 62 | assertEquals(numToKeep, lr.getNumToKeep()); 63 | assertEquals(artifactDaysToKeep, lr.getArtifactDaysToKeep()); 64 | assertEquals(artifactNumToKeep, lr.getArtifactNumToKeep()); 65 | } 66 | 67 | @Test 68 | void testLogRotatorEquals() { 69 | doTestLogRotatorEquals(0, 0, 0, 0, true); 70 | doTestLogRotatorEquals(-1, -1, -1, -1, true); 71 | 72 | doTestLogRotatorEquals(1, 1, 1, 1, true); 73 | doTestLogRotatorEquals(1, 1, 2, 2, true); 74 | 75 | doTestLogRotatorEquals(1, -1, -1, -1, false); 76 | doTestLogRotatorEquals(-1, 1, -1, -1, false); 77 | doTestLogRotatorEquals(-1, -1, 1, -1, false); 78 | doTestLogRotatorEquals(-1, -1, -1, 1, false); 79 | 80 | doTestLogRotatorEquals(1, 1, 2, 3, false); 81 | doTestLogRotatorEquals(2, 3, 1, 1, false); 82 | } 83 | 84 | private void doTestLogRotatorEquals(int d1, int d2, int n1, int n2, boolean expect) { 85 | LogRotator r1 = new LogRotator(d1, n1, 0, 0); 86 | LogRotator r2 = new LogRotator(d2, n2, 0, 0); 87 | boolean equals = LogRotationSlicer.equals(r1, r2); 88 | assertEquals(expect, equals); 89 | assertFalse(LogRotationSlicer.equals(r1, null)); 90 | assertFalse(LogRotationSlicer.equals(null, r1)); 91 | assertFalse(LogRotationSlicer.equals(r2, null)); 92 | assertFalse(LogRotationSlicer.equals(null, r2)); 93 | 94 | assertTrue(LogRotationSlicer.equals(null, null)); 95 | assertTrue(LogRotationSlicer.equals(r1, r1)); 96 | assertTrue(LogRotationSlicer.equals(r2, r2)); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/test/java/configurationslicing/LogfilesizecheckerSlicerTest.java: -------------------------------------------------------------------------------- 1 | package configurationslicing; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | 5 | import configurationslicing.logfilesizechecker.LogfilesizecheckerSlicer; 6 | import hudson.plugins.logfilesizechecker.LogfilesizecheckerWrapper; 7 | import org.junit.jupiter.api.BeforeEach; 8 | import org.junit.jupiter.api.Test; 9 | import org.jvnet.hudson.test.JenkinsRule; 10 | import org.jvnet.hudson.test.junit.jupiter.WithJenkins; 11 | 12 | @WithJenkins 13 | class LogfilesizecheckerSlicerTest { 14 | 15 | private JenkinsRule r; 16 | 17 | int maxLogSize = 3; 18 | boolean failBuild = true; 19 | boolean setOwn = true; 20 | 21 | @BeforeEach 22 | void setUp(JenkinsRule rule) { 23 | r = rule; 24 | } 25 | 26 | @Test 27 | void testNewLogfilesizecheckerWrapper() { 28 | LogfilesizecheckerWrapper wrapper = LogfilesizecheckerSlicer.LogfilesizeSliceSpec.newLogfilesizecheckerWrapper( 29 | maxLogSize, failBuild, setOwn); 30 | assertEquals(maxLogSize, wrapper.maxLogSize); 31 | assertEquals(failBuild, wrapper.failBuild); 32 | assertEquals(setOwn, wrapper.setOwn); 33 | } 34 | 35 | @Test 36 | void testLogfilesizecheckerWrapperConstructor() { 37 | LogfilesizecheckerWrapper wrapper = new LogfilesizecheckerWrapper(maxLogSize, failBuild, setOwn); 38 | assertEquals(maxLogSize, wrapper.maxLogSize); 39 | assertEquals(failBuild, wrapper.failBuild); 40 | assertEquals(setOwn, wrapper.setOwn); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/test/java/configurationslicing/PythonTest.java: -------------------------------------------------------------------------------- 1 | package configurationslicing; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertNotNull; 4 | 5 | import configurationslicing.executeshell.ExecutePythonSlicer; 6 | import hudson.plugins.python.Python; 7 | import org.junit.jupiter.api.Test; 8 | 9 | class PythonTest { 10 | 11 | @Test 12 | void testCreatePython() { 13 | // this is failing at runtime for a method not found problem with "newInstance" 14 | Python p = new ExecutePythonSlicer.ExecutePythonSliceSpec().createBuilder("hello", null, null); 15 | assertNotNull(p); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/test/java/configurationslicing/ShellTest.java: -------------------------------------------------------------------------------- 1 | package configurationslicing; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | 5 | import configurationslicing.executeshell.ExecuteShellSlicer; 6 | import hudson.model.Project; 7 | import hudson.tasks.Shell; 8 | import java.util.ArrayList; 9 | import java.util.Arrays; 10 | import java.util.List; 11 | import org.junit.jupiter.api.BeforeEach; 12 | import org.junit.jupiter.api.Test; 13 | import org.jvnet.hudson.test.JenkinsRule; 14 | import org.jvnet.hudson.test.junit.jupiter.WithJenkins; 15 | 16 | @WithJenkins 17 | class ShellTest { 18 | 19 | private JenkinsRule r; 20 | 21 | @BeforeEach 22 | void setUp(JenkinsRule rule) { 23 | r = rule; 24 | } 25 | 26 | @Test 27 | void testGetMultipleShells() throws Exception { 28 | ExecuteShellSlicer.ExecuteShellSliceSpec spec = new ExecuteShellSlicer.ExecuteShellSliceSpec(); 29 | 30 | String command1 = "foo"; 31 | String command2 = "bar"; 32 | 33 | Project project = createProject("shell-get", command1, command2); 34 | 35 | List values = spec.getValues(project); 36 | assertEquals(command1, values.get(0)); 37 | assertEquals(command2, values.get(1)); 38 | } 39 | 40 | @Test 41 | void testSetMultipleShells() throws Exception { 42 | int count = 0; 43 | doTestSetMultipleShells("shell-" + (count++), new String[] {"a", "b"}, new String[] {"c", "d", "e"}); 44 | doTestSetMultipleShells("shell-" + (count++), new String[] {"a", "b"}, new String[] {"a", "e", "b"}); 45 | doTestSetMultipleShells("shell-" + (count++), new String[] {"a", "b", "c"}, new String[] {"a", "c"}); 46 | doTestSetMultipleShells("shell-" + (count++), new String[] {"a", "b", "c"}, new String[] {"a", "", "c"}); 47 | doTestSetMultipleShells("shell-" + (count++), new String[] {"a", "b", "c"}, new String[] {""}); 48 | doTestSetMultipleShells("shell-" + (count++), new String[] {"a", "b", "c"}, new String[] {"", "d", "", "e"}); 49 | doTestSetMultipleShells("shell-" + (count++), new String[] {"a", "b", "c"}, new String[] {"c", "b", "a"}); 50 | doTestSetMultipleShells("shell-" + (count++), new String[] {}, new String[] {"a", "b"}); 51 | } 52 | 53 | public void doTestSetMultipleShells(String name, String[] oldCommands, String[] newCommands) throws Exception { 54 | ExecuteShellSlicer.ExecuteShellSliceSpec spec = new ExecuteShellSlicer.ExecuteShellSliceSpec(); 55 | 56 | Project project = createProject(name, oldCommands); 57 | 58 | // smoke test that the create worked 59 | List oldValues = spec.getValues(project); 60 | for (int i = 0; i < oldCommands.length; i++) { 61 | assertEquals(oldCommands[i], oldValues.get(i)); 62 | } 63 | 64 | List newShells = Arrays.asList(newCommands); 65 | spec.setValues(project, newShells); 66 | 67 | List newCommandsClean = new ArrayList<>(); 68 | for (String newCommand : newCommands) { 69 | if (!"".equals(newCommand)) { 70 | newCommandsClean.add(newCommand); 71 | } 72 | } 73 | if (newCommandsClean.isEmpty()) { 74 | newCommandsClean.add(ExecuteShellSlicer.ExecuteShellSliceSpec.NOTHING); 75 | } 76 | 77 | List newValues = spec.getValues(project); 78 | assertEquals(newCommandsClean.size(), newValues.size()); 79 | for (int i = 0; i < newCommandsClean.size(); i++) { 80 | assertEquals(newCommandsClean.get(i), newValues.get(i)); 81 | } 82 | } 83 | 84 | @SuppressWarnings("unchecked") 85 | private Project createProject(String name, String... shells) throws Exception { 86 | Project project = r.createFreeStyleProject(name); 87 | for (String shell : shells) { 88 | project.getBuildersList().add(new Shell(shell)); 89 | } 90 | return project; 91 | } 92 | 93 | @SuppressWarnings("unchecked") 94 | @Test 95 | void testNoBracketNames() { 96 | ExecuteShellSlicer.ExecuteShellSliceSpec spec = new ExecuteShellSlicer.ExecuteShellSliceSpec(); 97 | 98 | String v1 = "v1"; 99 | List configurationValues = new ArrayList<>(); 100 | configurationValues.add(v1); 101 | 102 | String n1 = "n1"; 103 | List itemNames = new ArrayList<>(); 104 | itemNames.add(n1); 105 | 106 | UnorderedStringSlice slice = new UnorderedStringSlice(spec, configurationValues, itemNames); 107 | 108 | List values = slice.get(n1); 109 | assertEquals(1, values.size()); 110 | assertEquals(v1, values.get(0)); 111 | } 112 | 113 | @SuppressWarnings("unchecked") 114 | @Test 115 | void testBracketNames() throws Exception { 116 | 117 | r.createFreeStyleProject("a"); 118 | r.createFreeStyleProject("b"); 119 | r.createFreeStyleProject("c"); 120 | 121 | ExecuteShellSlicer.ExecuteShellSliceSpec spec = new ExecuteShellSlicer.ExecuteShellSliceSpec(); 122 | 123 | String v1 = "v1"; 124 | String v2 = "v2"; 125 | List configurationValues = new ArrayList<>(); 126 | configurationValues.add(v1); 127 | configurationValues.add(v2); 128 | 129 | List itemNames = new ArrayList<>(); 130 | itemNames.add("a[1]\nb[2]"); 131 | itemNames.add("a[0]\nc[4]"); 132 | 133 | UnorderedStringSlice slice = new UnorderedStringSlice(spec, configurationValues, itemNames); 134 | 135 | assertEquals(2, slice.get("a").size()); 136 | assertEquals(3, slice.get("b").size()); 137 | assertEquals(5, slice.get("c").size()); 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /src/test/java/configurationslicing/TimerSliceStringSlicerTest.java: -------------------------------------------------------------------------------- 1 | package configurationslicing; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | 5 | import configurationslicing.timer.AbstractTimerSliceSpec; 6 | import configurationslicing.timer.SCMTimerSliceStringSlicer; 7 | import configurationslicing.timer.TimerSliceStringSlicer; 8 | import hudson.model.AbstractProject; 9 | import hudson.triggers.Trigger; 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | import org.junit.jupiter.api.BeforeEach; 13 | import org.junit.jupiter.api.Test; 14 | import org.jvnet.hudson.test.JenkinsRule; 15 | import org.jvnet.hudson.test.junit.jupiter.WithJenkins; 16 | 17 | @WithJenkins 18 | class TimerSliceStringSlicerTest { 19 | 20 | private JenkinsRule r; 21 | 22 | @BeforeEach 23 | void setUp(JenkinsRule rule) { 24 | r = rule; 25 | } 26 | 27 | @Test 28 | void testTimerSliceStringSlicer() throws Exception { 29 | TimerSliceStringSlicer slicer = new TimerSliceStringSlicer(); 30 | TimerSliceStringSlicer.TimerSliceSpec spec = new TimerSliceStringSlicer.TimerSliceSpec(); 31 | doTestTimerSliceStringSlicer(slicer, spec); 32 | } 33 | 34 | @Test 35 | void testSCMTimerSliceStringSlicer() throws Exception { 36 | SCMTimerSliceStringSlicer slicer = new SCMTimerSliceStringSlicer(); 37 | SCMTimerSliceStringSlicer.SCMTimerSliceSpec spec = new SCMTimerSliceStringSlicer.SCMTimerSliceSpec(); 38 | doTestTimerSliceStringSlicer(slicer, spec); 39 | } 40 | 41 | /** 42 | * Show before/after fixing chron spec splitting behavior. 43 | * This is to test the slicer itself. More detailed testing is in ChrinSplittingTest. 44 | */ 45 | @SuppressWarnings({"unchecked"}) 46 | private void doTestTimerSliceStringSlicer(UnorderedStringSlicer slicer, AbstractTimerSliceSpec spec) 47 | throws Exception { 48 | UnorderedStringSlice slice = new UnorderedStringSlice(spec); 49 | 50 | assertEquals(0, getRealValues(slice).size()); 51 | 52 | accumulate(slicer, slice, spec, "p1", "30 * * * *"); 53 | assertEquals(1, getRealValues(slice).size()); 54 | 55 | // no additional configured values are added, because this is a duplicate 56 | accumulate(slicer, slice, spec, "p1a", "30 * * * *"); 57 | assertEquals(1, getRealValues(slice).size()); 58 | 59 | // only one additional value is added because the comment is not split out 60 | accumulate(slicer, slice, spec, "p2", "#this is my spec\n0 * * * *"); 61 | assertEquals(2, getRealValues(slice).size()); 62 | 63 | slice = new UnorderedStringSlice(spec); 64 | AbstractProject project = accumulate( 65 | slicer, 66 | slice, 67 | spec, 68 | "p3", 69 | "\n\n#comment1\n\n#line2 of comment 1\n\n0 * * * *\n\n\n#comment2\n\n20 * * * *"); 70 | assertEquals(2, getRealValues(slice).size()); 71 | 72 | assertEquals(1, project.getTriggers().size()); 73 | List set = new ArrayList<>(getRealValues(slice)); 74 | spec.setValues(project, set); 75 | assertEquals(1, project.getTriggers().size()); 76 | Trigger timer = project.getTrigger(spec.getTriggerClass()); 77 | String specString = timer.getSpec(); 78 | assertEquals("#comment1\n#line2 of comment 1\n0 * * * *\n\n#comment2\n20 * * * *", specString); 79 | } 80 | 81 | @SuppressWarnings("unchecked") 82 | private List getRealValues(UnorderedStringSlice slice) { 83 | List list = slice.getConfiguredValues(); 84 | list.remove(""); 85 | list.remove(AbstractTimerSliceSpec.DISABLED); 86 | return list; 87 | } 88 | 89 | @SuppressWarnings("unchecked") 90 | private AbstractProject accumulate( 91 | UnorderedStringSlicer slicer, 92 | UnorderedStringSlice slice, 93 | AbstractTimerSliceSpec spec, 94 | String name, 95 | String chron) 96 | throws Exception { 97 | AbstractProject project = r.createFreeStyleProject(name); 98 | Trigger trigger = spec.newTrigger(chron, null); 99 | project.addTrigger(trigger); 100 | slicer.accumulate(slice, project); 101 | return project; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/test/java/configurationslicing/claim/ClaimSlicerTest.java: -------------------------------------------------------------------------------- 1 | package configurationslicing.claim; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertFalse; 4 | import static org.junit.jupiter.api.Assertions.assertTrue; 5 | 6 | import configurationslicing.claim.ClaimSlicer.ClaimSpec; 7 | import hudson.maven.MavenModuleSet; 8 | import hudson.model.AbstractProject; 9 | import jenkins.model.Jenkins; 10 | import org.junit.jupiter.api.BeforeEach; 11 | import org.junit.jupiter.api.Test; 12 | import org.jvnet.hudson.test.JenkinsRule; 13 | import org.jvnet.hudson.test.junit.jupiter.WithJenkins; 14 | 15 | @WithJenkins 16 | class ClaimSlicerTest { 17 | 18 | private JenkinsRule r; 19 | 20 | private static int projectNameCounter = 0; 21 | 22 | @BeforeEach 23 | void setUp(JenkinsRule rule) { 24 | r = rule; 25 | } 26 | 27 | /* 28 | * Test that we can interrogate and set values using the claim slicer on free style projects 29 | */ 30 | @Test 31 | void testFreeStyleValues() throws Exception { 32 | AbstractProject item = r.createFreeStyleProject(); 33 | doTestValues(item); 34 | } 35 | 36 | /* 37 | * Test that we can interrogate and set values using the claim slicer on maven projects 38 | */ 39 | 40 | @Test 41 | void testMavenValues() throws Exception { 42 | String name = createUniqueProjectName(); 43 | MavenModuleSet mavenModuleSet = Jenkins.get().createProject(MavenModuleSet.class, name); 44 | mavenModuleSet.setRunHeadless(true); 45 | 46 | AbstractProject item = mavenModuleSet; 47 | doTestValues(item); 48 | } 49 | 50 | /* 51 | * Test that the is loaded method returns true if the claim plug-in is loaded. 52 | * The test that this method returns false otherwise is problematic to test meaningfully in the unit test environment 53 | */ 54 | @Test 55 | void testIsLoaded() { 56 | ClaimSlicer slicer = new ClaimSlicer(); 57 | boolean isLoaded = slicer.isLoaded(); 58 | assertTrue(isLoaded, "Expect claim slicer to be loaded when we have the claim plugin"); 59 | } 60 | 61 | private void doTestValues(AbstractProject item) { 62 | ClaimSpec spec = new ClaimSpec(); 63 | boolean claimsEnabled = spec.getValue(item); 64 | assertFalse(claimsEnabled, "Claims should be disabled on a new project"); 65 | 66 | boolean valueSet = spec.setValue(item, false); 67 | assertTrue(valueSet, "disabling a value when it is already disabled should work"); 68 | 69 | valueSet = spec.setValue(item, true); 70 | assertTrue(valueSet, "setting a value when it is disabled should work"); 71 | 72 | claimsEnabled = spec.getValue(item); 73 | assertTrue(claimsEnabled, "Claims should be enabled after they have been set"); 74 | 75 | valueSet = spec.setValue(item, true); 76 | assertTrue(valueSet, "setting a value when it is already enabled should work"); 77 | 78 | valueSet = spec.setValue(item, false); 79 | assertTrue(valueSet, "removing the publisher when it is enabled should work"); 80 | 81 | claimsEnabled = spec.getValue(item); 82 | assertFalse(claimsEnabled, "Claims should be disabled after they have been unset"); 83 | } 84 | 85 | private String createUniqueProjectName() { 86 | return "somestring-" + projectNameCounter++; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/test/java/configurationslicing/maven/MavenSnapshotBuildTriggerTest.java: -------------------------------------------------------------------------------- 1 | package configurationslicing.maven; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertFalse; 4 | import static org.junit.jupiter.api.Assertions.assertTrue; 5 | 6 | import configurationslicing.maven.MavenSnapshotBuildTrigger.MavenSnapshotBuildTriggerSlicerSpec; 7 | import hudson.maven.MavenModuleSet; 8 | import jenkins.model.Jenkins; 9 | import org.junit.jupiter.api.BeforeEach; 10 | import org.junit.jupiter.api.Test; 11 | import org.jvnet.hudson.test.JenkinsRule; 12 | import org.jvnet.hudson.test.junit.jupiter.WithJenkins; 13 | 14 | /** 15 | * Created by jbischoff on 4/12/16. 16 | */ 17 | @WithJenkins 18 | class MavenSnapshotBuildTriggerTest { 19 | 20 | private JenkinsRule r; 21 | 22 | @BeforeEach 23 | void setUp(JenkinsRule rule) { 24 | r = rule; 25 | } 26 | 27 | @Test 28 | void testEnableSnapshotBuildTrigger() { 29 | // Create the class under test 30 | MavenSnapshotBuildTriggerSlicerSpec slicerSpec = new MavenSnapshotBuildTriggerSlicerSpec(); 31 | // Create a mock for the MavenModuleSet a.k.a. the project(s) being modified 32 | // The version of EasyMock in use in this project doesn't seem to support mocking of concrete classes -- upgrade 33 | // desirable 34 | // MavenModuleSet mavenModuleSet = EasyMock.createMock(MavenModuleSet.class); 35 | MavenModuleSet mavenModuleSet = new MavenModuleSet(Jenkins.get(), "mock"); 36 | // Set the Snapshot builds trigger setting to 'true' 37 | slicerSpec.setValue(mavenModuleSet, true); 38 | // Check that the property was set correctly 39 | assertTrue(slicerSpec.getValue(mavenModuleSet)); 40 | // Check that the underlying MavenModuleSet has the correct value 41 | // In this case, setting the build trigger to 'true' means setting the ignoreUpstremChanges flag to 'false' 42 | assertFalse(mavenModuleSet.ignoreUpstremChanges()); 43 | } 44 | 45 | @Test 46 | void testDisableSnapshotBuildTrigger() { 47 | // Create the class under test 48 | MavenSnapshotBuildTriggerSlicerSpec slicerSpec = new MavenSnapshotBuildTriggerSlicerSpec(); 49 | // Create a mock for the MavenModuleSet a.k.a. the project(s) being modified 50 | // The version of EasyMock in use in this project doesn't seem to support mocking of concrete classes -- upgrade 51 | // desirable 52 | // MavenModuleSet mavenModuleSet = EasyMock.createMock(MavenModuleSet.class); 53 | MavenModuleSet mavenModuleSet = new MavenModuleSet(Jenkins.get(), "mock"); 54 | // Set the Snapshot builds trigger setting to 'false' 55 | slicerSpec.setValue(mavenModuleSet, false); 56 | // Check that the property was set correctly 57 | assertFalse(slicerSpec.getValue(mavenModuleSet)); 58 | // Check that the underlying MavenModuleSet has the correct value 59 | // In this case, setting the build trigger to 'false' means setting the ignoreUpstremChanges flag to 'true' 60 | assertTrue(mavenModuleSet.ignoreUpstremChanges()); 61 | } 62 | } 63 | --------------------------------------------------------------------------------