1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.shared.scriptinterpreter;
20
21 import java.io.File;
22 import java.io.IOException;
23 import java.io.PrintStream;
24 import java.nio.file.Files;
25 import java.util.ArrayList;
26 import java.util.HashMap;
27 import java.util.LinkedHashMap;
28 import java.util.List;
29 import java.util.Locale;
30 import java.util.Map;
31
32 import org.apache.commons.io.FilenameUtils;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35
36
37
38
39
40
41 public class ScriptRunner {
42
43 private static final Logger LOG = LoggerFactory.getLogger(ScriptRunner.class);
44
45
46
47
48
49 private Map<String, ScriptInterpreter> scriptInterpreters;
50
51
52
53
54 private Map<String, Object> globalVariables;
55
56
57
58
59 private List<String> classPath;
60
61
62
63
64 private String encoding;
65
66
67
68
69 public ScriptRunner() {
70 scriptInterpreters = new LinkedHashMap<>();
71 scriptInterpreters.put("bsh", new BeanShellScriptInterpreter());
72 scriptInterpreters.put("groovy", new GroovyScriptInterpreter());
73 globalVariables = new HashMap<>();
74 classPath = new ArrayList<>();
75 }
76
77
78
79
80
81
82
83 public void addScriptInterpreter(String id, ScriptInterpreter scriptInterpreter) {
84 scriptInterpreters.put(id, scriptInterpreter);
85 }
86
87
88
89
90
91
92
93 public void setGlobalVariable(String name, Object value) {
94 this.globalVariables.put(name, value);
95 }
96
97
98
99
100
101
102
103
104
105 public void setClassPath(List<String> classPath) {
106 this.classPath = (classPath != null) ? new ArrayList<>(classPath) : new ArrayList<>();
107 }
108
109
110
111
112
113
114
115 public void setScriptEncoding(String encoding) {
116 this.encoding = (encoding != null && encoding.length() > 0) ? encoding : null;
117 }
118
119
120
121
122
123
124
125
126
127
128
129
130
131 public void run(
132 final String scriptDescription,
133 final File basedir,
134 final String relativeScriptPath,
135 final Map<String, ?> context,
136 final ExecutionLogger logger)
137 throws IOException, ScriptException {
138 if (relativeScriptPath == null) {
139 LOG.debug("{}: relativeScriptPath is null, not executing script", scriptDescription);
140 return;
141 }
142
143 final File scriptFile = resolveScript(new File(basedir, relativeScriptPath));
144
145 if (!scriptFile.exists()) {
146 LOG.debug(
147 "{} : no script '{}' found in directory {}",
148 scriptDescription,
149 relativeScriptPath,
150 basedir.getAbsolutePath());
151 return;
152 }
153
154 LOG.info(
155 "run {} {}.{}",
156 scriptDescription,
157 relativeScriptPath,
158 FilenameUtils.getExtension(scriptFile.getAbsolutePath()));
159
160 executeRun(scriptDescription, scriptFile, context, logger);
161 }
162
163
164
165
166
167
168
169
170
171
172
173 public void run(
174 final String scriptDescription, File scriptFile, final Map<String, ?> context, final ExecutionLogger logger)
175 throws IOException, ScriptException {
176
177 if (!scriptFile.exists()) {
178 LOG.debug("{} : script file not found in directory {}", scriptDescription, scriptFile.getAbsolutePath());
179 return;
180 }
181
182 LOG.info("run {} {}", scriptDescription, scriptFile.getAbsolutePath());
183
184 executeRun(scriptDescription, scriptFile, context, logger);
185 }
186
187 private void executeRun(
188 final String scriptDescription, File scriptFile, final Map<String, ?> context, final ExecutionLogger logger)
189 throws IOException, ScriptException {
190 ScriptInterpreter interpreter = getInterpreter(scriptFile);
191 if (LOG.isDebugEnabled()) {
192 String name = interpreter.getClass().getName();
193 name = name.substring(name.lastIndexOf('.') + 1);
194 LOG.debug("Running script with {} :{}", name, scriptFile);
195 }
196
197 String script;
198 try {
199 byte[] bytes = Files.readAllBytes(scriptFile.toPath());
200 if (encoding != null) {
201 script = new String(bytes, encoding);
202 } else {
203 script = new String(bytes);
204 }
205 } catch (IOException e) {
206 String errorMessage =
207 "error reading " + scriptDescription + " " + scriptFile.getPath() + ", " + e.getMessage();
208 throw new IOException(errorMessage, e);
209 }
210
211 Object result;
212 try {
213 if (logger != null) {
214 logger.consumeLine("Running " + scriptDescription + ": " + scriptFile);
215 }
216
217 PrintStream out = (logger != null) ? logger.getPrintStream() : null;
218
219 Map<String, Object> scriptVariables = new HashMap<>(this.globalVariables);
220 scriptVariables.put("basedir", scriptFile.getParentFile());
221 scriptVariables.put("context", context);
222
223 result = interpreter.evaluateScript(script, classPath, scriptVariables, out);
224 if (logger != null) {
225 logger.consumeLine("Finished " + scriptDescription + ": " + scriptFile);
226 }
227 } catch (ScriptEvaluationException e) {
228 Throwable t = (e.getCause() != null) ? e.getCause() : e;
229 if (logger != null) {
230 t.printStackTrace(logger.getPrintStream());
231 }
232 throw e;
233 }
234
235 if (!(result == null || Boolean.parseBoolean(String.valueOf(result)))) {
236 throw new ScriptReturnException("The " + scriptDescription + " returned " + result + ".", result);
237 }
238 }
239
240
241
242
243
244
245
246
247 private File resolveScript(File scriptFile) {
248 if (scriptFile != null && !scriptFile.exists()) {
249 for (String ext : this.scriptInterpreters.keySet()) {
250 File candidateFile = new File(scriptFile.getPath() + '.' + ext);
251 if (candidateFile.exists()) {
252 scriptFile = candidateFile;
253 break;
254 }
255 }
256 }
257 return scriptFile;
258 }
259
260
261
262
263
264
265
266
267
268 private ScriptInterpreter getInterpreter(File scriptFile) {
269 String ext = FilenameUtils.getExtension(scriptFile.getName()).toLowerCase(Locale.ENGLISH);
270 ScriptInterpreter interpreter = scriptInterpreters.get(ext);
271 if (interpreter == null) {
272 interpreter = scriptInterpreters.get("bsh");
273 }
274 return interpreter;
275 }
276 }