* Remove synchronization problems in request timeout handling
* Implement skin parameter handling via res.handlers.param * Implement onResponse() callback * Slim down renderSkin method implementation * Implement res.buffer to access current page output * Implement res.stop() to stop request execution * Do not reuse per thread scope, create a new one for each request
This commit is contained in:
parent
e6c287b35f
commit
21838fe606
10 changed files with 236 additions and 290 deletions
|
@ -29,7 +29,7 @@ public class RedirectException extends Error {
|
||||||
/**
|
/**
|
||||||
* Creates a new RedirectException object.
|
* Creates a new RedirectException object.
|
||||||
*
|
*
|
||||||
* @param url ...
|
* @param url the URL
|
||||||
*/
|
*/
|
||||||
public RedirectException(String url) {
|
public RedirectException(String url) {
|
||||||
super("Redirection Request to " + url);
|
super("Redirection Request to " + url);
|
||||||
|
@ -37,29 +37,11 @@ public class RedirectException extends Error {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Return the URL to redirect to.
|
||||||
*
|
* @return the URL
|
||||||
* @return ...
|
|
||||||
*/
|
*/
|
||||||
public String getMessage() {
|
public String getUrl() {
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param s ...
|
|
||||||
*/
|
|
||||||
public void printStackTrace(java.io.PrintStream s) {
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param w ...
|
|
||||||
*/
|
|
||||||
public void printStackTrace(java.io.PrintWriter w) {
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,6 +58,16 @@ public class ResponseBean implements Serializable {
|
||||||
res.encodeXml(obj);
|
res.encodeXml(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write an object to the response buffer by converting it to a string
|
||||||
|
* and then encoding it for form/text area content use.
|
||||||
|
*
|
||||||
|
* @param obj the object to write to the response buffer
|
||||||
|
*/
|
||||||
|
public void encodeForm(Object obj) {
|
||||||
|
res.encodeForm(obj);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write an object to the response buffer by converting it to a string
|
* Write an object to the response buffer by converting it to a string
|
||||||
* and then HTML-formatting it.
|
* and then HTML-formatting it.
|
||||||
|
@ -88,6 +98,15 @@ public class ResponseBean implements Serializable {
|
||||||
res.forward(url);
|
res.forward(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Immediately stop processing the current request
|
||||||
|
*
|
||||||
|
* @throws RedirectException to immediately terminate the request
|
||||||
|
*/
|
||||||
|
public void stop() throws RedirectException {
|
||||||
|
res.redirect(null);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset the response object, clearing all content previously written to it
|
* Reset the response object, clearing all content previously written to it
|
||||||
*/
|
*/
|
||||||
|
@ -481,6 +500,15 @@ public class ResponseBean implements Serializable {
|
||||||
return res.popStringBuffer();
|
return res.popStringBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current response buffer as string.
|
||||||
|
*
|
||||||
|
* @return the response buffer as string
|
||||||
|
*/
|
||||||
|
public String getBuffer() {
|
||||||
|
return res.getBuffer().toString();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Commit changes made during the course of the current transaction
|
* Commit changes made during the course of the current transaction
|
||||||
* and start a new one
|
* and start a new one
|
||||||
|
|
|
@ -387,12 +387,24 @@ public final class RequestEvaluator implements Runnable {
|
||||||
ScriptingEngine.ARGS_WRAP_DEFAULT,
|
ScriptingEngine.ARGS_WRAP_DEFAULT,
|
||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// try calling onResponse() function on object before
|
||||||
|
// calling the actual action
|
||||||
|
scriptingEngine.invoke(currentElement,
|
||||||
|
"onResponse",
|
||||||
|
EMPTY_ARGS,
|
||||||
|
ScriptingEngine.ARGS_WRAP_DEFAULT,
|
||||||
|
false);
|
||||||
|
|
||||||
} catch (RedirectException redirect) {
|
} catch (RedirectException redirect) {
|
||||||
// if there is a message set, save it on the user object for the next request
|
// if there is a message set, save it on the user object for the next request
|
||||||
session.storeResponseMessages(res);
|
if (res.getRedirect() != null)
|
||||||
|
session.storeResponseMessages(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if we're still the one and only or if the waiting thread has given up on us already
|
// check if request is still valid, or if the requesting thread has stopped waiting already
|
||||||
|
if (localrtx != rtx)
|
||||||
|
return;
|
||||||
commitTransaction();
|
commitTransaction();
|
||||||
done = true;
|
done = true;
|
||||||
|
|
||||||
|
@ -438,8 +450,14 @@ public final class RequestEvaluator implements Runnable {
|
||||||
functionName, args,
|
functionName, args,
|
||||||
ScriptingEngine.ARGS_WRAP_XMLRPC,
|
ScriptingEngine.ARGS_WRAP_XMLRPC,
|
||||||
false);
|
false);
|
||||||
|
// check if request is still valid, or if the requesting thread has stopped waiting already
|
||||||
|
if (localrtx != rtx)
|
||||||
|
return;
|
||||||
commitTransaction();
|
commitTransaction();
|
||||||
} catch (Exception x) {
|
} catch (Exception x) {
|
||||||
|
// check if request is still valid, or if the requesting thread has stopped waiting already
|
||||||
|
if (localrtx != rtx)
|
||||||
|
return;
|
||||||
abortTransaction();
|
abortTransaction();
|
||||||
app.logError(txname + ": " + error, x);
|
app.logError(txname + ": " + error, x);
|
||||||
|
|
||||||
|
@ -466,8 +484,14 @@ public final class RequestEvaluator implements Runnable {
|
||||||
args,
|
args,
|
||||||
ScriptingEngine.ARGS_WRAP_DEFAULT,
|
ScriptingEngine.ARGS_WRAP_DEFAULT,
|
||||||
true);
|
true);
|
||||||
|
// check if request is still valid, or if the requesting thread has stopped waiting already
|
||||||
|
if (localrtx != rtx)
|
||||||
|
return;
|
||||||
commitTransaction();
|
commitTransaction();
|
||||||
} catch (Exception x) {
|
} catch (Exception x) {
|
||||||
|
// check if request is still valid, or if the requesting thread has stopped waiting already
|
||||||
|
if (localrtx != rtx)
|
||||||
|
return;
|
||||||
abortTransaction();
|
abortTransaction();
|
||||||
app.logError(txname + ": " + error, x);
|
app.logError(txname + ": " + error, x);
|
||||||
|
|
||||||
|
@ -487,6 +511,9 @@ public final class RequestEvaluator implements Runnable {
|
||||||
} catch (AbortException x) {
|
} catch (AbortException x) {
|
||||||
// res.abort() just aborts the transaction and
|
// res.abort() just aborts the transaction and
|
||||||
// leaves the response untouched
|
// leaves the response untouched
|
||||||
|
// check if request is still valid, or if the requesting thread has stopped waiting already
|
||||||
|
if (localrtx != rtx)
|
||||||
|
return;
|
||||||
abortTransaction();
|
abortTransaction();
|
||||||
done = true;
|
done = true;
|
||||||
} catch (ConcurrencyException x) {
|
} catch (ConcurrencyException x) {
|
||||||
|
@ -494,6 +521,9 @@ public final class RequestEvaluator implements Runnable {
|
||||||
|
|
||||||
if (++tries < 8) {
|
if (++tries < 8) {
|
||||||
// try again after waiting some period
|
// try again after waiting some period
|
||||||
|
// check if request is still valid, or if the requesting thread has stopped waiting already
|
||||||
|
if (localrtx != rtx)
|
||||||
|
return;
|
||||||
abortTransaction();
|
abortTransaction();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -508,6 +538,9 @@ public final class RequestEvaluator implements Runnable {
|
||||||
rtx = null;
|
rtx = null;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// check if request is still valid, or if the requesting thread has stopped waiting already
|
||||||
|
if (localrtx != rtx)
|
||||||
|
return;
|
||||||
abortTransaction();
|
abortTransaction();
|
||||||
|
|
||||||
if (error == null)
|
if (error == null)
|
||||||
|
@ -519,6 +552,9 @@ public final class RequestEvaluator implements Runnable {
|
||||||
}
|
}
|
||||||
} catch (Throwable x) {
|
} catch (Throwable x) {
|
||||||
String txname = localrtx.getTransactionName();
|
String txname = localrtx.getTransactionName();
|
||||||
|
// check if request is still valid, or if the requesting thread has stopped waiting already
|
||||||
|
if (localrtx != rtx)
|
||||||
|
return;
|
||||||
abortTransaction();
|
abortTransaction();
|
||||||
|
|
||||||
// If the transactor thread has been killed by the invoker thread we don't have to
|
// If the transactor thread has been killed by the invoker thread we don't have to
|
||||||
|
@ -581,6 +617,7 @@ public final class RequestEvaluator implements Runnable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called by the transactor thread when it has successfully fulfilled a request.
|
* Called by the transactor thread when it has successfully fulfilled a request.
|
||||||
|
* @throws Exception transaction couldn't be committed
|
||||||
*/
|
*/
|
||||||
synchronized void commitTransaction() throws Exception {
|
synchronized void commitTransaction() throws Exception {
|
||||||
Transactor localrtx = (Transactor) Thread.currentThread();
|
Transactor localrtx = (Transactor) Thread.currentThread();
|
||||||
|
@ -592,11 +629,17 @@ public final class RequestEvaluator implements Runnable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by the transactor thread when the request didn't terminate successfully.
|
||||||
|
*/
|
||||||
synchronized void abortTransaction() {
|
synchronized void abortTransaction() {
|
||||||
Transactor localrtx = (Transactor) Thread.currentThread();
|
Transactor localrtx = (Transactor) Thread.currentThread();
|
||||||
localrtx.abort();
|
localrtx.abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize and start the transactor thread.
|
||||||
|
*/
|
||||||
private synchronized void startTransactor() {
|
private synchronized void startTransactor() {
|
||||||
if (!app.isRunning()) {
|
if (!app.isRunning()) {
|
||||||
throw new ApplicationStoppedException();
|
throw new ApplicationStoppedException();
|
||||||
|
@ -653,11 +696,10 @@ public final class RequestEvaluator implements Runnable {
|
||||||
* waiting thread when it times out and stops waiting, or from an outside
|
* waiting thread when it times out and stops waiting, or from an outside
|
||||||
* thread. If currently active kill the request, otherwise just notify.
|
* thread. If currently active kill the request, otherwise just notify.
|
||||||
*/
|
*/
|
||||||
public synchronized void stopTransactor() {
|
synchronized boolean stopTransactor() {
|
||||||
Transactor t = rtx;
|
Transactor t = rtx;
|
||||||
|
|
||||||
rtx = null;
|
rtx = null;
|
||||||
|
boolean stopped = false;
|
||||||
if (t != null && t.isActive()) {
|
if (t != null && t.isActive()) {
|
||||||
// let the scripting engine know that the
|
// let the scripting engine know that the
|
||||||
// current transaction is being aborted.
|
// current transaction is being aborted.
|
||||||
|
@ -665,15 +707,17 @@ public final class RequestEvaluator implements Runnable {
|
||||||
scriptingEngine.abort();
|
scriptingEngine.abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
app.logEvent("Killing Thread " + t);
|
app.logEvent("Request timeout for thread " + t);
|
||||||
|
|
||||||
reqtype = NONE;
|
reqtype = NONE;
|
||||||
|
|
||||||
t.kill();
|
t.kill();
|
||||||
t.abort();
|
t.abort();
|
||||||
t.closeConnections();
|
t.closeConnections();
|
||||||
|
stopped = true;
|
||||||
}
|
}
|
||||||
notifyAll();
|
notifyAll();
|
||||||
|
return stopped;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -694,9 +738,7 @@ public final class RequestEvaluator implements Runnable {
|
||||||
startTransactor();
|
startTransactor();
|
||||||
wait(app.requestTimeout);
|
wait(app.requestTimeout);
|
||||||
|
|
||||||
if (reqtype != NONE) {
|
if (reqtype != NONE && stopTransactor()) {
|
||||||
app.logEvent("Stopping Thread for Request " + app.getName() + "/" + req.getPath());
|
|
||||||
stopTransactor();
|
|
||||||
res.reset();
|
res.reset();
|
||||||
res.reportError(app.getName(), "Request timed out");
|
res.reportError(app.getName(), "Request timed out");
|
||||||
}
|
}
|
||||||
|
@ -749,8 +791,7 @@ public final class RequestEvaluator implements Runnable {
|
||||||
startTransactor();
|
startTransactor();
|
||||||
wait(app.requestTimeout);
|
wait(app.requestTimeout);
|
||||||
|
|
||||||
if (reqtype != NONE) {
|
if (reqtype != NONE && stopTransactor()) {
|
||||||
stopTransactor();
|
|
||||||
exception = new RuntimeException("Request timed out");
|
exception = new RuntimeException("Request timed out");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -784,8 +825,7 @@ public final class RequestEvaluator implements Runnable {
|
||||||
startTransactor();
|
startTransactor();
|
||||||
wait();
|
wait();
|
||||||
|
|
||||||
if (reqtype != NONE) {
|
if (reqtype != NONE && stopTransactor()) {
|
||||||
stopTransactor();
|
|
||||||
exception = new RuntimeException("Request timed out");
|
exception = new RuntimeException("Request timed out");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -853,8 +893,7 @@ public final class RequestEvaluator implements Runnable {
|
||||||
startTransactor();
|
startTransactor();
|
||||||
wait(timeout);
|
wait(timeout);
|
||||||
|
|
||||||
if (reqtype != NONE) {
|
if (reqtype != NONE && stopTransactor()) {
|
||||||
stopTransactor();
|
|
||||||
exception = new RuntimeException("Request timed out");
|
exception = new RuntimeException("Request timed out");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -144,23 +144,46 @@ public final class Skin {
|
||||||
return new String(source, 0, sourceLength);
|
return new String(source, 0, sourceLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render this skin and return it as string
|
||||||
|
*/
|
||||||
|
public String renderAsString(RequestEvaluator reval, Object thisObject, Object paramObject)
|
||||||
|
throws RedirectException, UnsupportedEncodingException {
|
||||||
|
String result = "";
|
||||||
|
ResponseTrans res = reval.getResponse();
|
||||||
|
res.pushStringBuffer();
|
||||||
|
try {
|
||||||
|
render(reval, thisObject, paramObject);
|
||||||
|
} finally {
|
||||||
|
result = res.popStringBuffer();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render this skin
|
* Render this skin
|
||||||
*/
|
*/
|
||||||
public void render(RequestEvaluator reval, Object thisObject, Map paramObject)
|
public void render(RequestEvaluator reval, Object thisObject, Object paramObject)
|
||||||
throws RedirectException, UnsupportedEncodingException {
|
throws RedirectException, UnsupportedEncodingException {
|
||||||
// check for endless skin recursion
|
// check for endless skin recursion
|
||||||
if (++reval.skinDepth > 50) {
|
if (++reval.skinDepth > 50) {
|
||||||
throw new RuntimeException("Recursive skin invocation suspected");
|
throw new RuntimeException("Recursive skin invocation suspected");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ResponseTrans res = reval.getResponse();
|
||||||
|
|
||||||
if (macros == null) {
|
if (macros == null) {
|
||||||
reval.getResponse().write(source, 0, sourceLength);
|
res.write(source, 0, sourceLength);
|
||||||
reval.skinDepth--;
|
reval.skinDepth--;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// register param object, remember previous one to reset afterwards
|
||||||
|
Map handlers = res.getMacroHandlers();
|
||||||
|
Object previousParam = handlers.put("param", paramObject);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
int written = 0;
|
int written = 0;
|
||||||
Map handlerCache = null;
|
Map handlerCache = null;
|
||||||
|
@ -171,18 +194,23 @@ public final class Skin {
|
||||||
|
|
||||||
for (int i = 0; i < macros.length; i++) {
|
for (int i = 0; i < macros.length; i++) {
|
||||||
if (macros[i].start > written) {
|
if (macros[i].start > written) {
|
||||||
reval.getResponse().write(source, written, macros[i].start - written);
|
res.write(source, written, macros[i].start - written);
|
||||||
}
|
}
|
||||||
|
|
||||||
macros[i].render(reval, thisObject, paramObject, handlerCache);
|
macros[i].render(reval, thisObject, handlerCache);
|
||||||
written = macros[i].end;
|
written = macros[i].end;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (written < sourceLength) {
|
if (written < sourceLength) {
|
||||||
reval.getResponse().write(source, written, sourceLength - written);
|
res.write(source, written, sourceLength - written);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
reval.skinDepth--;
|
reval.skinDepth--;
|
||||||
|
if (previousParam == null) {
|
||||||
|
handlers.remove("param");
|
||||||
|
} else {
|
||||||
|
handlers.put("param", previousParam);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -395,8 +423,7 @@ public final class Skin {
|
||||||
/**
|
/**
|
||||||
* Render the macro given a handler object
|
* Render the macro given a handler object
|
||||||
*/
|
*/
|
||||||
public void render(RequestEvaluator reval, Object thisObject, Map paramObject,
|
public void render(RequestEvaluator reval, Object thisObject, Map handlerCache)
|
||||||
Map handlerCache)
|
|
||||||
throws RedirectException, UnsupportedEncodingException {
|
throws RedirectException, UnsupportedEncodingException {
|
||||||
// immediately return for comment macros
|
// immediately return for comment macros
|
||||||
if (isCommentMacro) {
|
if (isCommentMacro) {
|
||||||
|
@ -414,10 +441,6 @@ public final class Skin {
|
||||||
} else if ("request".equalsIgnoreCase(handler)) {
|
} else if ("request".equalsIgnoreCase(handler)) {
|
||||||
renderFromRequest(reval);
|
renderFromRequest(reval);
|
||||||
|
|
||||||
return;
|
|
||||||
} else if ("param".equalsIgnoreCase(handler)) {
|
|
||||||
renderFromParam(reval, paramObject);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
} else if ("session".equalsIgnoreCase(handler)) {
|
} else if ("session".equalsIgnoreCase(handler)) {
|
||||||
renderFromSession(reval);
|
renderFromSession(reval);
|
||||||
|
|
|
@ -161,19 +161,17 @@ public class Transactor extends Thread {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Returns true if a transaction is currently active.
|
||||||
*
|
* @return true if currently a transaction is active
|
||||||
* @return ...
|
|
||||||
*/
|
*/
|
||||||
public boolean isActive() {
|
public boolean isActive() {
|
||||||
return active;
|
return active;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Register a db connection with this transactor thread.
|
||||||
*
|
* @param src the db source
|
||||||
* @param src ...
|
* @param con the connection
|
||||||
* @param con ...
|
|
||||||
*/
|
*/
|
||||||
public void registerConnection(DbSource src, Connection con) {
|
public void registerConnection(DbSource src, Connection con) {
|
||||||
sqlConnections.put(src, con);
|
sqlConnections.put(src, con);
|
||||||
|
@ -182,11 +180,9 @@ public class Transactor extends Thread {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Get a db connection that was previously registered with this transactor thread.
|
||||||
*
|
* @param src the db source
|
||||||
* @param src ...
|
* @return the connection
|
||||||
*
|
|
||||||
* @return ...
|
|
||||||
*/
|
*/
|
||||||
public Connection getConnection(DbSource src) {
|
public Connection getConnection(DbSource src) {
|
||||||
Connection con = (Connection) sqlConnections.get(src);
|
Connection con = (Connection) sqlConnections.get(src);
|
||||||
|
@ -218,9 +214,7 @@ public class Transactor extends Thread {
|
||||||
public synchronized void begin(String name) throws Exception {
|
public synchronized void begin(String name) throws Exception {
|
||||||
if (killed) {
|
if (killed) {
|
||||||
throw new DatabaseException("Transaction started on killed thread");
|
throw new DatabaseException("Transaction started on killed thread");
|
||||||
}
|
} else if (active) {
|
||||||
|
|
||||||
if (active) {
|
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,10 +235,10 @@ public class Transactor extends Thread {
|
||||||
*/
|
*/
|
||||||
public synchronized void commit() throws Exception {
|
public synchronized void commit() throws Exception {
|
||||||
if (killed) {
|
if (killed) {
|
||||||
abort();
|
throw new DatabaseException("commit() called on killed transactor thread");
|
||||||
|
} else if (!active) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int inserted = 0;
|
int inserted = 0;
|
||||||
int updated = 0;
|
int updated = 0;
|
||||||
int deleted = 0;
|
int deleted = 0;
|
||||||
|
@ -396,7 +390,6 @@ public class Transactor extends Thread {
|
||||||
|
|
||||||
// clear the node collections
|
// clear the node collections
|
||||||
recycle();
|
recycle();
|
||||||
|
|
||||||
// close any JDBC connections associated with this transactor thread
|
// close any JDBC connections associated with this transactor thread
|
||||||
closeConnections();
|
closeConnections();
|
||||||
|
|
||||||
|
@ -420,34 +413,39 @@ public class Transactor extends Thread {
|
||||||
* Kill this transaction thread. Used as last measure only.
|
* Kill this transaction thread. Used as last measure only.
|
||||||
*/
|
*/
|
||||||
public synchronized void kill() {
|
public synchronized void kill() {
|
||||||
killed = true;
|
killed = true;
|
||||||
|
interrupt();
|
||||||
// The thread is told to stop by setting the thread flag in the EcmaScript
|
|
||||||
// evaluator, so we can hope that it stops without doing anything else.
|
|
||||||
try {
|
|
||||||
join(500);
|
|
||||||
} catch (InterruptedException ir) {
|
|
||||||
// interrupted by other thread
|
|
||||||
}
|
|
||||||
|
|
||||||
// Interrupt the thread if it has not noticed the flag (e.g. because it is busy
|
// Interrupt the thread if it has not noticed the flag (e.g. because it is busy
|
||||||
// reading from a network socket).
|
// reading from a network socket).
|
||||||
if (isAlive()) {
|
if (isAlive()) {
|
||||||
interrupt();
|
interrupt();
|
||||||
|
try {
|
||||||
|
join(1000);
|
||||||
|
} catch (InterruptedException ir) {
|
||||||
|
// interrupted by other thread
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
if (isAlive() && "true".equals(nmgr.app.getProperty("requestTimeoutStop", "true"))) {
|
||||||
join(1000);
|
// still running - check if we ought to stop() it
|
||||||
} catch (InterruptedException ir) {
|
try {
|
||||||
// interrupted by other thread
|
Thread.sleep(2000);
|
||||||
}
|
if (isAlive()) {
|
||||||
|
// thread is still running, pull emergency break
|
||||||
|
nmgr.app.logEvent("Stopping Thread for Transactor " + this);
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
} catch (InterruptedException ir) {
|
||||||
|
// interrupted by other thread
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Closes all open JDBC connections
|
||||||
*/
|
*/
|
||||||
public void closeConnections() {
|
public void closeConnections() {
|
||||||
// nmgr.app.logEvent("Cleaning up Transactor thread");
|
|
||||||
if (sqlConnections != null) {
|
if (sqlConnections != null) {
|
||||||
for (Iterator i = sqlConnections.values().iterator(); i.hasNext();) {
|
for (Iterator i = sqlConnections.values().iterator(); i.hasNext();) {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -39,7 +39,7 @@ import java.io.*;
|
||||||
public class GlobalObject extends ImporterTopLevel implements PropertyRecorder {
|
public class GlobalObject extends ImporterTopLevel implements PropertyRecorder {
|
||||||
Application app;
|
Application app;
|
||||||
RhinoCore core;
|
RhinoCore core;
|
||||||
GlobalObject sharedGlobal = null;
|
boolean isThreadScope = false;
|
||||||
|
|
||||||
// fields to implement PropertyRecorder
|
// fields to implement PropertyRecorder
|
||||||
private volatile boolean isRecording = false;
|
private volatile boolean isRecording = false;
|
||||||
|
@ -51,12 +51,12 @@ public class GlobalObject extends ImporterTopLevel implements PropertyRecorder {
|
||||||
* @param core ...
|
* @param core ...
|
||||||
* @param app ...
|
* @param app ...
|
||||||
*/
|
*/
|
||||||
public GlobalObject(RhinoCore core, Application app, boolean perThread) {
|
public GlobalObject(RhinoCore core, Application app, boolean isThreadScope) {
|
||||||
this.core = core;
|
this.core = core;
|
||||||
this.app = app;
|
this.app = app;
|
||||||
if (perThread) {
|
this.isThreadScope = isThreadScope;
|
||||||
sharedGlobal = core.global;
|
if (isThreadScope) {
|
||||||
setPrototype(sharedGlobal);
|
setPrototype(core.global);
|
||||||
setParentScope(null);
|
setParentScope(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,10 +64,8 @@ public class GlobalObject extends ImporterTopLevel implements PropertyRecorder {
|
||||||
/**
|
/**
|
||||||
* Initializes the global object. This is only done for the shared
|
* Initializes the global object. This is only done for the shared
|
||||||
* global objects not the per-thread ones.
|
* global objects not the per-thread ones.
|
||||||
*
|
|
||||||
* @throws PropertyException ...
|
|
||||||
*/
|
*/
|
||||||
public void init() throws PropertyException {
|
public void init() {
|
||||||
String[] globalFuncs = {
|
String[] globalFuncs = {
|
||||||
"renderSkin", "renderSkinAsString", "getProperty",
|
"renderSkin", "renderSkinAsString", "getProperty",
|
||||||
"authenticate", "createSkin", "format", "encode",
|
"authenticate", "createSkin", "format", "encode",
|
||||||
|
@ -127,18 +125,10 @@ public class GlobalObject extends ImporterTopLevel implements PropertyRecorder {
|
||||||
if (isRecording) {
|
if (isRecording) {
|
||||||
changedProperties.add(name);
|
changedProperties.add(name);
|
||||||
}
|
}
|
||||||
// check if this is a per-thread scope instance
|
// expose thread scope as global variable "global"
|
||||||
if (sharedGlobal != null) {
|
if (isThreadScope && "global".equals(name)) {
|
||||||
// make thread scope accessible as "global"
|
return this;
|
||||||
if ("global".equals(name)) {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
// use synchronized get on fast changing per-thread scopes just to be sure
|
|
||||||
synchronized(this) {
|
|
||||||
return super.get(name, start);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// we're the shared scope
|
|
||||||
return super.get(name, start);
|
return super.get(name, start);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,22 +143,11 @@ public class GlobalObject extends ImporterTopLevel implements PropertyRecorder {
|
||||||
public boolean renderSkin(Object skinobj, Object paramobj)
|
public boolean renderSkin(Object skinobj, Object paramobj)
|
||||||
throws UnsupportedEncodingException, IOException {
|
throws UnsupportedEncodingException, IOException {
|
||||||
RhinoEngine engine = RhinoEngine.getRhinoEngine();
|
RhinoEngine engine = RhinoEngine.getRhinoEngine();
|
||||||
Skin skin;
|
Skin skin = engine.toSkin(skinobj, "global");
|
||||||
|
|
||||||
if (skinobj instanceof Wrapper) {
|
|
||||||
skinobj = ((Wrapper) skinobj).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (skinobj instanceof Skin) {
|
|
||||||
skin = (Skin) skinobj;
|
|
||||||
} else {
|
|
||||||
skin = engine.getSkin("global", skinobj.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
Map param = RhinoCore.getSkinParam(paramobj);
|
|
||||||
|
|
||||||
if (skin != null) {
|
if (skin != null) {
|
||||||
skin.render(engine.reval, null, param);
|
skin.render(engine.reval, null,
|
||||||
|
(paramobj == Undefined.instance) ? null : paramobj);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -185,25 +164,11 @@ public class GlobalObject extends ImporterTopLevel implements PropertyRecorder {
|
||||||
public String renderSkinAsString(Object skinobj, Object paramobj)
|
public String renderSkinAsString(Object skinobj, Object paramobj)
|
||||||
throws UnsupportedEncodingException, IOException {
|
throws UnsupportedEncodingException, IOException {
|
||||||
RhinoEngine engine = RhinoEngine.getRhinoEngine();
|
RhinoEngine engine = RhinoEngine.getRhinoEngine();
|
||||||
Skin skin;
|
Skin skin = engine.toSkin(skinobj, "global");
|
||||||
|
|
||||||
if (skinobj instanceof Wrapper) {
|
|
||||||
skinobj = ((Wrapper) skinobj).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (skinobj instanceof Skin) {
|
|
||||||
skin = (Skin) skinobj;
|
|
||||||
} else {
|
|
||||||
skin = engine.getSkin("global", skinobj.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
Map param = RhinoCore.getSkinParam(paramobj);
|
|
||||||
|
|
||||||
if (skin != null) {
|
if (skin != null) {
|
||||||
ResponseTrans res = engine.getResponse();
|
return skin.renderAsString(engine.reval, null,
|
||||||
res.pushStringBuffer();
|
(paramobj == Undefined.instance) ? null : paramobj);
|
||||||
skin.render(engine.reval, null, param);
|
|
||||||
return res.popStringBuffer();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return "";
|
return "";
|
||||||
|
@ -671,7 +636,9 @@ public class GlobalObject extends ImporterTopLevel implements PropertyRecorder {
|
||||||
}
|
}
|
||||||
String str = (String) args[i];
|
String str = (String) args[i];
|
||||||
if (obj.has(str, obj)) {
|
if (obj.has(str, obj)) {
|
||||||
obj.setAttributes(str, obj.getAttributes(str) | DONTENUM);
|
int attr = obj.getAttributes(str);
|
||||||
|
if ((attr & PERMANENT) == 0)
|
||||||
|
obj.setAttributes(str, attr | DONTENUM);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -719,6 +686,6 @@ public class GlobalObject extends ImporterTopLevel implements PropertyRecorder {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return sharedGlobal == null ? "[Shared Scope]" : "[Thread Scope]";
|
return isThreadScope ? "[Thread Scope]" : "[Shared Scope]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -197,24 +197,13 @@ public class HopObject extends ScriptableObject implements Wrapper, PropertyReco
|
||||||
public boolean jsFunction_renderSkin(Object skinobj, Object paramobj)
|
public boolean jsFunction_renderSkin(Object skinobj, Object paramobj)
|
||||||
throws UnsupportedEncodingException, IOException {
|
throws UnsupportedEncodingException, IOException {
|
||||||
RhinoEngine engine = RhinoEngine.getRhinoEngine();
|
RhinoEngine engine = RhinoEngine.getRhinoEngine();
|
||||||
Skin skin;
|
Skin skin = engine.toSkin(skinobj, className);
|
||||||
|
|
||||||
if (skinobj instanceof Wrapper) {
|
|
||||||
skinobj = ((Wrapper) skinobj).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (skinobj instanceof Skin) {
|
|
||||||
skin = (Skin) skinobj;
|
|
||||||
} else {
|
|
||||||
skin = engine.getSkin(className, skinobj.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
Map param = RhinoCore.getSkinParam(paramobj);
|
|
||||||
|
|
||||||
checkNode();
|
checkNode();
|
||||||
|
|
||||||
if (skin != null) {
|
if (skin != null) {
|
||||||
skin.render(engine.reval, node, param);
|
skin.render(engine.reval, node,
|
||||||
|
(paramobj == Undefined.instance) ? null : paramobj);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -278,27 +267,13 @@ public class HopObject extends ScriptableObject implements Wrapper, PropertyReco
|
||||||
public String jsFunction_renderSkinAsString(Object skinobj, Object paramobj)
|
public String jsFunction_renderSkinAsString(Object skinobj, Object paramobj)
|
||||||
throws UnsupportedEncodingException, IOException {
|
throws UnsupportedEncodingException, IOException {
|
||||||
RhinoEngine engine = RhinoEngine.getRhinoEngine();
|
RhinoEngine engine = RhinoEngine.getRhinoEngine();
|
||||||
Skin skin;
|
Skin skin = engine.toSkin(skinobj, className);
|
||||||
|
Object param = paramobj == Undefined.instance ? null : paramobj;
|
||||||
if (skinobj instanceof Wrapper) {
|
|
||||||
skinobj = ((Wrapper) skinobj).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (skinobj instanceof Skin) {
|
|
||||||
skin = (Skin) skinobj;
|
|
||||||
} else {
|
|
||||||
skin = engine.getSkin(className, skinobj.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
Map param = RhinoCore.getSkinParam(paramobj);
|
|
||||||
|
|
||||||
checkNode();
|
checkNode();
|
||||||
|
|
||||||
if (skin != null) {
|
if (skin != null) {
|
||||||
ResponseTrans res = engine.getResponse();
|
return skin.renderAsString(engine.reval, node,
|
||||||
res.pushStringBuffer();
|
(paramobj == Undefined.instance) ? null : paramobj);
|
||||||
skin.render(engine.reval, node, param);
|
|
||||||
return res.popStringBuffer();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return "";
|
return "";
|
||||||
|
|
|
@ -78,22 +78,11 @@ public class JavaObject extends NativeJavaObject {
|
||||||
public boolean renderSkin(Object skinobj, Object paramobj)
|
public boolean renderSkin(Object skinobj, Object paramobj)
|
||||||
throws UnsupportedEncodingException, IOException {
|
throws UnsupportedEncodingException, IOException {
|
||||||
RhinoEngine engine = RhinoEngine.getRhinoEngine();
|
RhinoEngine engine = RhinoEngine.getRhinoEngine();
|
||||||
Skin skin;
|
Skin skin = engine.toSkin(skinobj, protoName);
|
||||||
|
|
||||||
if (skinobj instanceof Wrapper) {
|
|
||||||
skinobj = ((Wrapper) skinobj).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (skinobj instanceof Skin) {
|
|
||||||
skin = (Skin) skinobj;
|
|
||||||
} else {
|
|
||||||
skin = engine.getSkin(protoName, skinobj.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
Map param = RhinoCore.getSkinParam(paramobj);
|
|
||||||
|
|
||||||
if (skin != null) {
|
if (skin != null) {
|
||||||
skin.render(engine.reval, javaObject, param);
|
skin.render(engine.reval, javaObject,
|
||||||
|
(paramobj == Undefined.instance) ? null : paramobj);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -110,25 +99,11 @@ public class JavaObject extends NativeJavaObject {
|
||||||
public String renderSkinAsString(Object skinobj, Object paramobj)
|
public String renderSkinAsString(Object skinobj, Object paramobj)
|
||||||
throws UnsupportedEncodingException, IOException {
|
throws UnsupportedEncodingException, IOException {
|
||||||
RhinoEngine engine = RhinoEngine.getRhinoEngine();
|
RhinoEngine engine = RhinoEngine.getRhinoEngine();
|
||||||
Skin skin;
|
Skin skin = engine.toSkin(skinobj, protoName);
|
||||||
|
|
||||||
if (skinobj instanceof Wrapper) {
|
|
||||||
skinobj = ((Wrapper) skinobj).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (skinobj instanceof Skin) {
|
|
||||||
skin = (Skin) skinobj;
|
|
||||||
} else {
|
|
||||||
skin = engine.getSkin(protoName, skinobj.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
Map param = RhinoCore.getSkinParam(paramobj);
|
|
||||||
|
|
||||||
if (skin != null) {
|
if (skin != null) {
|
||||||
ResponseTrans res = engine.getResponse();
|
return skin.renderAsString(engine.reval, javaObject,
|
||||||
res.pushStringBuffer();
|
(paramobj == Undefined.instance) ? null : paramobj);
|
||||||
skin.render(engine.reval, javaObject, param);
|
|
||||||
return res.popStringBuffer();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return "";
|
return "";
|
||||||
|
|
|
@ -635,7 +635,7 @@ public final class RhinoCore implements ScopeProvider {
|
||||||
return hobj;
|
return hobj;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String postProcessHref(Object obj, String protoName, String basicHref)
|
protected String postProcessHref(Object obj, String protoName, String href)
|
||||||
throws UnsupportedEncodingException, IOException {
|
throws UnsupportedEncodingException, IOException {
|
||||||
// check if the app.properties specify a href-function to post-process the
|
// check if the app.properties specify a href-function to post-process the
|
||||||
// basic href.
|
// basic href.
|
||||||
|
@ -655,7 +655,7 @@ public final class RhinoCore implements ScopeProvider {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
result = eng.invoke(handler, hrefFunction,
|
result = eng.invoke(handler, hrefFunction,
|
||||||
new Object[] { basicHref },
|
new Object[] {href},
|
||||||
ScriptingEngine.ARGS_WRAP_DEFAULT,
|
ScriptingEngine.ARGS_WRAP_DEFAULT,
|
||||||
false);
|
false);
|
||||||
} catch (ScriptingException x) {
|
} catch (ScriptingException x) {
|
||||||
|
@ -667,7 +667,7 @@ public final class RhinoCore implements ScopeProvider {
|
||||||
" returned null");
|
" returned null");
|
||||||
}
|
}
|
||||||
|
|
||||||
basicHref = result.toString();
|
href = result.toString();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
handler = app.getParentElement(handler);
|
handler = app.getParentElement(handler);
|
||||||
|
@ -696,23 +696,17 @@ public final class RhinoCore implements ScopeProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (skin != null) {
|
if (skin != null) {
|
||||||
|
Scriptable param = Context.getCurrentContext().newObject(global);
|
||||||
|
param.put("path", param, href);
|
||||||
|
href = skin.renderAsString(eng.getRequestEvaluator(), handler, param);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
handler = app.getParentElement(handler);
|
handler = app.getParentElement(handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (skin != null) {
|
|
||||||
eng.getResponse().pushStringBuffer();
|
|
||||||
HashMap param = new HashMap();
|
|
||||||
param.put("path", basicHref);
|
|
||||||
skin.render(eng.getRequestEvaluator(), handler, param);
|
|
||||||
|
|
||||||
basicHref = eng.getResponse().popStringBuffer().trim();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return basicHref;
|
return href;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -741,30 +735,6 @@ public final class RhinoCore implements ScopeProvider {
|
||||||
return skinpath;
|
return skinpath;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static Map getSkinParam(Object paramobj) {
|
|
||||||
Map param = null;
|
|
||||||
|
|
||||||
if ((paramobj != null) && (paramobj != Undefined.instance)) {
|
|
||||||
param = new HashMap();
|
|
||||||
|
|
||||||
if (paramobj instanceof Scriptable) {
|
|
||||||
Scriptable sp = (Scriptable) paramobj;
|
|
||||||
Object[] ids = sp.getIds();
|
|
||||||
|
|
||||||
for (int i = 0; i < ids.length; i++) {
|
|
||||||
Object obj = sp.get(ids[i].toString(), sp);
|
|
||||||
if (obj instanceof Wrapper) {
|
|
||||||
param.put(ids[i], ((Wrapper) obj).unwrap());
|
|
||||||
} else if (obj != Undefined.instance) {
|
|
||||||
param.put(ids[i], obj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return param;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a code resource to a given prototype by immediately compiling and evaluating it.
|
* Add a code resource to a given prototype by immediately compiling and evaluating it.
|
||||||
*
|
*
|
||||||
|
|
|
@ -58,15 +58,11 @@ public class RhinoEngine implements ScriptingEngine {
|
||||||
// the rhino core
|
// the rhino core
|
||||||
RhinoCore core;
|
RhinoCore core;
|
||||||
|
|
||||||
// remember global variables from last invokation to be able to
|
|
||||||
// do lazy cleanup
|
|
||||||
Map lastGlobals = null;
|
|
||||||
|
|
||||||
// the global vars set by extensions
|
// the global vars set by extensions
|
||||||
HashMap extensionGlobals;
|
HashMap extensionGlobals;
|
||||||
|
|
||||||
// the thread currently running this engine
|
// the thread currently running this engine
|
||||||
Thread thread;
|
volatile Thread thread;
|
||||||
|
|
||||||
// thread local engine registry
|
// thread local engine registry
|
||||||
static ThreadLocal engines = new ThreadLocal();
|
static ThreadLocal engines = new ThreadLocal();
|
||||||
|
@ -92,8 +88,6 @@ public class RhinoEngine implements ScriptingEngine {
|
||||||
context = core.contextFactory.enter();
|
context = core.contextFactory.enter();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
global = new GlobalObject(core, app, true);
|
|
||||||
|
|
||||||
extensionGlobals = new HashMap();
|
extensionGlobals = new HashMap();
|
||||||
|
|
||||||
if (Server.getServer() != null) {
|
if (Server.getServer() != null) {
|
||||||
|
@ -153,13 +147,13 @@ public class RhinoEngine implements ScriptingEngine {
|
||||||
* This method is called before an execution context is entered to let the
|
* This method is called before an execution context is entered to let the
|
||||||
* engine know it should update its prototype information.
|
* engine know it should update its prototype information.
|
||||||
*/
|
*/
|
||||||
public void updatePrototypes() throws IOException {
|
public synchronized void updatePrototypes() throws IOException {
|
||||||
// remember the current thread as our thread - we do this here so
|
// remember the current thread as our thread - we do this here so
|
||||||
// the thread is already set when the RequestEvaluator calls
|
// the thread is already set when the RequestEvaluator calls
|
||||||
// Application.getDataRoot(), which may result in a function invocation
|
// Application.getDataRoot(), which may result in a function invocation
|
||||||
// (chicken and egg problem, kind of)
|
// (chicken and egg problem, kind of)
|
||||||
thread = Thread.currentThread();
|
thread = Thread.currentThread();
|
||||||
|
global = new GlobalObject(core, app, true);
|
||||||
context = core.contextFactory.enter();
|
context = core.contextFactory.enter();
|
||||||
|
|
||||||
if (core.hasTracer) {
|
if (core.hasTracer) {
|
||||||
|
@ -182,30 +176,26 @@ public class RhinoEngine implements ScriptingEngine {
|
||||||
thread = Thread.currentThread();
|
thread = Thread.currentThread();
|
||||||
|
|
||||||
// set globals on the global object
|
// set globals on the global object
|
||||||
if (globals != lastGlobals) {
|
// add globals from extensions
|
||||||
// add globals from extensions
|
globals.putAll(extensionGlobals);
|
||||||
globals.putAll(extensionGlobals);
|
// loop through global vars and set them
|
||||||
// loop through global vars and set them
|
for (Iterator i = globals.keySet().iterator(); i.hasNext();) {
|
||||||
for (Iterator i = globals.keySet().iterator(); i.hasNext();) {
|
String k = (String) i.next();
|
||||||
String k = (String) i.next();
|
Object v = globals.get(k);
|
||||||
Object v = globals.get(k);
|
Scriptable scriptable;
|
||||||
Scriptable scriptable;
|
|
||||||
|
|
||||||
// create a special wrapper for the path object.
|
// create a special wrapper for the path object.
|
||||||
// other objects are wrapped in the default way.
|
// other objects are wrapped in the default way.
|
||||||
if (v == null) {
|
if (v == null) {
|
||||||
continue;
|
continue;
|
||||||
} else if (v instanceof RequestPath) {
|
} else if (v instanceof RequestPath) {
|
||||||
scriptable = new PathWrapper((RequestPath) v, core);
|
scriptable = new PathWrapper((RequestPath) v, core);
|
||||||
scriptable.setPrototype(core.pathProto);
|
scriptable.setPrototype(core.pathProto);
|
||||||
} else {
|
} else {
|
||||||
scriptable = Context.toObject(v, global);
|
scriptable = Context.toObject(v, global);
|
||||||
}
|
|
||||||
|
|
||||||
global.put(k, global, scriptable);
|
|
||||||
}
|
}
|
||||||
// remember the globals set on this evaluator
|
|
||||||
lastGlobals = globals;
|
global.put(k, global, scriptable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,19 +208,7 @@ public class RhinoEngine implements ScriptingEngine {
|
||||||
engines.set(null);
|
engines.set(null);
|
||||||
core.contextFactory.exit();
|
core.contextFactory.exit();
|
||||||
thread = null;
|
thread = null;
|
||||||
|
global = null;
|
||||||
// loop through previous globals and unset them, if necessary.
|
|
||||||
if (lastGlobals != null) {
|
|
||||||
for (Iterator i = lastGlobals.keySet().iterator(); i.hasNext();) {
|
|
||||||
String g = (String) i.next();
|
|
||||||
try {
|
|
||||||
global.delete(g);
|
|
||||||
} catch (Exception x) {
|
|
||||||
app.logEvent("Error unsetting global property: " + g);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lastGlobals = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -342,21 +320,17 @@ public class RhinoEngine implements ScriptingEngine {
|
||||||
* Let the evaluator know that the current evaluation has been
|
* Let the evaluator know that the current evaluation has been
|
||||||
* aborted.
|
* aborted.
|
||||||
*/
|
*/
|
||||||
public synchronized void abort() {
|
public void abort() {
|
||||||
// current request has been aborted.
|
// current request has been aborted.
|
||||||
Thread t = thread;
|
Thread t = thread;
|
||||||
|
// set thread to null
|
||||||
|
thread = null;
|
||||||
if (t != null && t.isAlive()) {
|
if (t != null && t.isAlive()) {
|
||||||
t.interrupt();
|
t.interrupt();
|
||||||
if ("true".equals(app.getProperty("requestTimeoutStop", "true"))) {
|
try {
|
||||||
try {
|
t.join(1000);
|
||||||
Thread.sleep(5000);
|
} catch (InterruptedException ir) {
|
||||||
if (t.isAlive()) {
|
// interrupted by other thread
|
||||||
// thread is still running, gotta stop it.
|
|
||||||
t.stop();
|
|
||||||
}
|
|
||||||
} catch (InterruptedException i) {
|
|
||||||
// interrupted, ignore
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -552,6 +526,21 @@ public class RhinoEngine implements ScriptingEngine {
|
||||||
return core;
|
return core;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try to get a skin from the parameter object.
|
||||||
|
*/
|
||||||
|
public Skin toSkin(Object skinobj, String protoName) throws IOException {
|
||||||
|
if (skinobj instanceof Wrapper) {
|
||||||
|
skinobj = ((Wrapper) skinobj).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (skinobj instanceof Skin) {
|
||||||
|
return (Skin) skinobj;
|
||||||
|
} else {
|
||||||
|
return getSkin(protoName, skinobj.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a skin for the given prototype and skin name. This method considers the
|
* Get a skin for the given prototype and skin name. This method considers the
|
||||||
* skinpath set in the current response object and does per-response skin
|
* skinpath set in the current response object and does per-response skin
|
||||||
|
|
Loading…
Add table
Reference in a new issue