I’ve been doing a bit of Jenkins plugin development lately and I have found that documentation can be a bit scarce. Like many projects out there, they show you how to drive a nail and then expect you to go off and build a house. I’m posting a little bit of what I have created in hopes of either sharing some much needed documentation or being shown a better way to do things.

While building my plugin I needed a way to inject Jenkins environment variables, called EnvVars in Jenkins API into some input. Not being able to find any built-in utilities to do this, I wrote my own. So, without further to-do, a util that has been useful (for met at least):

 1 import hudson.EnvVars;
 2 
 3 import java.util.regex.Matcher;
 4 import java.util.regex.Pattern;
 5 
 6 public class EnvTemplater {
 7 
 8     private static final Pattern VARIABLE_PATTERN = Pattern.compile(
 9             "(\\$\\{?[A-Za-z_]+\\}?)");
10     private static final Pattern VARIABLE_NAME_PATTERN = Pattern.compile("([A-Za-z_]+)");
11 
12     /**
13      * Given an input string, find environment var patterns and inject them into
14      * the string from the current environment variables. The input of the string really
15      * isn't important to this function, only the format of the variables within the string.
16      * We look for two forms of variables:
17      *  - $VAR_NAME
18      *  - ${VAR_NAME}
19      *
20      * Note: The environment variables that we are using are not _true_ environment 
21      * variables, but rather Jenkins Environment variables (the same ones you would normally 
22      * use to template within a normal Jenkins job).
23      *
24      * @param input The input string to be templated (possibly containing variable 
25      *              expressions)
26      * @param vars  The vars to use to inject into the input string
27      * @return      A string where the variables have been replaced by Jenkins evn variable 
28      *              value, if the variable exists.
29      */
30     public static String templateString(String input, EnvVars vars) {
31         if (vars == null || input == null) {
32             return input;
33         }
34 
35         String output = input;
36         Matcher match = VARIABLE_PATTERN.matcher(input);
37         int replacementOffset = 0;
38 
39         // iterate through all of the variables that we find
40         while (match.find()) {
41 
42             // find the variable name (without the $ and {} characters)
43             String matchGroup = match.group();
44             Matcher varNameMatcher = VARIABLE_NAME_PATTERN.matcher(matchGroup);
45             while (varNameMatcher.find()) {
46                 // pull out variable name, replace using bounds of outer `match`
47                 String varNameMatchGroup = varNameMatcher.group(1);
48                 int startPos = match.start(1);
49                 int endPos = match.end(1);
50                 if (vars.containsKey(varNameMatchGroup)) {
51                     String replacement = vars.get(varNameMatchGroup, matchGroup);
52                     output = output.substring(0, replacementOffset + startPos)
53                             + replacement
54                             + output.substring(replacementOffset + endPos, output.length());
55 
56                     // replacement offset is used during string replacement to account for 
57                     // the string growing or shrinking as we replace values (and the regex 
58                     // positions being out of date).
59                     replacementOffset +=  replacement.length() - (endPos - startPos);
60                 }
61             }
62         }
63         return output;
64     }
65 }