blob: 3ed177d85d7a4a6b621ff925a4737bf8003ebda5 [file] [log] [blame]
//
// ========================================================================
// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.continuation;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.ServletResponseWrapper;
import org.mortbay.log.Log;
import org.mortbay.log.Logger;
/* ------------------------------------------------------------ */
/**
* This implementation of Continuation is used by {@link ContinuationSupport}
* when it detects that the application is deployed in a jetty-6 server.
* This continuation requires the {@link ContinuationFilter} to be deployed.
*/
public class Jetty6Continuation implements ContinuationFilter.FilteredContinuation
{
private static final Logger LOG = Log.getLogger(Jetty6Continuation.class.getName());
// Exception reused for all continuations
// Turn on debug in ContinuationFilter to see real stack trace.
private final static ContinuationThrowable __exception = new ContinuationThrowable();
private final ServletRequest _request;
private ServletResponse _response;
private final org.mortbay.util.ajax.Continuation _j6Continuation;
private Throwable _retry;
private int _timeout;
private boolean _initial=true;
private volatile boolean _completed=false;
private volatile boolean _resumed=false;
private volatile boolean _expired=false;
private boolean _responseWrapped=false;
private List<ContinuationListener> _listeners;
public Jetty6Continuation(ServletRequest request, org.mortbay.util.ajax.Continuation continuation)
{
if (!ContinuationFilter._initialized)
{
LOG.warn("!ContinuationFilter installed",null,null);
throw new IllegalStateException("!ContinuationFilter installed");
}
_request=request;
_j6Continuation=continuation;
}
public void addContinuationListener(final ContinuationListener listener)
{
if (_listeners==null)
_listeners=new ArrayList<ContinuationListener>();
_listeners.add(listener);
}
public void complete()
{
synchronized(this)
{
if (_resumed)
throw new IllegalStateException();
_completed=true;
if (_j6Continuation.isPending())
_j6Continuation.resume();
}
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.continuation.Continuation#getAttribute(java.lang.String)
*/
public Object getAttribute(String name)
{
return _request.getAttribute(name);
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.continuation.Continuation#removeAttribute(java.lang.String)
*/
public void removeAttribute(String name)
{
_request.removeAttribute(name);
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.continuation.Continuation#setAttribute(java.lang.String, java.lang.Object)
*/
public void setAttribute(String name, Object attribute)
{
_request.setAttribute(name,attribute);
}
/* ------------------------------------------------------------ */
public ServletResponse getServletResponse()
{
return _response;
}
/* ------------------------------------------------------------ */
public boolean isExpired()
{
return _expired;
}
/* ------------------------------------------------------------ */
public boolean isInitial()
{
return _initial;
}
/* ------------------------------------------------------------ */
public boolean isResumed()
{
return _resumed;
}
/* ------------------------------------------------------------ */
public boolean isSuspended()
{
return _retry!=null;
}
/* ------------------------------------------------------------ */
public void resume()
{
synchronized(this)
{
if (_completed)
throw new IllegalStateException();
_resumed=true;
if (_j6Continuation.isPending())
_j6Continuation.resume();
}
}
/* ------------------------------------------------------------ */
public void setTimeout(long timeoutMs)
{
_timeout=(timeoutMs>Integer.MAX_VALUE)?Integer.MAX_VALUE:(int)timeoutMs;
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.continuation.Continuation#suspend(javax.servlet.ServletResponse)
*/
public void suspend(ServletResponse response)
{
try
{
_response=response;
_responseWrapped=_response instanceof ServletResponseWrapper;
_resumed=false;
_expired=false;
_completed=false;
_j6Continuation.suspend(_timeout);
}
catch(Throwable retry)
{
_retry=retry;
}
}
/* ------------------------------------------------------------ */
public void suspend()
{
try
{
_response=null;
_responseWrapped=false;
_resumed=false;
_expired=false;
_completed=false;
_j6Continuation.suspend(_timeout);
}
catch(Throwable retry)
{
_retry=retry;
}
}
/* ------------------------------------------------------------ */
public boolean isResponseWrapped()
{
return _responseWrapped;
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.continuation.Continuation#undispatch()
*/
public void undispatch()
{
if (isSuspended())
{
if (ContinuationFilter.__debug)
throw new ContinuationThrowable();
throw __exception;
}
throw new IllegalStateException("!suspended");
}
/* ------------------------------------------------------------ */
public boolean enter(ServletResponse response)
{
_response=response;
_expired=!_j6Continuation.isResumed();
if (_initial)
return true;
_j6Continuation.reset();
if (_expired)
{
if (_listeners!=null)
{
for (ContinuationListener l: _listeners)
l.onTimeout(this);
}
}
return !_completed;
}
/* ------------------------------------------------------------ */
public boolean exit()
{
_initial=false;
Throwable th=_retry;
_retry=null;
if (th instanceof Error)
throw (Error)th;
if (th instanceof RuntimeException)
throw (RuntimeException)th;
if (_listeners!=null)
{
for (ContinuationListener l: _listeners)
l.onComplete(this);
}
return true;
}
}