pollhandler.java
来自「反向的AJAX。最大的特性是我们成为反向的Ajax。DWR1.x允许你用java」· Java 代码 · 共 445 行 · 第 1/2 页
JAVA
445 行
/* * Copyright 2005 Joe Walker * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package org.directwebremoting.dwrp;import java.io.IOException;import java.io.PrintWriter;import java.util.ArrayList;import java.util.Iterator;import java.util.List;import javax.servlet.http.Cookie;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.directwebremoting.extend.ConverterManager;import org.directwebremoting.extend.EnginePrivate;import org.directwebremoting.extend.Handler;import org.directwebremoting.extend.PageNormalizer;import org.directwebremoting.extend.RealScriptSession;import org.directwebremoting.extend.ScriptSessionManager;import org.directwebremoting.extend.ServerException;import org.directwebremoting.extend.ServerLoadMonitor;import org.directwebremoting.util.Continuation;import org.directwebremoting.util.MimeConstants;/** * A Marshaller that output plain Javascript. * This marshaller can be tweaked to output Javascript in an HTML context. * This class works in concert with CallScriptConduit, they should be * considered closely related and it is important to understand what one does * while editing the other. * @author Joe Walker [joe at getahead dot ltd dot uk] */public class PollHandler implements Handler{ /** * @param plain Are we using plain javascript or html wrapped javascript */ public PollHandler(boolean plain) { this.plain = plain; } /* (non-Javadoc) * @see org.directwebremoting.Handler#handle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) */ public void handle(HttpServletRequest request, HttpServletResponse response) throws IOException { // If you're new to understanding this file, you may wish to skip this // step and come back to it later ;-) // So Jetty does something a bit weird with Ajax Continuations. You // suspend a request (which works via an exception) while keeping hold // of a continuation object. There are methods on this continuation // object to restart the request. Also you can write to the output at // any time the request is suspended. When the continuation is // restarted, rather than restart the thread from where is was // suspended, it starts it from the beginning again. Since we are able // to write to the response outside of the servlet thread, there is no // need for us to do anything if we have been restarted. So we ignore // 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(); 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); } /** * Check that this request is not subject to a CSRF attack * @param request The original browser's request * @param bodySessionId The session id */ private void checkNotCsrfAttack(HttpServletRequest request, String bodySessionId) { // A check to see that this isn't a csrf attack // http://en.wikipedia.org/wiki/Cross-site_request_forgery // http://www.tux.org/~peterw/csrf.txt
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?