/*
* BeanShellServerTemplate.java
*
* Brazil project web application toolkit,
* export version: 2.3
* Copyright (c) 2002-2008 Sun Microsystems, Inc.
*
* Sun Public License Notice
*
* The contents of this file are subject to the Sun Public License Version
* 1.0 (the "License"). You may not use this file except in compliance with
* the License. A copy of the License is included as the file "license.terms",
* and also available at http://www.sun.com/
*
* The Original Code is from:
* Brazil project web application toolkit release 2.3.
* The Initial Developer of the Original Code is: drach.
* Portions created by drach are Copyright (C) Sun Microsystems, Inc.
* All Rights Reserved.
*
* Contributor(s): drach, suhler.
*
* Version: 2.7
* Created by drach on 02/01/28
* Last modified by suhler on 08/12/19 08:40:05
*
* Version Histories:
*
* 2.7 08/12/19-08:40:05 (suhler)
* remove dead code
*
* 2.6 08/07/24-16:50:17 (suhler)
* preserve token accumulation state
*
* 2.5 04/11/30-15:19:38 (suhler)
* fixed sccs version string
*
* 2.4 03/08/01-16:19:41 (suhler)
* fixes for javadoc
*
* 2.3 03/07/07-13:59:21 (suhler)
* use new addClosingTag convenience method
*
* 2.2 02/11/14-14:48:48 (suhler)
* Merged changes between child workspace "/home/suhler/brazil/naws" and
* parent workspace "/net/mack.eng/export/ws/brazil/naws".
*
* 1.6.1.1 02/11/14-14:47:54 (suhler)
* make setup protected, so we can subclass
*
* 2.1 02/10/01-16:39:54 (suhler)
* version change
*
* 1.6 02/07/19-14:24:42 (suhler)
* Request object reference wasn't being reset on each request (duh!)
*
* 1.5 02/07/18-14:03:46 (suhler)
* only process ${...} constructs using eval
*
* 1.4 02/06/05-14:31:46 (suhler)
* only create an interp when its needed.
*
* 1.3 02/02/06-13:24:43 (drach)
* Fix example so it looks right.
*
* 1.2 02/01/29-14:52:45 (drach)
* Add a simple example.
*
* 1.2 02/01/28-14:39:27 (Codemgr)
* SunPro Code Manager data about conflicts, renames, etc...
* Name history : 1 0 beanshell/BeanShellServerTemplate.java
*
* 1.1 02/01/28-14:39:26 (drach)
* date and time created 02/01/28 14:39:26 by drach
*
*/
package sunlabs.brazil.beanshell;
import sunlabs.brazil.handler.ResourceHandler;
import sunlabs.brazil.server.Request;
import sunlabs.brazil.server.Server;
import sunlabs.brazil.template.RewriteContext;
import sunlabs.brazil.template.Template;
import sunlabs.brazil.util.Format;
import bsh.EvalError;
import bsh.Interpreter;
import java.io.ByteArrayOutputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Properties;
/**
* The BeanShellServerTemplate
looks for one of the
* starting tags
* <server language="beanshell">
,
* <beanshell>
, or
* <bsh>
* in an HTML page and treats the following data up to the corresponding
* ending tag (
* </server>
,
* </beanshell>
, or
* </bsh>
)
* as a BeanShell script to evaluate. For information on BeanShell, see
* www.beanshell.org.
*
* The reason that BeanShell scripts are included in an HTML page is * usually to generate dynamic, server-side content. After running * this template, everything between and including the starting tag * and and the ending tag is replaced by all output written to the * BeanShell output stream (if any). *
* All BeanShell fragments within a given page are evaluated in the
* same BeanShell interpreter. The BeanShell interpreter actually
* lives for the entire duration of this Template
object,
* so the user can implement persistence across requests.
*
* The following configuration parameters are used to initialize this * template. *
prefix
and server
are set
* before this file is evaluated, and are references to the
* parameters passed to a handler
init method.
* * Before evaluating each HTML document, this class sets variables in * the BeanShell interpreter, which can be used to interact back with * Java to do things like set the response headers: *
eval
is present as an attribute, all
* constructs off the form ${...} are substituted before processing
* the script.
* * Here's a simple example of a BeanShell template: *
* <html>
* <head>
* <title>BeanShell Examples</title>
* </head>
* <body>
* The global variables <code>request</code>,
* <code>prefix</code>, and <code>server</code>
* are already defined. Here's how to add a new property:
* <bsh>
* sum = 3 + 4 + 5;
* request.props.put("sum", Integer.toString(sum));
* </bsh>
* And here's a way to list the properties contained in the request:
* <table>
* <bsh>
* e = request.props.propertyNames();
* while (e.hasMoreElements()) {
* name = e.nextElement();
* value = request.props.getProperty(name);
* print("<tr><td>" + name + "</td><td>"
* + value + "</td></tr>");
* }
* </bsh>
* </table>
* </body>
* </html>
*
*
* @author Steve Drach
* @version 2.7
*/
public class BeanShellServerTemplate
extends Template {
private static final String SCRIPT = "script";
Interpreter bsh = null;
ByteArrayOutputStream stdout;
/**
* Called at the beginning of each HTML document that this
* BeanShellServerTemplate
is asked to process.
*
* The first time this method is called, the initialization script
* is sourced into the interpreter, based on the configuration
* properties in the Request
*
* @param hr
* The request and associated HTML document that will be
* processed.
*
* @return true
interpreter was successfully
* initialized false
otherwise. About the
* only way that the initialization could fail would be
* due to an error sourcing the initialization script. If
* false
is returned, an error message is
* logged.
*/
public boolean
init(RewriteContext hr) {
hr.addClosingTag("beanshell");
hr.addClosingTag("bsh");
return super.init(hr);
}
/**
* Only create the interp on first use; not at each page
*/
protected boolean
setup(RewriteContext hr) {
Properties props = hr.request.props;
if (bsh == null) {
stdout = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(stdout);
bsh = new Interpreter(new InputStreamReader(System.in), ps, ps,
false);
String script = props.getProperty(hr.prefix + SCRIPT);
try {
bsh.set("prefix", hr.prefix);
bsh.set("server", hr.server);
if (script != null) {
String body = ResourceHandler.getResourceString(props,
hr.prefix, script);
bsh.eval(body);
}
} catch (IOException e) {
hr.request.log(Server.LOG_ERROR, "reading init script", script);
return false;
} catch (EvalError e) {
hr.request.log(Server.LOG_ERROR, "initializing BeanShell",
e.toString());
return false;
}
}
return true;
}
/**
* Processes the <server>
tag. Substitutes the
* result of evaluating the following BeanShell script into the
* resultant HTML document.
*
* @param hr
* The request and associated HTML document that will be
* processed.
*/
public void
tag_server(RewriteContext hr) {
String language = hr.get("language");
if ("beanshell".equals(language) ||
"bsh".equals(language)) {
tag_beanshell(hr);
}
}
/**
* Processes the <beanshell>
tag. Substitutes
* the result of evaluating the following BeanShell script into
* the resultant HTML document.
*
* @param hr
* The request and associated HTML document that will be
* processed.
*
*/
public void
tag_beanshell(RewriteContext hr) {
debug(hr);
boolean eval = hr.isTrue("eval");
boolean was = hr.accumulate(false);
hr.nextToken();
String script = hr.getBody();
if (eval) {
script = Format.subst(hr.request.props, script, true);
}
hr.request.log(Server.LOG_DIAGNOSTIC, hr.prefix, script);
if (setup(hr)) {
try {
bsh.set("request", hr.request);
bsh.eval(script);
} catch (EvalError e) {
hr.append("\n\n");
hr.request.log(Server.LOG_DIAGNOSTIC, hr.prefix, e.toString());
}
hr.nextToken();
hr.append(stdout.toString());
stdout.reset();
} else {
debug(hr, "Interpreter didn't initialize");
}
hr.accumulate(was);
}
/**
* Processes the <bsh>
tag. Substitutes the
* result of evaluating the following BeanShell script into the
* resultant HTML document.
*
* @param hr
* The request and associated HTML document that will be
* processed.
*/
public void
tag_bsh(RewriteContext hr) {
tag_beanshell(hr);
}
}