* Made most fields in RequestEvaluator private and use a synchronized getter to access them

* Minor change in ScriptingEngine interface
This commit is contained in:
hns 2005-09-13 13:40:31 +00:00
parent e05d4eabc8
commit f9a327a9e8
8 changed files with 122 additions and 80 deletions

View file

@ -1175,7 +1175,7 @@ public final class Application implements IPathElement, Runnable {
for (int i = 0; i < l; i++) {
RequestEvaluator r = (RequestEvaluator) allThreads.get(i);
if ((r != null) && (r.rtx == thread)) {
if ((r != null) && (r.getThread() == thread)) {
return r;
}
}

View file

@ -36,42 +36,42 @@ public final class RequestEvaluator implements Runnable {
static final int XMLRPC = 2; // via XML-RPC
static final int INTERNAL = 3; // generic function call, e.g. by scheduler
static final int EXTERNAL = 4; // function from script etc
public final Application app;
protected ScriptingEngine scriptingEngine;
public volatile RequestTrans req;
public volatile ResponseTrans res;
// the one and only transactor thread
volatile Transactor rtx;
// the type of request to be serviced,
// used to coordinate worker and waiter threads
volatile int reqtype;
// the object on which to invoke a function, if specified
Object thisObject;
// the method to be executed
String functionName;
// the session object associated with the current request
Session session;
// arguments passed to the function
Object[] args;
// the object path of the request we're evaluating
RequestPath requestPath;
// the result of the operation
Object result;
// the exception thrown by the evaluator, if any.
Exception exception;
// skin depth counter, used to avoid recursive skin rendering
protected int skinDepth;
private volatile RequestTrans req;
private volatile ResponseTrans res;
// the one and only transactor thread
private volatile Transactor rtx;
// the type of request to be serviced,
// used to coordinate worker and waiter threads
private volatile int reqtype;
// the object on which to invoke a function, if specified
private Object thisObject;
// the method to be executed
private String functionName;
// the session object associated with the current request
private Session session;
// arguments passed to the function
private Object[] args;
// the result of the operation
private Object result;
// the exception thrown by the evaluator, if any.
private Exception exception;
/**
* Create a new RequestEvaluator for this application.
*/
@ -131,8 +131,13 @@ public final class RequestEvaluator implements Runnable {
// object reference to ressolve request path
Object currentElement;
// Get req and res into local variables to avoid memory caching problems
// in unsynchronized method.
RequestTrans req = getRequest();
ResponseTrans res = getResponse();
// request path object
requestPath = new RequestPath(app);
RequestPath requestPath = new RequestPath(app);
int tries = 0;
boolean done = false;
@ -160,7 +165,7 @@ public final class RequestEvaluator implements Runnable {
root = app.getDataRoot();
initGlobals(root);
initGlobals(root, requestPath);
if (error != null) {
res.error = error;
@ -489,8 +494,6 @@ public final class RequestEvaluator implements Runnable {
Thread.sleep((long) (base + (Math.random() * base * 2)));
} catch (Exception ignore) {
}
continue;
} else {
abortTransaction();
@ -859,7 +862,7 @@ public final class RequestEvaluator implements Runnable {
* @param req
* @param session
*/
private void initObjects(RequestTrans req, Session session) {
private synchronized void initObjects(RequestTrans req, Session session) {
this.req = req;
this.reqtype = HTTP;
this.session = session;
@ -876,12 +879,12 @@ public final class RequestEvaluator implements Runnable {
* @param reqtype
* @param reqtypeName
*/
private void initObjects(String functionName, int reqtype, String reqtypeName) {
private synchronized void initObjects(String functionName, int reqtype, String reqtypeName) {
this.functionName = functionName;
this.reqtype = reqtype;
req = new RequestTrans(reqtypeName, functionName);
session = new Session(functionName, app);
res = new ResponseTrans(app, req);
res = new ResponseTrans(app, getRequest());
result = null;
exception = null;
}
@ -892,7 +895,8 @@ public final class RequestEvaluator implements Runnable {
* @param root
* @throws ScriptingException
*/
private void initGlobals(Object root) throws ScriptingException {
private synchronized void initGlobals(Object root, Object requestPath)
throws ScriptingException {
HashMap globals = new HashMap();
globals.put("root", root);
@ -930,12 +934,11 @@ public final class RequestEvaluator implements Runnable {
/**
* Null out some fields, mostly for the sake of garbage collection.
*/
public void recycle() {
public synchronized void recycle() {
res = null;
req = null;
session = null;
args = null;
requestPath = null;
result = null;
exception = null;
}
@ -989,4 +992,39 @@ public final class RequestEvaluator implements Runnable {
return scriptingEngine;
}
/**
* Get the request object for the current request.
*
* @return the request object
*/
public synchronized RequestTrans getRequest() {
return req;
}
/**
* Get the response object for the current request.
*
* @return the response object
*/
public synchronized ResponseTrans getResponse() {
return res;
}
/**
* Get the current transactor thread
*
* @return the current transactor thread
*/
public synchronized Transactor getThread() {
return rtx;
}
/**
* Return the current session
*
* @return the session for the current request
*/
public synchronized Session getSession() {
return session;
}
}

View file

@ -154,7 +154,7 @@ public final class Skin {
}
if (macros == null) {
reval.res.writeCharArray(source, 0, sourceLength);
reval.getResponse().writeCharArray(source, 0, sourceLength);
reval.skinDepth--;
return;
@ -170,7 +170,7 @@ public final class Skin {
for (int i = 0; i < macros.length; i++) {
if (macros[i].start > written) {
reval.res.writeCharArray(source, written, macros[i].start - written);
reval.getResponse().writeCharArray(source, written, macros[i].start - written);
}
macros[i].render(reval, thisObject, paramObject, handlerCache);
@ -178,7 +178,7 @@ public final class Skin {
}
if (written < sourceLength) {
reval.res.writeCharArray(source, written, sourceLength - written);
reval.getResponse().writeCharArray(source, written, sourceLength - written);
}
} finally {
reval.skinDepth--;
@ -403,7 +403,7 @@ public final class Skin {
}
if ((sandbox != null) && !sandbox.contains(fullName)) {
reval.res.write("[Macro " + fullName + " not allowed in sandbox]");
reval.getResponse().write("[Macro " + fullName + " not allowed in sandbox]");
return;
} else if ("response".equalsIgnoreCase(handler)) {
@ -468,7 +468,7 @@ public final class Skin {
// eiter because thisObject == null or the right object wasn't found
// in the object's parent path. Check if a matching macro handler
// is registered with the response object (res.handlers).
handlerObject = reval.res.getMacroHandlers().get(handler);
handlerObject = reval.getResponse().getMacroHandlers().get(handler);
}
// the macro handler object couldn't be found
@ -492,7 +492,7 @@ public final class Skin {
String funcName = name + "_macro";
if (reval.scriptingEngine.hasFunction(handlerObject, funcName)) {
StringBuffer buffer = reval.res.getBuffer();
StringBuffer buffer = reval.getResponse().getBuffer();
RenderParameters renderParams = defaultRenderParams;
// remember length of response buffer before calling macro
@ -551,18 +551,18 @@ public final class Skin {
// otherwise try property lookup
if (handlerObject == null) {
String msg = "[Macro unhandled: " + fullName + "]";
reval.res.write(" " + msg + " ");
reval.getResponse().write(" " + msg + " ");
app.logEvent(msg);
} else {
Object value = reval.scriptingEngine.get(handlerObject, name);
writeResponse(value, reval.res.getBuffer(), defaultRenderParams, true);
writeResponse(value, reval.getResponse().getBuffer(), defaultRenderParams, true);
}
}
} else {
String msg = "[Macro unhandled: " + fullName + "]";
reval.res.write(" " + msg + " ");
reval.getResponse().write(" " + msg + " ");
app.logEvent(msg);
}
@ -581,7 +581,7 @@ public final class Skin {
}
msg = "[Macro error in " + fullName + ": " + msg + "]";
reval.res.write(" " + msg + " ");
reval.getResponse().write(" " + msg + " ");
app.logEvent(msg);
}
}
@ -591,48 +591,48 @@ public final class Skin {
Object value = null;
if ("message".equals(name)) {
value = reval.res.message;
value = reval.getResponse().message;
} else if ("error".equals(name)) {
value = reval.res.error;
value = reval.getResponse().error;
}
if (value == null) {
value = reval.res.get(name);
value = reval.getResponse().get(name);
}
writeResponse(value, reval.res.getBuffer(), defaultRenderParams, true);
writeResponse(value, reval.getResponse().getBuffer(), defaultRenderParams, true);
}
private void renderFromRequest(RequestEvaluator reval)
throws UnsupportedEncodingException {
if (reval.req == null) {
if (reval.getRequest() == null) {
return;
}
Object value = reval.req.get(name);
Object value = reval.getRequest().get(name);
writeResponse(value, reval.res.getBuffer(), defaultRenderParams, true);
writeResponse(value, reval.getResponse().getBuffer(), defaultRenderParams, true);
}
private void renderFromSession(RequestEvaluator reval)
throws UnsupportedEncodingException {
if (reval.session == null) {
if (reval.getSession() == null) {
return;
}
Object value = reval.session.getCacheNode().getString(name);
Object value = reval.getSession().getCacheNode().getString(name);
writeResponse(value, reval.res.getBuffer(), defaultRenderParams, true);
writeResponse(value, reval.getResponse().getBuffer(), defaultRenderParams, true);
}
private void renderFromParam(RequestEvaluator reval, Map paramObject)
throws UnsupportedEncodingException {
if (paramObject == null) {
reval.res.write("[Macro error: Skin requires a parameter object]");
reval.getResponse().write("[Macro error: Skin requires a parameter object]");
} else {
Object value = paramObject.get(name);
writeResponse(value, reval.res.getBuffer(), defaultRenderParams, true);
writeResponse(value, reval.getResponse().getBuffer(), defaultRenderParams, true);
}
}

View file

@ -22,7 +22,7 @@ import helma.framework.core.RequestEvaluator;
import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
/**
* This is the interface that must be implemented to make a scripting environment
@ -68,7 +68,7 @@ public interface ScriptingEngine {
* evaluation is entered. The globals parameter contains the global values
* to be applied during this execution context.
*/
public void enterContext(HashMap globals) throws ScriptingException;
public void enterContext(Map globals) throws ScriptingException;
/**
* This method is called to let the scripting engine know that the current

View file

@ -18,6 +18,7 @@ package helma.scripting.rhino;
import helma.scripting.rhino.extensions.*;
import helma.framework.core.*;
import helma.framework.ResponseTrans;
import helma.objectmodel.db.*;
import helma.util.HtmlEncoder;
import helma.util.MimePart;
@ -178,10 +179,10 @@ public class GlobalObject extends ImporterTopLevel implements PropertyRecorder {
Map param = RhinoCore.getSkinParam(paramobj);
if (skin != null) {
reval.res.pushStringBuffer();
ResponseTrans res = reval.getResponse();
res.pushStringBuffer();
skin.render(reval, null, param);
return reval.res.popStringBuffer();
return res.popStringBuffer();
}
return "";

View file

@ -19,6 +19,7 @@ package helma.scripting.rhino;
import helma.scripting.ScriptingException;
import helma.scripting.ScriptingEngine;
import helma.framework.core.*;
import helma.framework.ResponseTrans;
import helma.objectmodel.*;
import helma.objectmodel.db.*;
import org.mozilla.javascript.*;
@ -311,10 +312,10 @@ public class HopObject extends ScriptableObject implements Wrapper, PropertyReco
checkNode();
if (skin != null) {
reval.res.pushStringBuffer();
ResponseTrans res = reval.getResponse();
res.pushStringBuffer();
skin.render(reval, node, param);
return reval.res.popStringBuffer();
return res.popStringBuffer();
}
return "";

View file

@ -17,6 +17,7 @@
package helma.scripting.rhino;
import helma.framework.core.*;
import helma.framework.ResponseTrans;
import org.mozilla.javascript.*;
import java.lang.reflect.Method;
import java.util.HashMap;
@ -124,10 +125,10 @@ public class JavaObject extends NativeJavaObject {
Map param = RhinoCore.getSkinParam(paramobj);
if (skin != null) {
reval.res.pushStringBuffer();
ResponseTrans res = reval.getResponse();
res.pushStringBuffer();
skin.render(reval, javaObject, param);
return reval.res.popStringBuffer();
return res.popStringBuffer();
}
return "";

View file

@ -187,7 +187,7 @@ public class RhinoEngine implements ScriptingEngine {
* evaluation is entered. The globals parameter contains the global values
* to be applied during this execution context.
*/
public void enterContext(HashMap globals) throws ScriptingException {
public void enterContext(Map globals) throws ScriptingException {
// set the thread filed in the FESI evaluator
// evaluator.thread = Thread.currentThread ();
// set globals on the global object
@ -524,7 +524,7 @@ public class RhinoEngine implements ScriptingEngine {
* Proxy method to RequestEvaluator.
*/
public ResponseTrans getResponse() {
return reval.res;
return reval.getResponse();
}
/**
@ -532,7 +532,7 @@ public class RhinoEngine implements ScriptingEngine {
* Proxy method to RequestEvaluator.
*/
public RequestTrans getRequest() {
return reval.req;
return reval.getRequest();
}
/**
@ -551,16 +551,17 @@ public class RhinoEngine implements ScriptingEngine {
*/
public Skin getSkin(String protoName, String skinName) throws IOException {
SkinKey key = new SkinKey(protoName, skinName);
ResponseTrans res = getResponse();
Skin skin = reval.res.getCachedSkin(key);
Skin skin = res.getCachedSkin(key);
if (skin == null) {
// retrieve res.skinpath, an array of objects that tell us where to look for skins
// (strings for directory names and INodes for internal, db-stored skinsets)
Object[] skinpath = reval.res.getSkinpath();
Object[] skinpath = res.getSkinpath();
RhinoCore.unwrapSkinpath(skinpath);
skin = app.getSkin(protoName, skinName, skinpath);
reval.res.cacheSkin(key, skin);
res.cacheSkin(key, skin);
}
return skin;
}