From f9a327a9e806533ce1db82632ca93c077777fa0a Mon Sep 17 00:00:00 2001 From: hns Date: Tue, 13 Sep 2005 13:40:31 +0000 Subject: [PATCH] * Made most fields in RequestEvaluator private and use a synchronized getter to access them * Minor change in ScriptingEngine interface --- src/helma/framework/core/Application.java | 2 +- .../framework/core/RequestEvaluator.java | 118 ++++++++++++------ src/helma/framework/core/Skin.java | 44 +++---- src/helma/scripting/ScriptingEngine.java | 4 +- src/helma/scripting/rhino/GlobalObject.java | 7 +- src/helma/scripting/rhino/HopObject.java | 7 +- src/helma/scripting/rhino/JavaObject.java | 7 +- src/helma/scripting/rhino/RhinoEngine.java | 13 +- 8 files changed, 122 insertions(+), 80 deletions(-) diff --git a/src/helma/framework/core/Application.java b/src/helma/framework/core/Application.java index 64618bdd..22eb5120 100644 --- a/src/helma/framework/core/Application.java +++ b/src/helma/framework/core/Application.java @@ -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; } } diff --git a/src/helma/framework/core/RequestEvaluator.java b/src/helma/framework/core/RequestEvaluator.java index 140042dc..a8e0560e 100644 --- a/src/helma/framework/core/RequestEvaluator.java +++ b/src/helma/framework/core/RequestEvaluator.java @@ -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; + } } diff --git a/src/helma/framework/core/Skin.java b/src/helma/framework/core/Skin.java index ce38d4fc..c33b3917 100644 --- a/src/helma/framework/core/Skin.java +++ b/src/helma/framework/core/Skin.java @@ -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); } } diff --git a/src/helma/scripting/ScriptingEngine.java b/src/helma/scripting/ScriptingEngine.java index b59e082c..a1503f84 100644 --- a/src/helma/scripting/ScriptingEngine.java +++ b/src/helma/scripting/ScriptingEngine.java @@ -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 diff --git a/src/helma/scripting/rhino/GlobalObject.java b/src/helma/scripting/rhino/GlobalObject.java index 51d135d3..7930445c 100644 --- a/src/helma/scripting/rhino/GlobalObject.java +++ b/src/helma/scripting/rhino/GlobalObject.java @@ -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 ""; diff --git a/src/helma/scripting/rhino/HopObject.java b/src/helma/scripting/rhino/HopObject.java index 248fc40f..1b8ca65c 100644 --- a/src/helma/scripting/rhino/HopObject.java +++ b/src/helma/scripting/rhino/HopObject.java @@ -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 ""; diff --git a/src/helma/scripting/rhino/JavaObject.java b/src/helma/scripting/rhino/JavaObject.java index 738cd4df..eb3a8401 100644 --- a/src/helma/scripting/rhino/JavaObject.java +++ b/src/helma/scripting/rhino/JavaObject.java @@ -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 ""; diff --git a/src/helma/scripting/rhino/RhinoEngine.java b/src/helma/scripting/rhino/RhinoEngine.java index b24e6543..afc4f052 100644 --- a/src/helma/scripting/rhino/RhinoEngine.java +++ b/src/helma/scripting/rhino/RhinoEngine.java @@ -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; }