sunlabs.brazil.javascript.JavaScriptTemplate Maven / Gradle / Ivy
Show all versions of sunlabs.brazil Show documentation
/*
* JavaScriptTemplate.java
*
* Brazil project web application toolkit,
* export version: 2.3
* Copyright (c) 2002-2004 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.4
* Created by drach on 02/07/19
* Last modified by suhler on 04/11/30 15:19:39
*
* Version Histories:
*
* 2.4 04/11/30-15:19:39 (suhler)
* fixed sccs version string
*
* 2.3 03/08/01-16:21:57 (suhler)
* javadoc fixes
*
* 2.2 03/07/07-14:44:34 (suhler)
* Merged changes between child workspace "/home/suhler/brazil/naws" and
* parent workspace "/net/mack.eng/export/ws/brazil/naws".
*
* 1.2.1.1 03/07/07-14:04:54 (suhler)
* use addClosingTag() convenience method
*
* 2.1 02/10/01-16:34:49 (suhler)
* version change
*
* 1.2 02/07/19-17:01:29 (drach)
* Fixed up the comments.
*
* 1.2 02/07/19-16:12:01 (Codemgr)
* SunPro Code Manager data about conflicts, renames, etc...
* Name history : 1 0 javascript/JavaScriptTemplate.java
*
* 1.1 02/07/19-16:12:00 (drach)
* date and time created 02/07/19 16:12:00 by drach
*
*/
package sunlabs.brazil.javascript;
import sunlabs.brazil.server.Request;
import sunlabs.brazil.server.Server;
import sunlabs.brazil.handler.ResourceHandler;
import sunlabs.brazil.template.RewriteContext;
import sunlabs.brazil.template.Template;
import sunlabs.brazil.util.Format;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.JavaScriptException;
import org.mozilla.javascript.Scriptable;
import java.io.IOException;
import java.util.Properties;
/**
* The JavaScriptTemplate
looks for each
* <server language="javascript">
(or
* <javascript>
)
* tag in an HTML page and treats the following data up to the next
* </server>
(or </javascript>
)
* tag as a JavaScript script to evaluate.
*
* The reason that JavaScript scripts are included in an HTML page is usually
* to generate dynamic, server-side content. After running this template,
* everything between and including the <server>
and
* </server>
(or <javascript>
and
* </javascript>
tags is replaced by all output written
* to the JavaScript standard output stream (if any).
*
* All JavaScript fragments within a given page are evaluated in the same JavaScript
* interpreter. The JavaScript 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.
* - script
*
- The name of the JavaScript script to evaluate when the interpreter is
* created. This script is only evaluated when the interp is created,
* not on every request. The variables
prefix
and
* server
are set before this file is evaluated, and
* are references to the parameters passed to a handler
* init method.
* - root
*
- The document root, if the script is a relative file name.
* If the "root" property under the template prefix is not found, the
* global "root" property is used. If the global "root" property is
* not found, the current directory is used.
*
- debug
*
- If this configuration parameter is present, this class
* replaces the
<server>
and
* </server>
tags with comments, so the user
* can keep track of where the dynamically generated content is coming
* from by examining the comments in the resultant HTML document.
* By default, the <server>
and
* </server>
are completely eliminated from the
* HTML document rather than changed into comments.
*
*
* Before evaluating each HTML document, this class sets variables
* in the JavaScript interpreter, which can be used to interact back with Java to
* do things like set the response headers:
* - request
*
- Exposes the {@link sunlabs.brazil.server.Request} Java object.
* It is set anew at each request.
*
- prefix
*
- Exposes the handler prefix String.
*
- server
*
- Exposes the handler {@link sunlabs.brazil.server.Server} object.
*
* If the attribute eval
is present as an attribute, all
* constructs of the form ${...} are substituted before processing the
* script.
*
* Here's a simple example of a JavaScript template:
*
* <html>
* <head>
* <title>JavaScript Example</title>
* </head>
* <body>
* <javascript>
* var s = "request=" + request;
* s += "<br>request.serverUrl is " + request.serverUrl();
* s += "<br>server hostName is " + server.hostName;
* s += "<br>prefix is " + prefix;
* s += "<br> <table>";
*
* // This is an example of using Java in JavaScript with LiveConnect
* var e = request.props.propertyNames();
* while (e.hasMoreElements()) {
* var prop = e.nextElement();
* s += "<tr><td>" + prop + "</td>";
* s += "<td>" + request.props.getProperty(prop) + "</td></tr>";
* }
*
* s += "</table>";
*
* // The last value computed or expressed is returned
* s;
*
* </javascript>
* </body>
* </html>
*
*
* @author Steve Drach
* @version 2.4
*/
public class JavaScriptTemplate extends Template {
private static final String SCRIPT = "script";
Context cx = null;
Scriptable scope = null;
Thread current = null;
/**
* Called at the beginning of each HTML document that this
* JavaScriptTemplate
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
.
*/
public boolean
init(RewriteContext hr) {
hr.addClosingTag("javascript");
return super.init(hr);
}
private boolean
setup(RewriteContext hr) {
Properties props = hr.request.props;
scope = cx.initStandardObjects(null);
String script = props.getProperty(hr.prefix + SCRIPT);
try {
scope.put("prefix", scope, hr.prefix);
scope.put("server", scope, Context.toObject(hr.server, scope));
if (script != null) {
String body = ResourceHandler.getResourceString(props,
hr.prefix, script);
System.err.println("startup: " + body);
cx.evaluateString(scope, body, script, 1, null);
}
} catch (IOException e) {
hr.request.log(Server.LOG_ERROR, "reading init script", script);
Context.exit();
return false;
} catch (JavaScriptException e) {
hr.request.log(Server.LOG_ERROR, "initializing JavaScript",
e.toString());
Context.exit();
return false;
}
return true;
}
/**
* Processes the <server>
tag. Substitutes the
* result of evaluating the following JavaScript script into the resultant
* HTML document.
*
* Note: Currently, there is no mechanism for other language interpreters
* to share the same server
tag.
*
* @param hr
* The request and associated HTML document that will be
* processed.
*/
public void
tag_server(RewriteContext hr) {
if ("javascript".equals(hr.get("language")) == false) {
return;
}
tag_javascript(hr);
}
/**
* Processes the <javascript>
tag. Substitutes the
* result of evaluating the following JavaScript script into the resultant
* HTML document.
*
* @param hr
* The request and associated HTML document that will be
* processed.
*/
public void
tag_javascript(RewriteContext hr) {
Thread thread;
debug(hr);
boolean eval = hr.isTrue("eval");
hr.accumulate(false);
hr.nextToken();
String script = hr.getBody();
if (eval) {
script = Format.subst(hr.request.props, script);
}
hr.request.log(Server.LOG_DIAGNOSTIC, hr.prefix, "Setting request");
if ((thread = Thread.currentThread()) != current) {
if (cx != null) {
Context.exit();
}
cx = Context.enter();
current = thread;
}
if (scope == null) {
if (!setup(hr)) {
hr.accumulate(true);
return;
}
}
scope.put("request", scope, Context.toObject(hr.request, scope));
hr.request.log(Server.LOG_DIAGNOSTIC, hr.prefix, script);
Object result = null;
try {
result = cx.evaluateString(scope, script, "template", 1, null);
} catch (JavaScriptException e) {
hr.append("\n\n");
hr.request.log(Server.LOG_DIAGNOSTIC, hr.prefix, e.toString());
}
hr.nextToken();
if (result != cx.getUndefinedValue()) {
hr.append(cx.toString(result));
}
hr.accumulate(true);
}
}