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 + -
显示快捷键?