All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.directwebremoting.util.Continuation Maven / Gradle / Ivy

Go to download

DWR is easy Ajax for Java. It makes it simple to call Java code directly from Javascript. It gets rid of almost all the boiler plate code between the web browser and your Java code.

There is a newer version: 3.0.2-RELEASE
Show newest version
/*
 * 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.util;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import javax.servlet.http.HttpServletRequest;

/**
 * A wrapper around Jetty Ajax Continuations
 * @author Joe Walker [joe at getahead dot ltd dot uk]
 */
public class Continuation
{
    /**
     * Fish the Jetty continuation out of the request if it exists
     * @param request The http request
     */
    public Continuation(HttpServletRequest request)
    {
        this.proxy = request.getAttribute(ATTRIBUTE_JETTY_CONTINUATION);
    }

    /**
     * Are continuations working?
     * If this method returns false then all the other methods will fail.
     * @return true if Jetty continuations are working
     */
    public boolean isAvailable()
    {
        return proxy != null;
    }

    /**
     * Suspend the thread for a maximum of sleepTime milliseconds
     * @param sleepTime The maximum time to wait
     * @throws Exception If reflection breaks
     */
    public void suspend(long sleepTime) throws Exception
    {
        try
        {
            suspendMethod.invoke(proxy, new Object[] { new Long(sleepTime) });
        }
        catch (InvocationTargetException ex)
        {
            rethrowWithoutWrapper(ex);
        }
    }

    /**
     * Resume an continuation.
     * For Jetty: does not work like a real continuation because it restarts
     * the http request.
     * @throws Exception If reflection breaks
     */
    public void resume() throws Exception
    {
        try
        {
            resumeMethod.invoke(proxy, new Object[0]);
        }
        catch (InvocationTargetException ex)
        {
            rethrowWithoutWrapper(ex);
        }
    }

    /**
     * Accessor for the object associated with this continuation
     * @return the object associated with this continuation
     * @throws Exception If reflection breaks
     */
    public Object getObject() throws Exception
    {
        try
        {
            return getObject.invoke(proxy, new Object[0]);
        }
        catch (InvocationTargetException ex)
        {
            return rethrowWithoutWrapper(ex);
        }
    }

    /**
     * Accessor for the object associated with this continuation
     * @param object the object associated with this continuation
     * @throws Exception If reflection breaks
     */
    public void setObject(Object object) throws Exception
    {
        try
        {
            setObject.invoke(proxy, new Object[] { object });
        }
        catch (InvocationTargetException ex)
        {
            rethrowWithoutWrapper(ex);
        }
    }

    /**
     * We shouldn't be catching Jetty RetryRequests so we rethrow them.
     * @param th The exception to test for continuation-ness
     */
    public static void rethrowIfContinuation(Throwable th)
    {
        Throwable ex = th;

        if (ex instanceof InvocationTargetException)
        {
            ex = ((InvocationTargetException) ex).getTargetException();
        }

        // Allow Jetty RequestRetry exception to propogate to container!
        if ("org.mortbay.jetty.RetryRequest".equals(ex.getClass().getName()))
        {
            throw (RuntimeException) ex;
        }
    }

    /**
     * Unwrap an InvocationTargetException
     * @param ex The exception to unwrap
     * @return Nothing. This method will not complete normally
     * @throws Exception If reflection breaks
     */
    private static Object rethrowWithoutWrapper(InvocationTargetException ex) throws Exception
    {
        Throwable target = ex.getTargetException();
        if (target instanceof Exception)
        {
            throw (Exception) target;
        }

        if (target instanceof Error)
        {
            throw (Error) target;
        }

        throw ex;
    }

    /**
     * The real continuation object
     */
    private Object proxy;

    /**
     * The log stream
     */
    private static final Logger log = Logger.getLogger(Continuation.class);

    /**
     * The attribute under which Jetty stores it's Contuniations.
     * TODO: This feels like a mighty hack. I hope Greg doesn't change it without telling us!
     */
    private static final String ATTRIBUTE_JETTY_CONTINUATION = "org.mortbay.jetty.ajax.Continuation";

    /**
     * Jetty code used by reflection to allow it to run outside of Jetty
     */
    protected static Class continuationClass;

    /**
     * How we suspend the continuation
     */
    protected static Method suspendMethod;

    /**
     * How we resume the continuation
     */
    protected static Method resumeMethod;

    /**
     * How we get the associated continuation object
     */
    protected static Method getObject;

    /**
     * How we set the associated continuation object
     */
    protected static Method setObject;

    /**
     * Are we using Jetty at all?
     */
    protected static boolean isJetty;

    /**
     * Can we use Jetty?
     */
    static
    {
        try
        {
            continuationClass = LocalUtil.classForName("org.mortbay.util.ajax.Continuation");
            suspendMethod = continuationClass.getMethod("suspend", new Class[] { Long.TYPE });
            resumeMethod = continuationClass.getMethod("resume", new Class[] {});
            getObject = continuationClass.getMethod("getObject", new Class[] {});
            setObject = continuationClass.getMethod("setObject", new Class[] { Object.class });
            isJetty = true;
        }
        catch (Exception ex)
        {
            isJetty = false;
            log.debug("No Jetty ContuniationSupport class, using standard Servlet API");
        }
    }

    /**
     * @return True if we have detected Continuation classes
     */
    public static boolean isJetty()
    {
        return isJetty;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy