Skip to content

Commit 796a5c3

Browse files
committed
provide basic parameter parsing validation.
It would be nice, but not included here, if the parameters were checked against: - supported parameter types - actual project parameter names
1 parent f2579d7 commit 796a5c3

4 files changed

Lines changed: 102 additions & 19 deletions

File tree

src/main/java/org/jenkinsci/plugins/parameterizedschedular/ParameterParser.java

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,50 @@
22

33
import java.util.Map;
44

5+
import org.apache.commons.lang.StringUtils;
6+
7+
import com.google.common.base.Splitter;
58
import com.google.common.collect.Maps;
69

710
public class ParameterParser {
11+
/**
12+
* if ever changed, documentation and messages will need to be updated as well
13+
*/
14+
private static final String PARAMETER_SEPARATOR = "%";
15+
private static final String NAME_VALUE_SEPARATOR = "=";
16+
private static final String PAIR_SEPARATOR = ";";
17+
18+
/**
19+
*
20+
* @param nameValuePairFormattedString of name=value;other=value name value pairs
21+
* @return
22+
*/
23+
public Map<String, String> parse(String nameValuePairFormattedString) {
24+
if (StringUtils.isBlank(nameValuePairFormattedString)) {
25+
return Maps.<String, String> newHashMap();
26+
}
27+
String clean = nameValuePairFormattedString.trim();
28+
if (nameValuePairFormattedString.endsWith(PAIR_SEPARATOR)) {
29+
//the default splitter message in this scenario is not user friendly, so snip a trailing semicolon
30+
clean = clean.substring(0, clean.length() - 1);
31+
}
32+
return Splitter.on(PAIR_SEPARATOR).withKeyValueSeparator(NAME_VALUE_SEPARATOR).split(clean);
33+
}
834

9-
public Map<String, String> parse(String formattedString) {
10-
Map<String, String> result = Maps.newHashMap();
11-
if (formattedString == null) {
12-
return result;
35+
public String checkSanity(String cronTabSpec) {
36+
String[] split = cronTabSpec.split(PARAMETER_SEPARATOR);
37+
if (split.length < 2) {
38+
return null;
1339
}
14-
String[] parameters = formattedString.split(";");
15-
for (String parameter : parameters) {
16-
String[] keyvalue = parameter.split("=");
17-
if (keyvalue.length == 2) {
18-
result.put(keyvalue[0].trim(), keyvalue[1].trim());
19-
}
40+
if (split.length > 2) {
41+
return Messages.ParameterizedTimerTrigger_MoreThanOnePercent();
2042
}
2143

22-
return result;
44+
try {
45+
parse(split[1]);
46+
} catch (IllegalArgumentException e) {
47+
return e.getMessage();
48+
}
49+
return null;
2350
}
2451
}

src/main/java/org/jenkinsci/plugins/parameterizedschedular/ParameterizedTimerTrigger.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,11 +129,18 @@ public FormValidation doCheckParameterizedSpecification(@QueryParameter String v
129129
if (msg != null) {
130130
return FormValidation.warning(msg);
131131
}
132+
msg = new ParameterParser().checkSanity(value);
133+
if (msg != null) {
134+
return FormValidation.warning(msg);
135+
}
136+
132137
return FormValidation.ok();
133138
} catch (ANTLRException e) {
134139
if (value.trim().indexOf('\n') == -1 && value.contains("**"))
135140
return FormValidation.error(Messages.ParameterizedTimerTrigger_MissingWhitespace());
136141
return FormValidation.error(e.getMessage());
142+
} catch (IllegalArgumentException e) {
143+
return FormValidation.error(e.getMessage());
137144
}
138145
}
139146
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
ParameterizedTimerTrigger.DisplayName=Build periodically with parameters
22
ParameterizedTimerTrigger.MissingWhitespace=You appear to be missing whitespace between * and *.
3+
ParameterizedTimerTrigger.MoreThanOnePercent=You can only use one percent sign to separate the cron from the parameters.
4+
ParameterizedTimerTrigger.TrailingSemicolon=I need you to remove that semicolon from the end of the line.
35
ParameterizedTimerTrigger.TimerTriggerCause.ShortDescription=Started by timer with parameters:

src/test/java/org/jenkinsci/plugins/parameterizedschedular/ParameterParserTest.java

Lines changed: 55 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.jenkinsci.plugins.parameterizedschedular;
22

33
import static org.junit.Assert.assertEquals;
4+
import static org.junit.Assert.assertNull;
45

56
import java.util.HashMap;
67

@@ -20,15 +21,17 @@ public void test_EmptyStringReturns_emptyMap() {
2021
ParameterParser testObject = new ParameterParser();
2122

2223
assertEquals(new HashMap<String, String>(), testObject.parse(""));
24+
assertEquals(new HashMap<String, String>(), testObject.parse(" "));
2325
}
24-
25-
@Test
26+
27+
@Test(expected = IllegalArgumentException.class)
2628
public void test_Malformed_NoEquals_StringReturns_emptyMap() {
2729
ParameterParser testObject = new ParameterParser();
28-
30+
2931
assertEquals(new HashMap<String, String>(), testObject.parse("namevalue"));
3032
}
31-
@Test
33+
34+
@Test(expected = IllegalArgumentException.class)
3235
public void test_Malformed_ExtraSemicolon_StringReturns_emptyMap() {
3336
ParameterParser testObject = new ParameterParser();
3437

@@ -45,14 +48,14 @@ public void test_OneParamStringReturns_emptyMap() {
4548
expected.put("name", "value");
4649
assertEquals(expected, testObject.parse("name=value"));
4750
}
48-
49-
@Test
51+
52+
@Test(expected = IllegalArgumentException.class)
5053
public void test_TrimsSpacesStringReturns_emptyMap() {
5154
ParameterParser testObject = new ParameterParser();
52-
55+
5356
HashMap<String, String> expected = new HashMap<String, String>();
5457
expected.put("name", "value");
55-
assertEquals(expected, testObject.parse(" name = value; ;;"));
58+
testObject.parse(" name = value; ;;");
5659
}
5760

5861
@Test
@@ -65,4 +68,48 @@ public void test_TwoParamsStringReturns_emptyMap() {
6568
assertEquals(expected, testObject.parse("name2=value2;name=value"));
6669
}
6770

71+
@Test
72+
public void checkSanity_HappyPath() throws Exception {
73+
ParameterParser testObject = new ParameterParser();
74+
75+
assertNull(testObject.checkSanity("* * * * *%name=value"));
76+
}
77+
78+
@Test
79+
public void checkSanity_TrailingSemiColon_IsTrimmed() throws Exception {
80+
ParameterParser testObject = new ParameterParser();
81+
82+
assertNull(testObject.checkSanity("* * * * *%env=eight;freckled=flase;frecked=false;"));
83+
}
84+
85+
@Test
86+
public void checkSanity_MoreThanOnePercent() throws Exception {
87+
ParameterParser testObject = new ParameterParser();
88+
89+
assertEquals(Messages.ParameterizedTimerTrigger_MoreThanOnePercent(),
90+
testObject.checkSanity("* * * * *%name=value;%fred=barney"));
91+
}
92+
93+
@Test
94+
public void checkSanity_NoParaetersIsNoBigDeal() throws Exception {
95+
ParameterParser testObject = new ParameterParser();
96+
97+
assertNull(testObject.checkSanity("* * * * *%"));
98+
assertNull(testObject.checkSanity("* * * * *"));
99+
}
100+
101+
@Test
102+
public void checkSanity_duplicateParamName() throws Exception {
103+
ParameterParser testObject = new ParameterParser();
104+
105+
testObject.checkSanity("* * * * *%name=value;name=value2");
106+
}
107+
108+
@Test
109+
public void checkSanity_UnmatchedEquals() throws Exception {
110+
ParameterParser testObject = new ParameterParser();
111+
112+
testObject.checkSanity("* * * * *%name=value;name2=");
113+
}
114+
68115
}

0 commit comments

Comments
 (0)