use of org.directwebremoting.extend.RealScriptSession in project ma-core-public by infiniteautomation.
the class BaseCallMarshaller method marshallOutbound.
/* (non-Javadoc)
* @see org.directwebremoting.Marshaller#marshallOutbound(org.directwebremoting.Replies, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
public void marshallOutbound(Replies replies, HttpServletRequest request, HttpServletResponse response) throws IOException {
// Get the output stream and setup the mimetype
response.setContentType(getOutboundMimeType());
PrintWriter out;
if (log.isDebugEnabled()) {
// This might be considered evil - altering the program flow
// depending on the log status, however DebuggingPrintWriter is
// very thin and only about logging
out = new DebuggingPrintWriter("", response.getWriter());
} else {
out = response.getWriter();
}
// The conduit to pass on reverse ajax scripts
ScriptConduit conduit = new CallScriptConduit(out);
// Setup a debugging prefix
if (out instanceof DebuggingPrintWriter) {
DebuggingPrintWriter dpw = (DebuggingPrintWriter) out;
dpw.setPrefix("out(" + conduit.hashCode() + "): ");
}
// Send the script prefix (if any)
sendOutboundScriptPrefix(out, replies.getBatchId());
// From the call to addScriptConduit() there could be 2 threads writing
// to 'out' so we synchronize on 'out' to make sure there are no
// clashes
RealScriptSession scriptSession = (RealScriptSession) WebContextFactory.get().getScriptSession();
out.println(ProtocolConstants.SCRIPT_CALL_INSERT);
scriptSession.writeScripts(conduit);
out.println(ProtocolConstants.SCRIPT_CALL_REPLY);
String batchId = replies.getBatchId();
for (int i = 0; i < replies.getReplyCount(); i++) {
Reply reply = replies.getReply(i);
String callId = reply.getCallId();
try {
// The existance of a throwable indicates that something went wrong
if (reply.getThrowable() != null) {
Throwable ex = reply.getThrowable();
EnginePrivate.remoteHandleException(conduit, batchId, callId, ex);
log.warn("--Erroring: batchId[" + batchId + "] message[" + ex.toString() + ']');
} else {
Object data = reply.getReply();
EnginePrivate.remoteHandleCallback(conduit, batchId, callId, data);
}
} catch (IOException ex) {
// We're a bit stuck we died half way through writing so
// we can't be sure the browser can react to the failure.
// Since we can no longer do output we just log and end
log.error("--Output Error: batchId[" + batchId + "] message[" + ex.toString() + ']', ex);
} catch (MarshallException ex) {
EnginePrivate.remoteHandleMarshallException(conduit, batchId, callId, ex);
log.warn("--MarshallException: batchId=" + batchId + " class=" + ex.getConversionType().getName(), ex);
} catch (Exception ex) {
// This is a bit of a "this can't happen" case so I am a bit
// nervous about sending the exception to the client, but we
// want to avoid silently dying so we need to do something.
EnginePrivate.remoteHandleException(conduit, batchId, callId, ex);
log.error("--MarshallException: batchId=" + batchId + " message=" + ex.toString());
}
}
sendOutboundScriptSuffix(out, replies.getBatchId());
}
use of org.directwebremoting.extend.RealScriptSession in project ma-core-public by infiniteautomation.
the class DefaultWebContext method getScriptSession.
/* (non-Javadoc)
* @see org.directwebremoting.WebContext#getScriptSession()
*/
public ScriptSession getScriptSession() {
ScriptSessionManager manager = getScriptSessionManager();
RealScriptSession scriptSession = manager.getScriptSession(scriptSessionId);
manager.setPageForScriptSession(scriptSession, page);
return scriptSession;
}
use of org.directwebremoting.extend.RealScriptSession in project ma-core-public by infiniteautomation.
the class DefaultScriptSessionManager method invalidate.
/**
* Remove the given session from the list of sessions that we manage, and
* leave it for the GC vultures to pluck.
* @param scriptSession The session to get rid of
*/
protected void invalidate(RealScriptSession scriptSession) {
// Can we think of a reason why we need to sync both together?
// It feels like a deadlock risk to do so
RealScriptSession removed = (RealScriptSession) sessionMap.remove(scriptSession.getId());
if (!scriptSession.equals(removed)) {
log.debug("ScriptSession already removed from manager. scriptSession=" + scriptSession + " removed=" + removed);
}
int removeCount = 0;
synchronized (pageSessionMap) {
for (Iterator it = pageSessionMap.values().iterator(); it.hasNext(); ) {
Set pageSessions = (Set) it.next();
boolean isRemoved = pageSessions.remove(scriptSession);
if (isRemoved) {
removeCount++;
}
}
}
if (removeCount != 1) {
log.debug("DefaultScriptSessionManager.invalidate(): removeCount=" + removeCount + " when invalidating: " + scriptSession);
}
}
use of org.directwebremoting.extend.RealScriptSession in project ma-core-public by infiniteautomation.
the class PollHandler method handle.
/* (non-Javadoc)
* @see org.directwebremoting.Handler#handle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
public void handle(HttpServletRequest request, HttpServletResponse response) throws IOException {
// all Jetty continuation restarts.
if (JettyContinuationSleeper.isRestart(request)) {
JettyContinuationSleeper.restart(request);
return;
}
// A PollBatch is the information that we expect from the request.
// if the parse fails we can do little more than tell the browser that
// something went wrong.
final PollBatch batch;
try {
batch = new PollBatch(request, pageNormalizer);
} catch (ServerException ex) {
// Send a batch exception to the server because the parse failed
String script = EnginePrivate.getRemoteHandleBatchExceptionScript(null, ex);
sendErrorScript(response, script);
return;
}
String bodySessionId = batch.getHttpSessionId();
if (crossDomainSessionSecurity) {
checkNotCsrfAttack(request, bodySessionId);
}
// We might need to complain that reverse ajax is not enabled.
if (!activeReverseAjaxEnabled) {
log.error("Polling and Comet are disabled. To enable them set the init-param activeReverseAjaxEnabled to true. See http://getahead.org/dwr/server/servlet for more.");
String script = EnginePrivate.getRemotePollCometDisabledScript(batch.getBatchId());
sendErrorScript(response, script);
return;
}
// Complain if GET is disallowed
if (batch.isGet() && !allowGetForSafariButMakeForgeryEasier) {
// Send a batch exception to the server because the parse failed
String script = EnginePrivate.getRemoteHandleBatchExceptionScript(batch.getBatchId(), new SecurityException("GET Disallowed"));
sendErrorScript(response, script);
return;
}
// A script conduit is some route from a ScriptSession back to the page
// that belongs to the session. There may be zero or many of these
// conduits (although if there are more than 2, something is strange)
// All scripts destined for a page go to a ScriptSession and then out
// via a ScriptConduit.
final RealScriptSession scriptSession = batch.getScriptSession();
// Create a conduit depending on the type of request (from the URL)
final BaseScriptConduit conduit = createScriptConduit(batch, response);
// So we're going to go to sleep. How do we wake up?
final Sleeper sleeper;
// If this is Jetty then we can use Continuations
if (Continuation.isJetty()) {
sleeper = new JettyContinuationSleeper(request);
} else {
sleeper = new ThreadWaitSleeper();
}
// There are various reasons why we want to wake up and carry on ...
final List alarms = new ArrayList();
// If the conduit has an error flushing data, it needs to give up
alarms.add(conduit.getErrorAlarm());
// Set the system up to resume on output (perhaps with delay)
if (batch.getPartialResponse() == PartialResponse.NO || maxWaitAfterWrite != -1) {
// add an output listener to the script session that calls the
// "wake me" method on whatever is putting us to sleep
alarms.add(new OutputAlarm(scriptSession, maxWaitAfterWrite));
}
// Set the system up to resume anyway after maxConnectedTime
long connectedTime = serverLoadMonitor.getConnectedTime();
alarms.add(new TimedAlarm(connectedTime));
// We also need to wake-up if the server is being shut down
// WARNING: This code has a non-obvious side effect - The server load
// monitor (which hands out shutdown messages) also monitors usage by
// looking at the number of connected alarms.
alarms.add(new ShutdownAlarm(serverLoadMonitor));
// Make sure that all the alarms know what to wake
for (Iterator it = alarms.iterator(); it.hasNext(); ) {
Alarm alarm = (Alarm) it.next();
alarm.setAlarmAction(sleeper);
}
// Register the conduit with a script session so messages can get out.
// This must happen late on in this method because this will cause any
// scripts cached in the script session (because there was no conduit
// available when they were written) to be sent to the conduit.
// We need any AlarmScriptConduits to be notified so they can make
// maxWaitWfterWrite work for all cases
scriptSession.addScriptConduit(conduit);
// We need to do something sensible when we wake up ...
Runnable onAwakening = new Runnable() {
public void run() {
// Cancel all the alarms
for (Iterator it = alarms.iterator(); it.hasNext(); ) {
Alarm alarm = (Alarm) it.next();
alarm.cancel();
}
// We can't be used as a conduit to the browser any more
scriptSession.removeScriptConduit(conduit);
// Tell the browser to come back at the right time
try {
int timeToNextPoll = serverLoadMonitor.getDisconnectedTime();
conduit.close(timeToNextPoll);
} catch (IOException ex) {
log.warn("Failed to write reconnect info to browser");
}
}
};
// Actually go to sleep. This *must* be the last thing in this method to
// cope with all the methods of affecting Threads. Jetty throws,
// Weblogic continues, others wait().
sleeper.goToSleep(onAwakening);
}
Aggregations