r9635 - in helma-ng/trunk: modules/helma src/org/helma/jack src/org/helma/javascript src/org/helma/web
[email protected] Tue, 21 Apr 2009 10:37:57 +0200 (CEST)
| Newsgroups | gmane.comp.java.helma.cvs |
|---|---|
| Message-ID | <20090421083757.2B5E53D0D6@mia> |
Author: hannes
Date: 2009-04-21 10:37:57 +0200 (Tue, 21 Apr 2009)
New Revision: 9635
Removed:
helma-ng/trunk/modules/helma/jack.js
helma-ng/trunk/src/org/helma/web/HelmaServlet.java
helma-ng/trunk/src/org/helma/web/Request.java
helma-ng/trunk/src/org/helma/web/Response.java
helma-ng/trunk/src/org/helma/web/Session.java
Modified:
helma-ng/trunk/modules/helma/httpserver.js
helma-ng/trunk/modules/helma/webapp.js
helma-ng/trunk/src/org/helma/jack/JackEnv.java
helma-ng/trunk/src/org/helma/jack/JackServlet.java
helma-ng/trunk/src/org/helma/javascript/ReloadableScript.java
helma-ng/trunk/src/org/helma/javascript/RhinoEngine.java
Log:
Make JackServlet the default and only servlet for Helma.
* Move jack helper functions from helma/jack to helma/httpserver
* Add constructor to JackServlet that allows to pass in a jack function
* Add jack.servlet_request and jack.servlet_response properties to JackEnv
* Remove org.helma.web package including HelmaServlet
Details at http://dev.helma.org/trac/helma/changeset/9635
Modified: helma-ng/trunk/modules/helma/httpserver.js
===================================================================
--- helma-ng/trunk/modules/helma/httpserver.js 2009-04-21 08:37:53 UTC (rev 9634)
+++ helma-ng/trunk/modules/helma/httpserver.js 2009-04-21 08:37:57 UTC (rev 9635)
@@ -2,7 +2,7 @@
* Module for starting and stopping the jetty http server.
*/
-export('start', 'stop');
+export('start', 'stop', 'initRequest', 'commitResponse');
// mark this module as shared between all requests
var __shared__ = true;
@@ -32,7 +32,7 @@
* function: 'handleServletRequest' })</li>
* </ul>
*/
- this.start = function(config) {
+ this.start = function(config, func) {
config = config || {};
var configFile = config.configFile || 'config/jetty.xml';
// var staticIndex = config.staticIndex || config.staticIndex == undefined;
@@ -44,7 +44,7 @@
}
var jetty = org.mortbay.jetty;
var XmlConfiguration = org.mortbay.xml.XmlConfiguration;
- var HelmaServlet = org.helma.web.HelmaServlet;
+ var Servlet = org.helma.jack.JackServlet;
server = new jetty.Server();
try {
var xmlconfig = new XmlConfiguration(jettyconfig.inputStream);
@@ -56,7 +56,7 @@
xmlconfig.configure(server);
//everything else is configured via idmap
var idMap = xmlconfig.getIdMap();
- // java.lang.System.err.println("idmap: " + idMap);
+ // print("idmap: " + idMap);
var staticCtx = idMap.get('staticContext');
if (staticCtx && typeof config.staticDir == "string") {
staticCtx.setResourceBase(getResource(config.staticDir));
@@ -66,11 +66,11 @@
// set up helma servlet context
var helmaCtx = idMap.get('helmaContext');
if (helmaCtx) {
- var servlet = new HelmaServlet(engine);
+ var servlet = func ? new Servlet(engine, func) : new Servlet(engine);
var servletHolder = new jetty.servlet.ServletHolder(servlet);
- var params = config.servletParams || {
- 'module': 'helma/webapp',
- 'function': 'handleServletRequest'
+ var params = {
+ 'moduleName': config.moduleName || 'helma/webapp',
+ 'functionName': config.functionName || 'handleRequest'
};
for (var p in params) {
servletHolder.setInitParameter(p, params[p]);
@@ -101,3 +101,44 @@
}
})(this);
+
+/**
+ * Set up the IO related properties of a jack environment object.
+ * @param env a jack request object
+ */
+function initRequest(env) {
+ var IO = require('io').IO;
+ env['jack.input'] = new IO(env['jack.input'], null);
+ env['jack.error'] = new IO(null, env['jack.error']);
+}
+
+/**
+ * Apply the return value of a Jack application to a servlet response.
+ * This is used internally by the org.helma.jack.JackServlet class, so
+ * you won't need this unless you're implementing your own servlet
+ * based jack connector.
+ *
+ * @param env the jack env argument
+ * @param result the object returned by a jack application
+ */
+function commitResponse(env, result) {
+ var response = env['jack.servlet_response'];
+ if (response.isCommitted() || !(result instanceof Array))
+ return;
+ var [status, headers, body] = result;
+ response.status = status;
+ for (var name in headers) {
+ response.setHeader(name, headers[name]);
+ }
+ var writer = response.writer;
+ if (body && typeof body.forEach == "function") {
+ body.forEach(function(chunk) {
+ writer.write(String(chunk));
+ writer.flush();
+ })
+ } else {
+ writer.write(String(body));
+ }
+ writer.close();
+}
+
Deleted: helma-ng/trunk/modules/helma/jack.js
Modified: helma-ng/trunk/modules/helma/webapp.js
===================================================================
--- helma-ng/trunk/modules/helma/webapp.js 2009-04-21 08:37:53 UTC (rev 9634)
+++ helma-ng/trunk/modules/helma/webapp.js 2009-04-21 08:37:57 UTC (rev 9635)
@@ -1,4 +1,4 @@
-11/*
+/*
* The webapp module provides support for building web applications in Helma NG.
*/
@@ -17,26 +17,20 @@
var log = logging.getLogger(__name__);
-function handleJackRequest(env) {}
+var __shared__ = true;
-// support old name
-function handleRequest(req, res) {
- return handleServletRequest(req, res);
-}
-
/**
- * Handler function called by the Helma servlet.
+ * Handler function called by the Jack servlet.
*
- * @param req
- * @param res
+ * @param env the jack environment argument
*/
-function handleServletRequest(servletRequest, servletResponse) {
+function handleRequest(env) {
// get config and apply it to req, res
var config = getConfig();
if (log.debugEnabled) log.debug('got config: ' + config.toSource());
- var req = new Request(servletRequest);
- var res = new Response(servletResponse);
+ var req = new Request(env['jack.servlet_request']);
+ var res = new Response(env['jack.servlet_response']);
req.charset = res.charset = config.charset || 'utf8';
res.contentType = config.contentType || 'text/html';
Modified: helma-ng/trunk/src/org/helma/jack/JackEnv.java
===================================================================
--- helma-ng/trunk/src/org/helma/jack/JackEnv.java 2009-04-21 08:37:53 UTC (rev 9634)
+++ helma-ng/trunk/src/org/helma/jack/JackEnv.java 2009-04-21 08:37:57 UTC (rev 9635)
@@ -19,24 +19,29 @@
import org.mozilla.javascript.*;
import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
import java.util.Enumeration;
import java.io.IOException;
import java.lang.reflect.Method;
public class JackEnv extends ScriptableObject {
- HttpServletRequest req;
+ HttpServletRequest request;
+ HttpServletResponse response;
public JackEnv() {}
- public JackEnv(Object obj) {
- if (!(obj instanceof HttpServletRequest)) {
- throw new IllegalArgumentException("Wrong argument: " + obj);
+ public JackEnv(Object req, Object res) {
+ if (!(req instanceof HttpServletRequest)) {
+ throw new IllegalArgumentException("Wrong argument: " + req);
+ } else if (!(res instanceof HttpServletResponse)) {
+ throw new IllegalArgumentException("Wrong argument: " + res);
}
- req = (HttpServletRequest) obj;
- for (Enumeration e = req.getHeaderNames(); e.hasMoreElements(); ) {
+ this.request = (HttpServletRequest) req;
+ this.response = (HttpServletResponse) res;
+ for (Enumeration e = request.getHeaderNames(); e.hasMoreElements(); ) {
String name = (String) e.nextElement();
- String value = req.getHeader(name);
+ String value = request.getHeader(name);
name = name.replace('-', '_').toUpperCase();
if (!"CONTENT_LENGTH".equals(value) && !"CONTENT_TYPE".equals(value)) {
name = "HTTP_" + name;
@@ -47,53 +52,61 @@
public String getScriptName() {
- return checkString(req.getServletPath());
+ return checkString(request.getServletPath());
}
public String getPathInfo() {
- return checkString(req.getPathInfo());
+ return checkString(request.getPathInfo());
}
public String getRequestMethod() {
- return checkString(req.getMethod());
+ return checkString(request.getMethod());
}
public String getServerName() {
- return checkString(req.getServerName());
+ return checkString(request.getServerName());
}
public String getServerPort() {
- return checkString(Integer.toString(req.getServerPort()));
+ return checkString(Integer.toString(request.getServerPort()));
}
public String getQueryString() {
- return checkString(req.getQueryString());
+ return checkString(request.getQueryString());
}
public String getHttpVersion() {
- return checkString(req.getProtocol());
+ return checkString(request.getProtocol());
}
public String getRemoteHost() {
- return checkString(req.getRemoteHost());
+ return checkString(request.getRemoteHost());
}
public String getUrlScheme() {
- return req.isSecure() ? "https" : "http";
+ return request.isSecure() ? "https" : "http";
}
public Object getInputStream() {
try {
- return req.getInputStream();
+ return Context.javaToJS(request.getInputStream(), this);
} catch (IOException iox) {
return Undefined.instance;
}
}
public Object getErrorStream() {
- return System.err;
+ return Context.javaToJS(System.err, this);
}
+ public Object getServletRequest() {
+ return Context.javaToJS(request, this);
+ }
+
+ public Object getServletResponse() {
+ return Context.javaToJS(response, this);
+ }
+
public static void finishInit(Scriptable scope, FunctionObject constructor, Scriptable prototype)
throws NoSuchMethodException {
int flags = PERMANENT;
@@ -115,6 +128,8 @@
ScriptableObject.defineProperty(proto, "jack.multiprocess", Boolean.TRUE, flags);
ScriptableObject.defineProperty(proto, "jack.run_once", Boolean.FALSE, flags);
proto.defineProperty("jack.url_scheme", null, getMethod("getUrlScheme"), null, flags);
+ proto.defineProperty("jack.servlet_request", null, getMethod("getServletRequest"), null, flags);
+ proto.defineProperty("jack.servlet_response", null, getMethod("getServletResponse"), null, flags);
}
private static Method getMethod(String name) throws NoSuchMethodException {
@@ -130,7 +145,7 @@
// FIXME: implement IO wrappers
if ("jack.input".equals(name)) {
try {
- return Context.toObject(req.getInputStream(), this);
+ return Context.toObject(request.getInputStream(), this);
} catch (IOException iox) {
return Undefined.instance;
}
Modified: helma-ng/trunk/src/org/helma/jack/JackServlet.java
===================================================================
--- helma-ng/trunk/src/org/helma/jack/JackServlet.java 2009-04-21 08:37:53 UTC (rev 9634)
+++ helma-ng/trunk/src/org/helma/jack/JackServlet.java 2009-04-21 08:37:57 UTC (rev 9635)
@@ -21,6 +21,7 @@
import org.helma.repository.FileRepository;
import org.helma.repository.WebappRepository;
import org.helma.javascript.RhinoEngine;
+import org.mozilla.javascript.Callable;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
@@ -34,9 +35,15 @@
String module, function;
RhinoEngine engine;
+ Callable callable;
public JackServlet(RhinoEngine engine) throws ServletException {
+ this(engine, null);
+ }
+
+ public JackServlet(RhinoEngine engine, Callable callable) throws ServletException {
this.engine = engine;
+ this.callable = callable;
try {
engine.defineHostClass(JackEnv.class);
} catch (Exception x) {
@@ -47,11 +54,11 @@
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
- module = getInitParam(config, "module", "app");
- function = getInitParam(config, "function", "handler");
+ module = getInitParam(config, "moduleName", "app");
+ function = getInitParam(config, "functionName", "handler");
if (engine == null) {
- String helmaHome = getInitParam(config, "home", "WEB-INF");
+ String helmaHome = getInitParam(config, "helmaHome", "WEB-INF");
String modulePath = getInitParam(config, "modulePath", "modules");
Repository home = new WebappRepository(config.getServletContext(), helmaHome);
@@ -72,8 +79,12 @@
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
- Object result = engine.invoke(module, function, new JackEnv(request));
- engine.invoke("helma/jack", "applyResponse", response, result);
+ JackEnv env = new JackEnv(request, response);
+ engine.invoke("helma/httpserver", "initRequest", env);
+ Object result = callable == null ?
+ engine.invoke(module, function, env) :
+ engine.invoke(callable, env);
+ engine.invoke("helma/httpserver", "commitResponse", env, result);
} catch (NoSuchMethodException x) {
throw new ServletException("Method not found", x);
}
Modified: helma-ng/trunk/src/org/helma/javascript/ReloadableScript.java
===================================================================
--- helma-ng/trunk/src/org/helma/javascript/ReloadableScript.java 2009-04-21 08:37:53 UTC (rev 9634)
+++ helma-ng/trunk/src/org/helma/javascript/ReloadableScript.java 2009-04-21 08:37:57 UTC (rev 9635)
@@ -190,7 +190,8 @@
protected synchronized Scriptable load(Scriptable prototype, Context cx)
throws JavaScriptException, IOException {
// check if we already came across the module in the current context/request
- Map<Trackable,Scriptable> modules = (Map<Trackable,Scriptable>) cx.getThreadLocal("modules");
+ Map<Trackable,Scriptable> modules =
+ (Map<Trackable,Scriptable>) cx.getThreadLocal("modules");
if (modules.containsKey(source)) {
return modules.get(source);
}
Modified: helma-ng/trunk/src/org/helma/javascript/RhinoEngine.java
===================================================================
--- helma-ng/trunk/src/org/helma/javascript/RhinoEngine.java 2009-04-21 08:37:53 UTC (rev 9634)
+++ helma-ng/trunk/src/org/helma/javascript/RhinoEngine.java 2009-04-21 08:37:57 UTC (rev 9635)
@@ -199,7 +199,7 @@
Scriptable module = loadModule(cx, moduleName, null);
Object function = ScriptableObject.getProperty(module, method);
if ((function == ScriptableObject.NOT_FOUND) || !(function instanceof Function)) {
- throw new NoSuchMethodException("Function " + method + "() not defined");
+ throw new NoSuchMethodException("Function " + method + " not defined");
}
retval = ((Function) function).call(cx, topLevelScope, module, args);
break;
@@ -226,6 +226,40 @@
}
}
+ public Object invoke(Callable callable, Object... args)
+ throws IOException, NoSuchMethodException {
+ Context cx = contextFactory.enterContext();
+ Object[] threadLocals = checkThreadLocals(cx);
+ try {
+ initArguments(args);
+ Object retval;
+ while (true) {
+ try {
+ retval = callable.call(cx, topLevelScope, null, args);
+ break;
+ } catch (JavaScriptException jsx) {
+ Scriptable thrown = jsx.getValue() instanceof Scriptable ?
+ (Scriptable) jsx.getValue() : null;
+ if (thrown != null && thrown.get("retry", thrown) == Boolean.TRUE) {
+ ((Map) cx.getThreadLocal("modules")).clear();
+ } else {
+ throw jsx;
+ }
+ } catch (RetryException retry) {
+ // request to try again
+ ((Map) cx.getThreadLocal("modules")).clear();
+ }
+ }
+ if (retval instanceof Wrapper) {
+ return ((Wrapper) retval).unwrap();
+ }
+ return retval;
+ } finally {
+ Context.exit();
+ resetThreadLocals(cx, threadLocals);
+ }
+ }
+
/**
* Return a shell scope for interactive evaluation
* @return a shell scope
Deleted: helma-ng/trunk/src/org/helma/web/HelmaServlet.java
Deleted: helma-ng/trunk/src/org/helma/web/Request.java
Deleted: helma-ng/trunk/src/org/helma/web/Response.java
Deleted: helma-ng/trunk/src/org/helma/web/Session.java