/
GroovyHookScript.java
140 lines (125 loc) · 4.36 KB
/
GroovyHookScript.java
1
2
3
4
5
6
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package jenkins.util.groovy;
import groovy.lang.Binding;
import groovy.lang.GroovyCodeSource;
import groovy.lang.GroovyShell;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.URL;
import java.util.Arrays;
import java.util.Set;
import java.util.TreeSet;
import static java.util.logging.Level.WARNING;
import java.util.logging.Logger;
import javax.annotation.Nonnull;
import javax.servlet.ServletContext;
/**
* A collection of Groovy scripts that are executed as various hooks.
*
* <p>
* For a given hook name, like "init", the following locations are searched for hook scripts,
* and then they are executed in turn.
*
* <ol>
* <li>/WEB-INF/<i>HOOK</i>.groovy in the war file
* <li>/WEB-INF/<i>HOOK</i>.groovy.d/*.groovy in the war file
* <li>$JENKINS_HOME/<i>HOOK</i>.groovy
* <il>$JENKINS_HOME/<i>HOOK</i>.groovy.d/*.groovy
* </ol>
*
* <p>
* Scripts inside <tt>/WEB-INF</tt> is meant for OEM distributions of Jenkins. Files inside
* <tt>$JENKINS_HOME</tt> are for installation local settings. Use of <tt>HOOK.groovy.d</tt>
* allows configuration management tools to control scripts easily.
*
* @author Kohsuke Kawaguchi
*/
public class GroovyHookScript {
private final String hook;
private final Binding bindings = new Binding();
private final ServletContext servletContext;
private final File home;
private final ClassLoader loader;
public GroovyHookScript(String hook, @Nonnull ServletContext servletContext, @Nonnull File home, @Nonnull ClassLoader loader) {
this.hook = hook;
this.servletContext = servletContext;
this.home = home;
this.loader = loader;
}
public GroovyHookScript bind(String name, Object o) {
bindings.setProperty(name,o);
return this;
}
public Binding getBindings() {
return bindings;
}
public void run() {
final String hookGroovy = hook+".groovy";
final String hookGroovyD = hook+".groovy.d";
try {
URL bundled = servletContext.getResource("/WEB-INF/"+ hookGroovy);
execute(bundled);
} catch (IOException e) {
LOGGER.log(WARNING, "Failed to execute /WEB-INF/"+hookGroovy,e);
}
Set<String> resources = servletContext.getResourcePaths("/WEB-INF/"+ hookGroovyD +"/");
if (resources!=null) {
// sort to execute them in a deterministic order
for (String res : new TreeSet<String>(resources)) {
try {
URL bundled = servletContext.getResource(res);
execute(bundled);
} catch (IOException e) {
LOGGER.log(WARNING, "Failed to execute " + res, e);
}
}
}
File script = new File(home, hookGroovy);
execute(script);
File scriptD = new File(home, hookGroovyD);
if (scriptD.isDirectory()) {
File[] scripts = scriptD.listFiles(new FileFilter() {
public boolean accept(File f) {
return f.getName().endsWith(".groovy");
}
});
if (scripts!=null) {
// sort to run them in a deterministic order
Arrays.sort(scripts);
for (File f : scripts) {
execute(f);
}
}
}
}
protected void execute(URL bundled) throws IOException {
if (bundled!=null) {
LOGGER.info("Executing bundled script: "+bundled);
execute(new GroovyCodeSource(bundled));
}
}
protected void execute(File f) {
if (f.exists()) {
LOGGER.info("Executing "+f);
try {
execute(new GroovyCodeSource(f));
} catch (IOException e) {
LOGGER.log(WARNING, "Failed to execute " + f, e);
}
}
}
protected void execute(GroovyCodeSource s) {
try {
createShell().evaluate(s);
} catch (RuntimeException x) {
LOGGER.log(WARNING, "Failed to run script " + s.getName(), x);
}
}
/**
* Can be used to customize the environment in which the script runs.
*/
protected GroovyShell createShell() {
return new GroovyShell(loader, bindings);
}
private static final Logger LOGGER = Logger.getLogger(GroovyHookScript.class.getName());
}