1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.apache.struts.scripting;
22
23
24 import java.util.ArrayList;
25 import java.util.Enumeration;
26 import java.util.Hashtable;
27 import java.util.List;
28 import java.util.Locale;
29 import java.util.Map;
30 import java.util.Properties;
31 import java.util.StringTokenizer;
32
33
34 import java.io.File;
35 import java.io.FileReader;
36 import java.io.IOException;
37 import java.io.InputStream;
38
39
40 import org.apache.commons.logging.Log;
41 import org.apache.commons.logging.LogFactory;
42
43
44 import org.apache.struts.action.Action;
45 import org.apache.struts.action.ActionErrors;
46 import org.apache.struts.action.ActionForm;
47 import org.apache.struts.action.ActionForward;
48 import org.apache.struts.action.ActionMapping;
49 import org.apache.struts.action.ActionMessages;
50
51
52 import javax.servlet.ServletContext;
53 import javax.servlet.http.HttpServletRequest;
54 import javax.servlet.http.HttpServletResponse;
55 import javax.servlet.http.HttpSession;
56 import org.apache.bsf.BSFException;
57 import org.apache.bsf.BSFManager;
58 import org.apache.bsf.util.IOUtils;
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 public class ScriptAction extends Action {
116
117
118 protected static final Log LOG = LogFactory.getLog(ScriptAction.class);
119
120
121 protected static final String PROPS_PATH = "/struts-scripting.properties";
122
123
124 protected static final String ENGINE_BASE = "struts-scripting.engine.";
125
126
127 protected static final String FILTERS_BASE = "struts-scripting.filters.";
128
129
130 private static BSFManagerFilter[] filters = null;
131
132
133 private Map scripts = new Hashtable();
134
135 static {
136 Properties props = new Properties();
137 try {
138 InputStream in =
139 ScriptAction.class.getClassLoader()
140 .getResourceAsStream(PROPS_PATH);
141 if (in == null) {
142 in =
143 ScriptAction.class.getClassLoader().getResourceAsStream(
144 "/struts-bsf.properties");
145 if (in != null) {
146 LOG.warn("The struts-bsf.properties file has been "
147 + "deprecated. Please use "
148 + "struts-scripting.properties instead.");
149 } else {
150 LOG.warn("struts-scripting.properties not found, using "
151 + "default engine mappings.");
152 }
153 }
154
155 if (in != null) {
156 props.load(in);
157 }
158 } catch (Exception ex) {
159 LOG.warn("Unable to load struts-scripting.properties, using "
160 + " default engine mappings.");
161 }
162 int pos = ENGINE_BASE.length();
163 for (Enumeration e = props.propertyNames(); e.hasMoreElements();) {
164 String name = (String) e.nextElement();
165 if (name.startsWith(ENGINE_BASE) && name.endsWith(".class")) {
166 String type = name.substring(pos, name.indexOf('.', pos));
167 String cls = props.getProperty(name);
168 String ext = props.getProperty(ENGINE_BASE + type
169 + ".extensions", "");
170 String[] exts = split(ext, ",");
171 if (LOG.isInfoEnabled()) {
172 LOG.info("Loading BSF engine name:" + type + " class:"
173 + cls + " ext:" + ext);
174 }
175 BSFManager.registerScriptingEngine(type, cls, exts);
176 }
177 }
178 filters = loadFilters(props);
179 }
180
181
182
183
184
185
186
187
188
189
190
191
192 public ActionForward execute(ActionMapping mapping,
193 ActionForm form,
194 HttpServletRequest request,
195 HttpServletResponse response)
196 throws Exception {
197
198 BSFManager bsfManager = new BSFManager();
199
200 String scriptName = null;
201 try {
202 scriptName = parseScriptName(mapping.getParameter(), bsfManager);
203 } catch (Exception ex) {
204 LOG.error("Unable to parse " + mapping.getParameter(), ex);
205 throw new Exception("Unable to parse " + mapping.getParameter());
206 }
207 if (scriptName == null) {
208 LOG.error("No script specified in the parameter attribute");
209 throw new Exception("No script specified");
210 }
211
212 if (LOG.isDebugEnabled()) {
213 LOG.debug("Executing script: " + scriptName);
214 }
215
216 HttpSession session = request.getSession();
217 ServletContext application = getServlet().getServletContext();
218
219 Script script = loadScript(scriptName, application);
220
221 bsfManager.declareBean("request", request,
222 HttpServletRequest.class);
223
224 bsfManager.declareBean("response", response,
225 HttpServletResponse.class);
226
227 if (session == null) {
228 LOG.debug("HTTP session is null");
229 } else {
230 bsfManager.declareBean("session", session, HttpSession.class);
231 }
232
233 bsfManager.declareBean("application", application,
234 ServletContext.class);
235
236 bsfManager.declareBean("log", LOG, Log.class);
237 StrutsInfo struts = new StrutsInfo(this, mapping, form,
238 getResources(request));
239 bsfManager.declareBean("struts", struts, StrutsInfo.class);
240
241 for (int x = 0; x < filters.length; x++) {
242 filters[x].apply(bsfManager);
243 }
244
245 bsfManager.exec(script.lang, script.file.getCanonicalPath(), 0, 0,
246 script.string);
247
248 ActionForward af = struts.getForward();
249 return af;
250 }
251
252
253
254
255
256
257
258
259
260
261
262 protected String parseScriptName(String url, BSFManager manager)
263 throws Exception {
264 if (LOG.isDebugEnabled()) {
265 LOG.debug("Parsing " + url);
266 }
267 String name = null;
268 if (url != null) {
269 String[] parsed = split(url, "?");
270 name = parsed[0];
271 if (parsed.length == 2) {
272 if (LOG.isDebugEnabled()) {
273 LOG.debug("Found a query string");
274 }
275 String[] args = split(parsed[1], "&");
276 for (int x = 0; x < args.length; x++) {
277 String[] param = split(args[x], "=");
278 Object o = manager.lookupBean(param[0]);
279 if (o != null) {
280 LOG.warn("BSF variable " + param[0]
281 + " already exists");
282 param[0] = "_" + param[0];
283 }
284 manager.declareBean(param[0], param[1], String.class);
285 if (LOG.isDebugEnabled()) {
286 LOG.debug("Registering param " + param[0]
287 + " with value " + param[1]);
288 }
289 }
290 } else {
291 if (LOG.isDebugEnabled()) {
292 LOG.debug("No query string:" + parsed.length);
293 }
294 }
295 }
296 return name;
297 }
298
299
300
301
302
303
304
305
306
307
308 protected Script loadScript(String name, ServletContext context) {
309
310 Script script = (Script) scripts.get(name);
311 if (script == null) {
312 script = new Script();
313 script.file = new File(context.getRealPath(name));
314 try {
315 script.lang =
316 BSFManager.getLangFromFilename(script.file.getName());
317 } catch (BSFException ex) {
318 LOG.warn(ex, ex);
319 }
320 }
321
322 boolean reloadScript = false;
323 long scriptLastModified = script.file.lastModified();
324 if (scriptLastModified > script.timeLastLoaded) {
325 if (LOG.isDebugEnabled()) {
326 LOG.debug("Loading updated or new script: "
327 + script.file.getName());
328 }
329 reloadScript = true;
330 }
331
332 if (reloadScript || script.string == null) {
333 synchronized (this) {
334 script.timeLastLoaded = System.currentTimeMillis();
335 FileReader reader = null;
336 try {
337 reader = new FileReader(script.file);
338 script.string = IOUtils.getStringFromReader(reader);
339 } catch (IOException ex) {
340 LOG.error("Unable to load script: " + script.file, ex);
341 } finally {
342 if (reader != null) {
343 try {
344 reader.close();
345 } catch (IOException ex) {
346 LOG.debug(ex, ex);
347 }
348 }
349 }
350 }
351 }
352
353 return script;
354 }
355
356
357
358
359
360
361
362
363 protected static BSFManagerFilter[] loadFilters(Properties props) {
364 ArrayList list = new ArrayList();
365 for (Enumeration e = props.propertyNames(); e.hasMoreElements();) {
366 String prop = (String) e.nextElement();
367 if (prop.startsWith(FILTERS_BASE) && prop.endsWith("class")) {
368 String type = prop.substring(FILTERS_BASE.length(),
369 prop.indexOf(".", FILTERS_BASE.length()));
370 String claz = props.getProperty(prop);
371 try {
372 Class cls = Class.forName(claz);
373 BSFManagerFilter f = (BSFManagerFilter) cls.newInstance();
374 f.init(type, props);
375 list.add(f);
376 if (LOG.isInfoEnabled()) {
377 LOG.info("Loaded " + type + " filter: " + claz);
378 }
379 } catch (Exception ex) {
380 LOG.error("Unable to load " + type + " filter: " + claz);
381 }
382 }
383 }
384 BSFManagerFilter[] filters = new BSFManagerFilter[list.size()];
385 filters = (BSFManagerFilter[]) list.toArray(filters);
386 return filters;
387 }
388
389
390
391
392
393
394
395
396
397 protected static String[] split(String line, String delimiter) {
398 if (line == null || "".equals(line)) {
399 return new String[]{};
400 }
401
402 List lst = new ArrayList();
403 for (Enumeration e = new StringTokenizer(line, delimiter);
404 e.hasMoreElements();) {
405 lst.add(e.nextElement());
406 }
407 String[] ret = new String[lst.size()];
408 return (String[]) lst.toArray(ret);
409 }
410
411
412
413
414
415
416
417
418
419
420 public void saveToken(HttpServletRequest req) {
421 super.saveToken(req);
422 }
423
424
425
426
427
428
429
430
431 public boolean isCancelled(HttpServletRequest req) {
432 return super.isCancelled(req);
433 }
434
435
436
437
438
439
440
441
442 public boolean isTokenValid(HttpServletRequest req) {
443 return super.isTokenValid(req);
444 }
445
446
447
448
449
450
451
452 public void resetToken(HttpServletRequest req) {
453 super.resetToken(req);
454 }
455
456
457
458
459
460
461
462
463 public Locale getLocale(HttpServletRequest req) {
464 return super.getLocale(req);
465 }
466
467
468
469
470
471
472
473
474 public void saveMessages(HttpServletRequest req, ActionMessages mes) {
475 super.saveMessages(req, mes);
476 }
477
478
479
480
481
482
483
484
485
486
487 public void saveErrors(HttpServletRequest req, ActionErrors errs) {
488 super.saveErrors(req, errs);
489 }
490
491
492
493 class Script {
494
495
496 public File file;
497
498
499 public String lang = null;
500
501
502 public long timeLastLoaded = 0;
503
504
505 public String string = null;
506 }
507 }