This commit takes jetty-7 back to the 2.5 servlet API, but leaves much of the

3.0 asynchronous machinery available.

Introduces a new improved Continuation API that is an evolution of the 
original Continuation API, while taking some good ideas from the 3.0 spec.
The intention is that this API will simplify the use of the 3.0
API, while making it available in jetty-7 (scalably) and in all other
2.5 containers with the ContinuationFilter.





git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@27 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
Greg Wilkins 2009-03-29 02:15:22 +00:00
parent ff76d89682
commit 0f510e6753
66 changed files with 1308 additions and 2712 deletions

View File

@ -50,11 +50,6 @@
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>servlet-annotation-spec</artifactId>
<version>3.0.pre0</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-jndi</artifactId>

View File

@ -16,7 +16,6 @@ package org.eclipse.jetty.annotations;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -29,29 +28,14 @@ import javax.annotation.security.RunAs;
import javax.naming.InitialContext;
import javax.naming.NameNotFoundException;
import javax.naming.NamingException;
import javax.servlet.DispatcherType;
import javax.servlet.http.annotation.InitParam;
import javax.servlet.http.annotation.jaxrs.DELETE;
import javax.servlet.http.annotation.jaxrs.GET;
import javax.servlet.http.annotation.jaxrs.HEAD;
import javax.servlet.http.annotation.jaxrs.POST;
import javax.servlet.http.annotation.jaxrs.PUT;
import org.eclipse.jetty.plus.annotation.Injection;
import org.eclipse.jetty.plus.annotation.InjectionCollection;
import org.eclipse.jetty.plus.annotation.LifeCycleCallbackCollection;
import org.eclipse.jetty.plus.annotation.PojoContextListener;
import org.eclipse.jetty.plus.annotation.PojoFilter;
import org.eclipse.jetty.plus.annotation.PojoServlet;
import org.eclipse.jetty.plus.annotation.PostConstructCallback;
import org.eclipse.jetty.plus.annotation.PreDestroyCallback;
import org.eclipse.jetty.plus.annotation.RunAsCollection;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.FilterMapping;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.servlet.ServletMapping;
import org.eclipse.jetty.util.IntrospectionUtil;
import org.eclipse.jetty.util.LazyList;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.webapp.WebAppContext;
@ -111,112 +95,11 @@ public class AnnotationProcessor
public void processServlets ()
throws Exception
{
//@Servlet(urlMappings=String[], description=String, icon=String, loadOnStartup=int, name=String, initParams=InitParams[])
for (Class clazz:_finder.getClassesForAnnotation(javax.servlet.http.annotation.Servlet.class))
{
javax.servlet.http.annotation.Servlet annotation = (javax.servlet.http.annotation.Servlet)clazz.getAnnotation(javax.servlet.http.annotation.Servlet.class);
PojoServlet servlet = new PojoServlet(getPojoInstanceFor(clazz));
List<Method> methods = _finder.getMethodsForAnnotation(GET.class);
if (methods.size() > 1)
throw new IllegalStateException ("More than one GET annotation on "+clazz.getName());
else if (methods.size() == 1)
servlet.setGetMethodName(methods.get(0).getName());
methods = _finder.getMethodsForAnnotation(POST.class);
if (methods.size() > 1)
throw new IllegalStateException ("More than one POST annotation on "+clazz.getName());
else if (methods.size() == 1)
servlet.setPostMethodName(methods.get(0).getName());
methods = _finder.getMethodsForAnnotation(PUT.class);
if (methods.size() > 1)
throw new IllegalStateException ("More than one PUT annotation on "+clazz.getName());
else if (methods.size() == 1)
servlet.setPutMethodName(methods.get(0).getName());
methods = _finder.getMethodsForAnnotation(DELETE.class);
if (methods.size() > 1)
throw new IllegalStateException ("More than one DELETE annotation on "+clazz.getName());
else if (methods.size() == 1)
servlet.setDeleteMethodName(methods.get(0).getName());
methods = _finder.getMethodsForAnnotation(HEAD.class);
if (methods.size() > 1)
throw new IllegalStateException ("More than one HEAD annotation on "+clazz.getName());
else if (methods.size() == 1)
servlet.setHeadMethodName(methods.get(0).getName());
ServletHolder holder = new ServletHolder(servlet);
holder.setName((annotation.name().equals("")?clazz.getName():annotation.name()));
holder.setInitOrder(annotation.loadOnStartup());
LazyList.add(_servlets, holder);
for (InitParam ip:annotation.initParams())
{
holder.setInitParameter(ip.name(), ip.value());
}
if (annotation.urlMappings().length > 0)
{
ArrayList paths = new ArrayList();
ServletMapping mapping = new ServletMapping();
mapping.setServletName(holder.getName());
for (String s:annotation.urlMappings())
{
paths.add(normalizePattern(s));
}
mapping.setPathSpecs((String[])paths.toArray(new String[paths.size()]));
LazyList.add(_servletMappings,mapping);
}
}
}
public void processFilters ()
throws Exception
{
//@ServletFilter(description=String, filterName=String, displayName=String, icon=String,initParams=InitParam[], filterMapping=FilterMapping)
for (Class clazz:_finder.getClassesForAnnotation(javax.servlet.http.annotation.ServletFilter.class))
{
javax.servlet.http.annotation.ServletFilter annotation = (javax.servlet.http.annotation.ServletFilter)clazz.getAnnotation(javax.servlet.http.annotation.ServletFilter.class);
PojoFilter filter = new PojoFilter(getPojoInstanceFor(clazz));
FilterHolder holder = new FilterHolder(filter);
holder.setName((annotation.filterName().equals("")?clazz.getName():annotation.filterName()));
holder.setDisplayName(annotation.displayName());
LazyList.add(_filters, holder);
for (InitParam ip:annotation.initParams())
{
holder.setInitParameter(ip.name(), ip.value());
}
if (annotation.filterMapping() != null)
{
FilterMapping mapping = new FilterMapping();
mapping.setFilterName(holder.getName());
ArrayList paths = new ArrayList();
for (String s:annotation.filterMapping().urlPattern())
{
paths.add(normalizePattern(s));
}
mapping.setPathSpecs((String[])paths.toArray(new String[paths.size()]));
ArrayList names = new ArrayList();
for (String s:annotation.filterMapping().servletNames())
{
names.add(s);
}
mapping.setServletNames((String[])names.toArray(new String[names.size()]));
int dispatcher=FilterMapping.DEFAULT;
for (DispatcherType d:annotation.filterMapping().dispatcherTypes())
{
dispatcher = dispatcher|FilterMapping.dispatch(d);
}
mapping.setDispatches(dispatcher);
LazyList.add(_filterMappings,mapping);
}
}
{
}
@ -224,12 +107,6 @@ public class AnnotationProcessor
public void processListeners ()
throws Exception
{
//@ServletContextListener(description=String)
for (Class clazz:_finder.getClassesForAnnotation(javax.servlet.http.annotation.ServletContextListener.class))
{
PojoContextListener listener = new PojoContextListener(getPojoInstanceFor(clazz));
LazyList.add(_listeners, listener);
}
}

View File

@ -18,22 +18,13 @@ import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import javax.annotation.security.RunAs;
import javax.servlet.DispatcherType;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.http.annotation.FilterMapping;
import javax.servlet.http.annotation.InitParam;
import javax.servlet.http.annotation.Servlet;
import javax.servlet.http.annotation.ServletFilter;
import javax.servlet.http.annotation.jaxrs.GET;
import javax.servlet.http.annotation.jaxrs.POST;
@Servlet(urlMappings = { "/foo/*", "/bah/*" }, name="CServlet", initParams={@InitParam(name="x", value="y")})
@ServletFilter(filterName="CFilter", filterMapping=@FilterMapping(dispatcherTypes={DispatcherType.REQUEST}, urlPattern = {"/*"}), initParams={@InitParam(name="a", value="99")})
@RunAs("admin")
public class ClassC
{
@ -52,8 +43,6 @@ public class ClassC
}
@GET()
@POST()
public void anything (HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{

View File

@ -1,155 +0,0 @@
// ========================================================================
// Copyright (c) 2008-2009 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.annotations;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NameNotFoundException;
import junit.framework.TestCase;
import org.eclipse.jetty.plus.annotation.Injection;
import org.eclipse.jetty.plus.annotation.InjectionCollection;
import org.eclipse.jetty.plus.annotation.LifeCycleCallback;
import org.eclipse.jetty.plus.annotation.LifeCycleCallbackCollection;
import org.eclipse.jetty.plus.annotation.PojoFilter;
import org.eclipse.jetty.plus.annotation.PojoServlet;
import org.eclipse.jetty.plus.annotation.RunAs;
import org.eclipse.jetty.plus.annotation.RunAsCollection;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.FilterMapping;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.servlet.ServletMapping;
import org.eclipse.jetty.webapp.WebAppContext;
public class ServletAnnotationTest extends TestCase
{
public void tearDown()
throws Exception
{
InitialContext ic = new InitialContext();
Context comp = (Context)ic.lookup("java:comp");
comp.destroySubcontext("env");
}
public void testAnnotations() throws Exception
{
Server server = new Server();
WebAppContext wac = new WebAppContext();
wac.setServer(server);
InitialContext ic = new InitialContext();
Context comp = (Context)ic.lookup("java:comp");
Context env = null;
try
{
env = (Context)comp.lookup("env");
}
catch (NameNotFoundException e)
{
env = comp.createSubcontext("env");
}
org.eclipse.jetty.plus.jndi.EnvEntry foo = new org.eclipse.jetty.plus.jndi.EnvEntry("foo", new Double(1000.00), false);
List servlets = new ArrayList();
List filters = new ArrayList();
List listeners = new ArrayList();
List servletMappings = new ArrayList();
List filterMappings = new ArrayList();
List classes = new ArrayList();
classes.add("org.eclipse.jetty.annotations.ClassC");
AnnotationFinder finder = new AnnotationFinder();
finder.find (classes,
new ClassNameResolver()
{
public boolean isExcluded(String name)
{
return false;
}
public boolean shouldOverride(String name)
{
return true;
}
});
RunAsCollection runAs = new RunAsCollection();
InjectionCollection injections = new InjectionCollection();
LifeCycleCallbackCollection callbacks = new LifeCycleCallbackCollection();
AnnotationProcessor processor = new AnnotationProcessor (wac, finder, runAs, injections, callbacks,
servlets, filters, listeners, servletMappings, filterMappings);
processor.process();
assertEquals(1, servlets.size());
ServletHolder sholder = (ServletHolder)servlets.get(0);
assertEquals("CServlet", sholder.getName());
assertTrue(sholder.getServlet() instanceof PojoServlet);
PojoServlet ps = (PojoServlet)sholder.getServlet();
assertEquals("anything", ps.getGetMethodName());
assertEquals("anything", ps.getPostMethodName());
Map sinitparams = sholder.getInitParameters();
assertEquals(1, sinitparams.size());
assertTrue(sinitparams.containsKey("x"));
assertTrue(sinitparams.containsValue("y"));
assertEquals(1, filters.size());
FilterHolder fholder = (FilterHolder)filters.get(0);
assertTrue(fholder.getFilter() instanceof PojoFilter);
Map finitparams = fholder.getInitParameters();
assertEquals(1, finitparams.size());
assertTrue(finitparams.containsKey("a"));
assertTrue(finitparams.containsValue("99"));
assertEquals(1, servletMappings.size());
ServletMapping smap = (ServletMapping)servletMappings.get(0);
assertEquals("CServlet", smap.getServletName());
assertEquals(2, smap.getPathSpecs().length);
assertEquals(1, filterMappings.size());
FilterMapping fmap = (FilterMapping)filterMappings.get(0);
assertEquals("CFilter", fmap.getFilterName());
assertEquals(1, fmap.getPathSpecs().length);
List<Injection> fieldInjections = injections.getFieldInjections(ClassC.class);
assertNotNull(fieldInjections);
assertEquals(1, fieldInjections.size());
RunAs ra = runAs.getRunAs(sholder);
assertNotNull(ra);
assertEquals("admin", ra.getRoleName());
List predestroys = callbacks.getPreDestroyCallbacks(sholder.getServlet());
assertNotNull(predestroys);
assertEquals(1, predestroys.size());
LifeCycleCallback cb = (LifeCycleCallback)predestroys.get(0);
assertTrue(cb.getTarget().equals(ClassC.class.getDeclaredMethod("pre", new Class[]{})));
List postconstructs = callbacks.getPostConstructCallbacks(sholder.getServlet());
assertNotNull(postconstructs);
assertEquals(1, postconstructs.size());
cb = (LifeCycleCallback)postconstructs.get(0);
assertTrue(cb.getTarget().equals(ClassC.class.getDeclaredMethod("post", new Class[]{})));
}
}

View File

@ -0,0 +1,83 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.0.0.incubation0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-continuation</artifactId>
<name>Jetty :: Continuation</name>
<description>Asynchronous API</description>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>1.4.2</version>
<extensions>true</extensions>
<executions>
<execution>
<goals>
<goal>manifest</goal>
</goals>
<configuration>
<instructions>
<Bundle-SymbolicName>org.eclipse.jetty.continuation</Bundle-SymbolicName>
<Bundle-RequiredExecutionEnvironment>J2SE-1.5</Bundle-RequiredExecutionEnvironment>
<Bundle-DocURL>http://jetty.eclipse.org</Bundle-DocURL>
<Import-Package></Import-Package>
</instructions>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>artifact-jar</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
<execution>
<id>test-jar</id>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
<configuration>
<archive>
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
</archive>
</configuration>
</plugin>
<!-- always include sources since jetty-xbean makes use of them -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>servlet-api</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,207 @@
// ========================================================================
// Copyright (c) 2004-2009 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.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.Servlet;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
/* ------------------------------------------------------------ */
/**
* Continuation.
*
* A continuation is a mechanism by which a HTTP Request can be suspended and
* restarted after a timeout or an asynchronous event has occurred.
*
*/
public interface Continuation
{
public final static String ATTRIBUTE = "org.eclipse.jetty.continuation";
/**
* Set the continuation timeout
*
* @param timeoutMs
* The time in milliseconds to wait before expiring this
* continuation.
*/
void setTimeout(long timeoutMs);
/**
* Suspend the processing of the request and associated
* {@link ServletResponse}.
*
* <p>
* After this method has been called, the lifecycle of the request will be
* extended beyond the return to the container from the
* {@link Servlet#service(ServletRequest, ServletResponse)} method and
* {@link Filter#doFilter(ServletRequest, ServletResponse, FilterChain)}
* calls. If a request is suspended, then the container will not commit the
* associated response when the call to the filter chain and/or servlet
* service method returns to the container. Any exceptions thrown to the
* container by a filter chain and/or servlet for a suspended requests are
* silently ignored.
* </p>
*
* <p>
* When the thread calling the filter chain and/or servlet has returned to
* the container with a suspended request, the thread is freed for other
* tasks and the request is held pending either:
* <ul>
* <li>a call to {@link ServletRequest#resume()}.</li>
* <li>a call to {@link ServletRequest#complete()}.</li>
* <li>the passed or default timeout expires.</li>
* <li>there is IO activity on the connection that received the request,
* such as the close of the connection or the receipt of a pipelined
* request.
* </ul>
* <p>
* After any of the events listed above, the suspended request will be
* redispatched via the filter and servlet processing.
* </p>
*
* <p>
* Suspend may only be called by a thread that is within the service calling
* stack of
* {@link Filter#doFilter(ServletRequest, ServletResponse, FilterChain)}
* and/or {@link Servlet#service(ServletRequest, ServletResponse)}. A
* request that has been dispatched for error handling may not be suspended.
* </p>
*
* @see {@link #resume()}
* @see {@link #complete()}
*
* @exception IllegalStateException
* If the calling thread is not within the calling stack of
* {@link Filter#doFilter(ServletRequest, ServletResponse, FilterChain)}
* and/or
* {@link Servlet#service(ServletRequest, ServletResponse)}
* or if the request has been dispatched for error handling.
*/
void suspend();
/**
* Resume a suspended request.
*
* <p>
* This method can be called by any thread that has been passed a reference
* to a suspended request. When called the request is redispatched to the
* normal filter chain and servlet processing.
* </p>
*
* <p>
* If resume is called before a suspended request is returned to the
* container (ie the thread that called {@link #suspend(long)} is still
* within the filter chain and/or servlet service method), then the resume
* does not take effect until the call to the filter chain and/or servlet
* returns to the container. In this case both {@link #isSuspended()} and
* {@link isResumed()} return true.
* </p>
*
* <p>
* Multiple calls to resume are ignored
* </p>
*
* @see {@link #suspend()}
* @exception IllegalStateException
* if the request is not suspended.
*
*/
void resume();
/**
* Complete a suspended request.
*
* <p>
* This method can be called by any thread that has been passed a reference
* to a suspended request. When a request is completed, the associated
* response object commited and flushed. The request is not redispatched.
* </p>
*
* <p>
* If complete is called before a suspended request is returned to the
* container (ie the thread that called {@link #suspend(long)} is still
* within the filter chain and/or servlet service method), then the complete
* does not take effect until the call to the filter chain and/or servlet
* returns to the container. In this case both {@link #isSuspended()} and
* {@link isResumed()} return true.
* </p>
*
* <p>
* Once complete has been called and any thread calling the filter chain
* and/or servlet chain has returned to the container, the request lifecycle
* is complete. The container is able to recycle request objects, so it is
* not valid hold a request reference after the end of the life cycle or to
* call any request methods.
*
* @see {@link #suspend()}
* @exception IllegalStateException
* if the request is not suspended.
*
*/
void complete();
/**
* @return true after {@link #suspend(long)} has been called and before the
* request has been redispatched due to being resumed, completed or
* timed out.
*/
boolean isSuspended();
/**
* @return true if the request has been redispatched by a call to
* {@link #resume()}. Returns false after any subsequent call to
* suspend
*/
boolean isResumed();
/**
* @return true after a request has been redispatched as the result of a
* timeout. Returns false after any subsequent call to suspend.
*/
boolean isExpired();
/**
* @return true while the request is within the initial dispatch to the
* filter chain and/or servlet. Will return false once the calling
* thread has returned to the container after suspend has been
* called and during any subsequent redispatch.
*/
boolean isInitial();
/* ------------------------------------------------------------ */
/**
* Call to signal that the suspending filter/servlet has kept a
* reference to any passed requests wrappers, and that these should
* not be finalized until a onComplete event has been seen.
*/
void keepWrappers();
/**
* @return True if {@link #keepWrappers()} has been called.
*/
boolean wrappersKept();
/* ------------------------------------------------------------ */
/**
* @param listener
*/
void addContinuationListener(ContinuationListener listener);
}

View File

@ -0,0 +1,10 @@
package org.eclipse.jetty.continuation;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public interface ContinuationEvent
{
public ServletRequest getRequest();
public ServletResponse getResponse();
}

View File

@ -0,0 +1,433 @@
package org.eclipse.jetty.continuation;
import java.io.IOException;
import java.util.ArrayList;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class ContinuationFilter implements Filter
{
final boolean _jetty=true;
ServletContext _context;
public void init(FilterConfig filterConfig) throws ServletException
{
_context = filterConfig.getServletContext();
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
{
if (_jetty)
chain.doFilter(request,response);
else
{
final FauxContinuation fc = new FauxContinuation();
request.setAttribute(Continuation.ATTRIBUTE,fc);
boolean complete=false;
while (!complete)
{
try
{
chain.doFilter(request,response);
}
catch(IOException e)
{
_context.log("OpenServletFilter caught ",e);
}
catch(ServletException e)
{
_context.log("OpenServletFilter caught ",e);
}
finally
{
complete=fc.handleSuspension();
}
}
}
}
public void destroy()
{
}
private class FauxContinuation implements Continuation
{
private static final int __HANDLING=1; // Request dispatched to filter/servlet
private static final int __SUSPENDING=2; // Suspend called, but not yet returned to container
private static final int __RESUMING=3; // resumed while suspending
private static final int __COMPLETING=4; // resumed while suspending or suspended
private static final int __SUSPENDED=5; // Suspended and parked
private static final int __UNSUSPENDING=6;
private static final int __COMPLETE=7;
private int _state=__HANDLING;
private boolean _initial=true;
private boolean _resumed=false;
private boolean _timeout=false;
private boolean _keepWrappers=false;
private long _timeoutMs=30000; // TODO configure
private ArrayList<ContinuationListener> _listeners;
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.continuation.Continuation#keepWrappers()
*/
public void keepWrappers()
{
_keepWrappers=true;
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.continuation.Continuation#wrappersKept()
*/
public boolean wrappersKept()
{
return _keepWrappers;
}
/* ------------------------------------------------------------ */
public boolean isInitial()
{
synchronized(this)
{
return _initial;
}
}
public boolean isResumed()
{
synchronized(this)
{
return _resumed;
}
}
public boolean isSuspended()
{
synchronized(this)
{
switch(_state)
{
case __HANDLING:
return false;
case __SUSPENDING:
case __RESUMING:
case __COMPLETING:
case __SUSPENDED:
return true;
case __UNSUSPENDING:
default:
return false;
}
}
}
public boolean isExpired()
{
synchronized(this)
{
return _timeout;
}
}
public void setTimeout(long timeoutMs)
{
_timeoutMs = timeoutMs;
}
public void suspend()
{
synchronized (this)
{
switch(_state)
{
case __HANDLING:
_timeout=false;
_resumed=false;
_state=__SUSPENDING;
return;
case __SUSPENDING:
case __RESUMING:
return;
case __COMPLETING:
case __SUSPENDED:
case __UNSUSPENDING:
throw new IllegalStateException(this.getStatusString());
default:
throw new IllegalStateException(""+_state);
}
}
}
/* ------------------------------------------------------------ */
/* (non-Javadoc)
* @see org.mortbay.jetty.Suspendor#resume()
*/
public void resume()
{
synchronized (this)
{
switch(_state)
{
case __HANDLING:
_resumed=true;
return;
case __SUSPENDING:
_resumed=true;
_state=__RESUMING;
return;
case __RESUMING:
case __COMPLETING:
return;
case __SUSPENDED:
fauxResume();
_resumed=true;
_state=__UNSUSPENDING;
break;
case __UNSUSPENDING:
_resumed=true;
return;
default:
throw new IllegalStateException(this.getStatusString());
}
}
}
public void complete()
{
// just like resume, except don't set _resumed=true;
synchronized (this)
{
switch(_state)
{
case __HANDLING:
throw new IllegalStateException(this.getStatusString());
case __SUSPENDING:
_state=__COMPLETING;
break;
case __RESUMING:
break;
case __COMPLETING:
return;
case __SUSPENDED:
_state=__COMPLETING;
fauxResume();
break;
case __UNSUSPENDING:
return;
default:
throw new IllegalStateException(this.getStatusString());
}
}
}
void handling()
{
synchronized (this)
{
_keepWrappers=false;
switch(_state)
{
case __HANDLING:
throw new IllegalStateException(this.getStatusString());
case __SUSPENDING:
case __RESUMING:
throw new IllegalStateException(this.getStatusString());
case __COMPLETING:
return;
case __SUSPENDED:
fauxResume();
case __UNSUSPENDING:
_state=__HANDLING;
return;
default:
throw new IllegalStateException(""+_state);
}
}
}
/* ------------------------------------------------------------ */
/**
* @return true if handling is complete
*/
public boolean handleSuspension()
{
synchronized (this)
{
switch(_state)
{
case __HANDLING:
_state=__COMPLETE;
return true;
case __SUSPENDING:
_initial=false;
_state=__SUSPENDED;
fauxSuspend(); // could block and change state.
if (_state==__SUSPENDED || _state==__COMPLETING)
return true;
_initial=false;
_state=__HANDLING;
return false;
case __RESUMING:
_initial=false;
_state=__HANDLING;
return false;
case __COMPLETING:
_initial=false;
_state=__COMPLETE;
return true;
case __SUSPENDED:
case __UNSUSPENDING:
default:
throw new IllegalStateException(this.getStatusString());
}
}
}
/* ------------------------------------------------------------ */
protected void expire()
{
// just like resume, except don't set _resumed=true;
synchronized (this)
{
switch(_state)
{
case __HANDLING:
return;
case __SUSPENDING:
_timeout=true;
_state=__RESUMING;
fauxResume();
return;
case __RESUMING:
return;
case __COMPLETING:
return;
case __SUSPENDED:
_timeout=true;
_state=__UNSUSPENDING;
break;
case __UNSUSPENDING:
_timeout=true;
return;
default:
throw new IllegalStateException(this.getStatusString());
}
}
}
private void fauxSuspend()
{
long expire_at = System.currentTimeMillis()+_timeoutMs;
long wait=_timeoutMs;
while (_timeoutMs>0 && wait>0)
{
try
{
this.wait(wait);
}
catch (InterruptedException e)
{
_context.log("OpenServletFilter caught ",e);
}
wait=expire_at-System.currentTimeMillis();
}
if (_timeoutMs>0 && wait<=0)
expire();
}
private void fauxResume()
{
_timeoutMs=0;
this.notifyAll();
}
public String toString()
{
return getStatusString();
}
String getStatusString()
{
synchronized (this)
{
return
((_state==__HANDLING)?"HANDLING":
(_state==__SUSPENDING)?"SUSPENDING":
(_state==__SUSPENDED)?"SUSPENDED":
(_state==__RESUMING)?"RESUMING":
(_state==__UNSUSPENDING)?"UNSUSPENDING":
(_state==__COMPLETING)?"COMPLETING":
("???"+_state))+
(_initial?",initial":"")+
(_resumed?",resumed":"")+
(_timeout?",timeout":"");
}
}
public void addContinuationListener(ContinuationListener listener)
{
if (_listeners==null)
_listeners=new ArrayList<ContinuationListener>();
_listeners.add(listener);
// TODO Call the listeners
}
}
}

View File

@ -0,0 +1,11 @@
package org.eclipse.jetty.continuation;
import java.io.IOException;
import java.util.EventListener;
public interface ContinuationListener extends EventListener
{
public void onComplete(ContinuationEvent event) throws IOException;
public void onTimeout(ContinuationEvent event) throws IOException;
}

View File

@ -11,25 +11,21 @@
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.util.ajax;
package org.eclipse.jetty.continuation;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.ServletRequest;
/* ------------------------------------------------------------ */
/** ContinuationSupport.
* Conveniance class to avoid classloading visibility issues.
*
*
*/
public class ContinuationSupport
{
public static Continuation getContinuation(HttpServletRequest request, Object mutex)
public static Continuation getContinuation(ServletRequest request)
{
Continuation continuation = (Continuation) request.getAttribute("org.eclipse.jetty.ajax.Continuation");
Continuation continuation = (Continuation) request.getAttribute(Continuation.ATTRIBUTE);
if (continuation==null)
continuation=new WaitingContinuation(mutex);
else
continuation.setMutex(mutex);
throw new IllegalStateException("!Jetty && !ContinuationFilter installed");
return continuation;
}
}

View File

@ -164,7 +164,7 @@ public abstract class MappedLoginService extends AbstractLifeCycle implements Lo
* @param roles
* @return UserIdentity
*/
protected synchronized UserIdentity putUser(String userName, Credential credential, String[] roles)
public synchronized UserIdentity putUser(String userName, Credential credential, String[] roles)
{
Principal userPrincipal = new KnownUser(userName,credential);
Subject subject = new Subject();

View File

@ -260,7 +260,7 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti
List<LoginService> list = getServer().getBeans(LoginService.class);
for (LoginService service : list)
if (service.getName().equals(getRealmName()))
if (service.getName()!=null && service.getName().equals(getRealmName()))
return service;
if (list.size()>0)
return list.get(0);

View File

@ -97,6 +97,11 @@
<groupId>org.mortbay.jetty</groupId>
<artifactId>servlet-api</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-continuation</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-http</artifactId>

View File

@ -0,0 +1,27 @@
package org.eclipse.jetty.server;
import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
/* temporary interface in anticipation of servlet 3.0 */
public interface AsyncContext
{
static final String ASYNC_REQUEST_URI = "javax.servlet.async.request_uri";
static final String ASYNC_CONTEXT_PATH = "javax.servlet.async.context_path";
static final String ASYNC_PATH_INFO = "javax.servlet.async.path_info";
static final String ASYNC_SERVLET_PATH = "javax.servlet.async.servlet_path";
static final String ASYNC_QUERY_STRING = "javax.servlet.async.query_string";
public ServletRequest getRequest();
public ServletResponse getResponse();
public boolean hasOriginalRequestAndResponse();
public void dispatch();
public void dispatch(String path);
public void dispatch(ServletContext context, String path);
public void complete();
public void start(Runnable run);
}

View File

@ -13,13 +13,13 @@
package org.eclipse.jetty.server;
import javax.servlet.AsyncContext;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.eclipse.jetty.continuation.ContinuationEvent;
import org.eclipse.jetty.continuation.ContinuationListener;
import org.eclipse.jetty.continuation.Continuation;
import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.server.handler.ContextHandler;
@ -31,10 +31,8 @@ import org.eclipse.jetty.util.thread.Timeout;
/* ------------------------------------------------------------ */
/** Asyncrhonous Request.
*
*
*
*/
public class AsyncRequest implements AsyncContext
public class AsyncRequest implements AsyncContext, Continuation
{
// STATES:
private static final int __IDLE=0; // Idle request
@ -62,11 +60,14 @@ public class AsyncRequest implements AsyncContext
/* ------------------------------------------------------------ */
protected HttpConnection _connection;
protected Object _listeners;
private Object _listeners;
/* ------------------------------------------------------------ */
private int _state;
private boolean _initial;
private boolean _resumed;
private boolean _expired;
private boolean _keepWrappers;
private long _timeoutMs;
private AsyncEventState _event;
@ -76,14 +77,6 @@ public class AsyncRequest implements AsyncContext
_state=__IDLE;
_initial=true;
}
/* ------------------------------------------------------------ */
protected AsyncRequest(final HttpConnection connection)
{
this();
if (connection!=null)
setConnection(connection);
}
/* ------------------------------------------------------------ */
protected void setConnection(final HttpConnection connection)
@ -91,6 +84,12 @@ public class AsyncRequest implements AsyncContext
_connection=connection;
}
/* ------------------------------------------------------------ */
public void addContinuationListener(ContinuationListener listener)
{
_listeners=LazyList.add(_listeners,listener);
}
/* ------------------------------------------------------------ */
public void setAsyncTimeout(long ms)
{
@ -109,6 +108,24 @@ public class AsyncRequest implements AsyncContext
return _event;
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.continuation.Continuation#keepWrappers()
*/
public void keepWrappers()
{
_keepWrappers=true;
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.continuation.Continuation#wrappersKept()
*/
public boolean wrappersKept()
{
return _keepWrappers;
}
/* ------------------------------------------------------------ */
/* (non-Javadoc)
* @see javax.servlet.ServletRequest#isInitial()
@ -178,6 +195,8 @@ public class AsyncRequest implements AsyncContext
{
synchronized (this)
{
_keepWrappers=false;
switch(_state)
{
case __DISPATCHED:
@ -220,7 +239,16 @@ public class AsyncRequest implements AsyncContext
{
synchronized (this)
{
_event=new AsyncEventState(context,request,response);
_resumed=false;
_expired=false;
if (_event==null || request!=_event.getRequest() || response != _event.getResponse() || context != _event.getServletContext())
_event=new AsyncEventState(context,request,response);
else
{
_event._dispatchContext=null;
_event._path=null;
}
switch(_state)
{
@ -322,11 +350,13 @@ public class AsyncRequest implements AsyncContext
case __SUSPENDING:
_state=__REDISPATCHING;
_resumed=true;
return;
case __SUSPENDED:
dispatch=true;
_state=__UNSUSPENDING;
_resumed=true;
break;
case __UNSUSPENDING:
@ -357,6 +387,7 @@ public class AsyncRequest implements AsyncContext
default:
return;
}
_expired=true;
}
if (_listeners!=null)
@ -365,7 +396,7 @@ public class AsyncRequest implements AsyncContext
{
try
{
AsyncListener listener=((AsyncListener)LazyList.get(_listeners,i));
ContinuationListener listener=((ContinuationListener)LazyList.get(_listeners,i));
listener.onTimeout(_event);
}
catch(Exception e)
@ -461,7 +492,7 @@ public class AsyncRequest implements AsyncContext
{
try
{
((AsyncListener)LazyList.get(_listeners,i)).onComplete(_event);
((ContinuationListener)LazyList.get(_listeners,i)).onComplete(_event);
}
catch(Exception e)
{
@ -485,8 +516,10 @@ public class AsyncRequest implements AsyncContext
_state=__IDLE;
}
_initial = true;
_resumed=false;
_expired=false;
_keepWrappers=false;
cancelTimeout();
_event=null;
_timeoutMs=60000L; // TODO configure
_listeners=null;
}
@ -500,7 +533,6 @@ public class AsyncRequest implements AsyncContext
_state=__COMPLETE;
_initial = false;
cancelTimeout();
_event=null;
_listeners=null;
}
}
@ -558,8 +590,12 @@ public class AsyncRequest implements AsyncContext
this.notifyAll();
}
}
else if (_event!=null)
_connection.cancelTimeout(_event._timeout);
else
{
final AsyncEventState event=_event;
if (event!=null)
_connection.cancelTimeout(event._timeout);
}
}
/* ------------------------------------------------------------ */
@ -662,27 +698,77 @@ public class AsyncRequest implements AsyncContext
return ((Context)_event.getServletContext()).getContextHandler();
return null;
}
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
public class AsyncEventState extends AsyncEvent
/**
* @see Continuation#isResumed()
*/
public boolean isResumed()
{
final Timeout.Task _timeout;
final ServletContext _suspendedContext;
return _resumed;
}
/* ------------------------------------------------------------ */
/**
* @see Continuation#isExpired()
*/
public boolean isExpired()
{
return _expired;
}
/* ------------------------------------------------------------ */
/**
* @see Continuation#resume()
*/
public void resume()
{
dispatch();
}
/* ------------------------------------------------------------ */
/**
* @see Continuation#suspend(long)
*/
public void setTimeout(long timeoutMs)
{
setAsyncTimeout(timeoutMs);
}
/* ------------------------------------------------------------ */
/**
* @see Continuation#suspend()
*/
public void suspend()
{
// TODO simplify?
AsyncRequest.this.suspend(_connection.getRequest().getServletContext(),_connection.getRequest(),_connection.getResponse());
}
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
public class AsyncEventState implements ContinuationEvent
{
private final ServletContext _suspendedContext;
private final ServletRequest _request;
private final ServletResponse _response;
ServletContext _dispatchContext;
String _path;
final Timeout.Task _timeout = new Timeout.Task()
{
public void expired()
{
AsyncRequest.this.expired();
}
};
public AsyncEventState(ServletContext context, ServletRequest request, ServletResponse response)
{
super(request,response);
_suspendedContext=context;
_timeout= new Timeout.Task()
{
public void expired()
{
AsyncRequest.this.expired();
}
};
_request=request;
_response=response;
}
public ServletContext getSuspendedContext()
@ -699,6 +785,16 @@ public class AsyncRequest implements AsyncContext
{
return _dispatchContext==null?_suspendedContext:_dispatchContext;
}
public ServletRequest getRequest()
{
return _request;
}
public ServletResponse getResponse()
{
return _response;
}
public String getPath()
{

View File

@ -20,7 +20,6 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import javax.servlet.DispatcherType;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
@ -41,7 +40,6 @@ import org.eclipse.jetty.util.UrlEncoded;
*/
public class Dispatcher implements RequestDispatcher
{
/*
public static final String FORWARD_REQUEST_URI = "javax.servlet.forward.request_uri";
public static final String FORWARD_CONTEXT_PATH = "javax.servlet.forward.context_path";
public static final String FORWARD_PATH_INFO = "javax.servlet.forward.path_info";
@ -59,7 +57,6 @@ public class Dispatcher implements RequestDispatcher
public static final String ERROR_REQUEST_URI = "javax.servlet.error.request_uri";
public static final String ERROR_SERVLET_NAME = "javax.servlet.error.servlet_name";
public static final String ERROR_STATUS_CODE = "javax.servlet.error.status_code";
*/
/** Dispatch include attribute names */
public final static String __INCLUDE_PREFIX="javax.servlet.include.";

View File

@ -0,0 +1,11 @@
package org.eclipse.jetty.server;
public enum DispatcherType
{
FORWARD,
INCLUDE,
REQUEST,
ASYNC,
ERROR
}

View File

@ -17,7 +17,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import javax.servlet.DispatcherType;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

View File

@ -32,10 +32,6 @@ import java.util.Locale;
import java.util.Map;
import javax.security.auth.login.LoginException;
import javax.servlet.AsyncContext;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
import javax.servlet.DispatcherType;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletInputStream;
@ -49,6 +45,9 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.eclipse.jetty.continuation.ContinuationEvent;
import org.eclipse.jetty.continuation.ContinuationListener;
import org.eclipse.jetty.continuation.Continuation;
import org.eclipse.jetty.http.HttpCookie;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpHeaders;
@ -72,7 +71,6 @@ import org.eclipse.jetty.util.MultiMap;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.UrlEncoded;
import org.eclipse.jetty.util.ajax.Continuation;
import org.eclipse.jetty.util.log.Log;
/* ------------------------------------------------------------ */
@ -181,28 +179,9 @@ public class Request implements HttpServletRequest
}
/* ------------------------------------------------------------ */
public void addAsyncListener(AsyncListener listener)
public void addAsyncListener(ContinuationListener listener)
{
_async._listeners=LazyList.add(_async._listeners,listener);
}
/* ------------------------------------------------------------ */
public void addAsyncListener(final AsyncListener listener, ServletRequest servletRequest, ServletResponse servletResponse)
{
final AsyncEvent event = new AsyncEvent(servletRequest,servletResponse);
_async._listeners=LazyList.add(_async._listeners,new AsyncListener()
{
public void onComplete(AsyncEvent ev) throws IOException
{
listener.onComplete(event);
}
public void onTimeout(AsyncEvent ev) throws IOException
{
listener.onComplete(event);
}
});
_async.addContinuationListener((ContinuationListener)listener);
}
/* ------------------------------------------------------------ */
@ -210,6 +189,9 @@ public class Request implements HttpServletRequest
{
if (listener instanceof ServletRequestAttributeListener)
_requestAttributeListeners= LazyList.add(_requestAttributeListeners, listener);
if (listener instanceof ContinuationListener)
_async.addContinuationListener((ContinuationListener)listener);
}
/* ------------------------------------------------------------ */
@ -336,18 +318,8 @@ public class Request implements HttpServletRequest
*/
public Object getAttribute(String name)
{
if ("org.eclipse.jetty.util.ajax.Continuation".equals(name))
return getContinuation(true);
if (DispatcherType.ASYNC.equals(_dispatcherType))
{
// TODO handle forwards(path!)
if (name.equals(Dispatcher.FORWARD_PATH_INFO)) return getPathInfo();
if (name.equals(Dispatcher.FORWARD_REQUEST_URI)) return getRequestURI();
if (name.equals(Dispatcher.FORWARD_SERVLET_PATH)) return getServletPath();
if (name.equals(Dispatcher.FORWARD_CONTEXT_PATH)) return getContextPath();
if (name.equals(Dispatcher.FORWARD_QUERY_STRING)) return getQueryString();
}
if (Continuation.ATTRIBUTE.equals(name))
return _async;
if (_attributes==null)
return null;
@ -362,6 +334,7 @@ public class Request implements HttpServletRequest
{
if (_attributes==null)
return Collections.enumeration(Collections.EMPTY_LIST);
return AttributesMap.getAttributeNamesCopy(_attributes);
}
@ -456,17 +429,6 @@ public class Request implements HttpServletRequest
return _continuation;
}
/* ------------------------------------------------------------ */
/**
* @deprecated
*/
public Continuation getContinuation(boolean create)
{
if (_continuation==null && create)
_continuation=new Servlet3Continuation(this);
return _continuation;
}
/* ------------------------------------------------------------ */
/*
@ -1355,8 +1317,6 @@ public class Request implements HttpServletRequest
if (_savedNewSessions!=null)
_savedNewSessions.clear();
_savedNewSessions=null;
if (_continuation!=null && _continuation.isPending())
_continuation.reset();
}
/* ------------------------------------------------------------ */
@ -1833,35 +1793,5 @@ public class Request implements HttpServletRequest
return (_handled?"[":"(")+getMethod()+" "+_uri+(_handled?"]@":")@")+hashCode()+" "+super.toString();
}
/* ------------------------------------------------------------ */
/**
* @see javax.servlet.http.HttpServletRequest#login(javax.servlet.http.HttpServletResponse)
*/
public boolean login(HttpServletResponse response) throws IOException, LoginException
{
// TODO Auto-generated method stub
return false;
}
/* ------------------------------------------------------------ */
/**
* @see javax.servlet.http.HttpServletRequest#login(java.lang.String, java.lang.String)
*/
public void login(String username, String password) throws LoginException
{
// TODO Auto-generated method stub
}
/* ------------------------------------------------------------ */
/**
* @see javax.servlet.http.HttpServletRequest#logout()
*/
public void logout() throws LoginException
{
// TODO Auto-generated method stub
}
}

View File

@ -22,7 +22,6 @@ import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import javax.servlet.AsyncContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

View File

@ -1,115 +0,0 @@
// ========================================================================
// Copyright (c) 2004-2009 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.server;
import java.io.IOException;
import javax.servlet.AsyncContext;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
import org.eclipse.jetty.util.ajax.Continuation;
public class Servlet3Continuation implements Continuation, AsyncListener
{
AsyncContext _asyncContext;
Request _request;
Object _object;
RetryRequest _retry;
boolean _resumed=false;
boolean _timeout=false;
Servlet3Continuation(Request request)
{
_request=request;
}
public Object getObject()
{
return _object;
}
public boolean isExpired()
{
return _asyncContext!=null && _timeout;
}
public boolean isNew()
{
return _retry==null;
}
public boolean isPending()
{
return _asyncContext!=null && (_request.getAsyncRequest().isSuspended() || !_request.getAsyncRequest().isInitial());
}
public boolean isResumed()
{
return _asyncContext!=null && _resumed;
}
public void reset()
{
_resumed=false;
_timeout=false;
}
public void resume()
{
if (_asyncContext==null)
throw new IllegalStateException();
_resumed=true;
_asyncContext.dispatch();
}
public void setMutex(Object mutex)
{
}
public void setObject(Object o)
{
_object=o;
}
public boolean suspend(long timeout)
{
_asyncContext=_request.startAsync();;
if (!_request.getAsyncRequest().isInitial()||_resumed||_timeout)
{
_resumed=false;
_timeout=false;
return _resumed;
}
_request.setAsyncTimeout(timeout);
_request.addAsyncListener(this);
if (_retry==null)
_retry=new RetryRequest();
throw _retry;
}
public void onComplete(AsyncEvent event) throws IOException
{
}
public void onTimeout(AsyncEvent event) throws IOException
{
_timeout=true;
_request.getAsyncRequest().dispatch();
}
}

View File

@ -30,9 +30,7 @@ import java.util.Locale;
import java.util.Map;
import java.util.Set;
import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.FilterRegistration;
import javax.servlet.RequestDispatcher;
import javax.servlet.Servlet;
import javax.servlet.ServletContext;
@ -41,12 +39,9 @@ import javax.servlet.ServletContextAttributeListener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import javax.servlet.ServletRequestAttributeListener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.SessionCookieConfig;
import javax.servlet.SessionTrackingMode;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -54,6 +49,7 @@ import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.io.Buffer;
import org.eclipse.jetty.io.HttpException;
import org.eclipse.jetty.server.Dispatcher;
import org.eclipse.jetty.server.DispatcherType;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.HandlerContainer;
import org.eclipse.jetty.server.HttpConnection;
@ -1766,137 +1762,6 @@ public class ContextHandler extends HandlerWrapper implements Attributes, Server
ContextHandler.this.getInitParams().put(name,value);
return true;
}
/* ------------------------------------------------------------ */
/**
* @see javax.servlet.ServletContext#addFilter(java.lang.String, java.lang.Class)
*/
public FilterRegistration addFilter(String filterName, Class<? extends Filter> filterClass)
{
Log.warn("Use servlet Context");
return null;
}
/* ------------------------------------------------------------ */
/**
* @see javax.servlet.ServletContext#addFilter(java.lang.String, java.lang.String)
*/
public FilterRegistration addFilter(String filterName, String className)
{
Log.warn("Use servlet Context");
return null;
}
/* ------------------------------------------------------------ */
/**
* @see javax.servlet.ServletContext#addServlet(java.lang.String, java.lang.Class)
*/
public ServletRegistration addServlet(String servletName, Class<? extends Servlet> servletClass)
{
Log.warn("Use servlet Context");
return null;
}
/* ------------------------------------------------------------ */
/**
* @see javax.servlet.ServletContext#addServlet(java.lang.String, java.lang.String)
*/
public ServletRegistration addServlet(String servletName, String className)
{
Log.warn("Use servlet Context");
return null;
}
/* ------------------------------------------------------------ */
/**
* @see javax.servlet.ServletContext#findFilterRegistration(java.lang.String)
*/
public FilterRegistration findFilterRegistration(String filterName)
{
Log.warn("Use servlet Context");
return null;
}
/* ------------------------------------------------------------ */
/**
* @see javax.servlet.ServletContext#findServletRegistration(java.lang.String)
*/
public ServletRegistration findServletRegistration(String servletName)
{
Log.warn("Use servlet Context");
return null;
}
/* ------------------------------------------------------------ */
/**
* @see javax.servlet.ServletContext#getDefaultSessionTrackingModes()
*/
public EnumSet<SessionTrackingMode> getDefaultSessionTrackingModes()
{
Log.warn("Use servlet Context");
return null;
}
/* ------------------------------------------------------------ */
/**
* @see javax.servlet.ServletContext#getEffectiveSessionTrackingModes()
*/
public EnumSet<SessionTrackingMode> getEffectiveSessionTrackingModes()
{
Log.warn("Use servlet Context");
return null;
}
/* ------------------------------------------------------------ */
/**
* @see javax.servlet.ServletContext#getSessionCookieConfig()
*/
public SessionCookieConfig getSessionCookieConfig()
{
Log.warn("Use servlet Context");
return null;
}
/* ------------------------------------------------------------ */
/**
* @see javax.servlet.ServletContext#setSessionTrackingModes(java.util.EnumSet)
*/
public void setSessionTrackingModes(EnumSet<SessionTrackingMode> sessionTrackingModes)
{
Log.warn("Use servlet Context");
}
/* ------------------------------------------------------------ */
/**
* @see javax.servlet.ServletContext#addFilter(java.lang.String, javax.servlet.Filter)
*/
public FilterRegistration addFilter(String filterName, Filter filter)
{
Log.warn("Use servlet Context");
return null;
}
/* ------------------------------------------------------------ */
/**
* @see javax.servlet.ServletContext#addServlet(java.lang.String, javax.servlet.Servlet)
*/
public ServletRegistration addServlet(String servletName, Servlet servlet)
{
Log.warn("Use servlet Context");
return null;
}
/* ------------------------------------------------------------ */
/**
* @see javax.servlet.ServletContext#setSessionTrackingModes(java.util.Set)
*/
public void setSessionTrackingModes(Set<SessionTrackingMode> sessionTrackingModes)
{
// TODO Auto-generated method stub
Log.warn("Not implemented");
}
}

View File

@ -15,11 +15,11 @@ package org.eclipse.jetty.server.handler;
import java.io.IOException;
import javax.servlet.DispatcherType;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.DispatcherType;
import org.eclipse.jetty.server.HttpConnection;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.RequestLog;

View File

@ -43,7 +43,7 @@ import org.eclipse.jetty.util.thread.Timeout.Task;
* This connector is best used when there are a many connections that have idle periods.
* </p>
* <p>
* When used with {@link org.eclipse.jetty.util.ajax.Continuation}, threadless waits are supported. When
* When used with {@link org.eclipse.jetty.continuation.Continuation}, threadless waits are supported. When
* a filter or servlet calls getEvent on a Continuation, a {@link org.eclipse.jetty.server.RetryRequest}
* runtime exception is thrown to allow the thread to exit the current request handling. Jetty will
* catch this exception and will not send a response to the client. Instead the thread is released

View File

@ -17,15 +17,14 @@ import java.io.IOException;
import java.util.EnumSet;
import java.util.EventListener;
import javax.servlet.DispatcherType;
import javax.servlet.ServletException;
import javax.servlet.SessionTrackingMode;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.eclipse.jetty.http.HttpCookie;
import org.eclipse.jetty.server.DispatcherType;
import org.eclipse.jetty.server.HttpConnection;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.RetryRequest;
@ -42,8 +41,6 @@ import org.eclipse.jetty.util.log.Log;
*/
public class SessionHandler extends HandlerWrapper
{
public final static EnumSet<SessionTrackingMode> DEFAULT_TRACKING = EnumSet.of(SessionTrackingMode.COOKIE,SessionTrackingMode.URL);
/* -------------------------------------------------------------- */
private SessionManager _sessionManager;

View File

@ -16,16 +16,14 @@ package org.eclipse.jetty.server;
import java.io.IOException;
import java.io.InputStream;
import javax.servlet.AsyncContext;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
import javax.servlet.DispatcherType;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import junit.framework.TestCase;
import org.eclipse.jetty.continuation.ContinuationEvent;
import org.eclipse.jetty.continuation.ContinuationListener;
import org.eclipse.jetty.server.handler.HandlerWrapper;
public class AsyncContextTest extends TestCase
@ -277,14 +275,14 @@ public class AsyncContextTest extends TestCase
}
private static AsyncListener __asyncListener =
new AsyncListener()
private static ContinuationListener __asyncListener =
new ContinuationListener()
{
public void onComplete(AsyncEvent event) throws IOException
public void onComplete(ContinuationEvent event) throws IOException
{
}
public void onTimeout(AsyncEvent event) throws IOException
public void onTimeout(ContinuationEvent event) throws IOException
{
event.getRequest().setAttribute("TIMEOUT",Boolean.TRUE);
((Request)event.getRequest()).getAsyncContext().dispatch();

View File

@ -26,12 +26,12 @@ import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.continuation.Continuation;
import org.eclipse.jetty.continuation.ContinuationSupport;
import org.eclipse.jetty.http.HttpHeaders;
import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.ajax.Continuation;
import org.eclipse.jetty.util.ajax.ContinuationSupport;
import org.eclipse.jetty.util.log.Log;
/* ------------------------------------------------------------ */
@ -68,8 +68,9 @@ public class DumpHandler extends AbstractHandler
if (request.getParameter("continue")!=null)
{
Continuation continuation = ContinuationSupport.getContinuation(request, null);
continuation.suspend(Long.parseLong(request.getParameter("continue")));
Continuation continuation = ContinuationSupport.getContinuation(request);
continuation.setTimeout(Long.parseLong(request.getParameter("continue")));
continuation.suspend();
}
base_request.setHandled(true);

View File

@ -326,7 +326,7 @@ public class HttpTester
cookie.getMaxAge(),
cookie.getComment(),
cookie.getSecure(),
cookie.isHttpOnly(),
false,
cookie.getVersion());
}

View File

@ -15,11 +15,10 @@ package org.eclipse.jetty.servlet;
import java.util.EnumSet;
import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.FilterConfig;
import javax.servlet.FilterRegistration;
import org.eclipse.jetty.server.DispatcherType;
import org.eclipse.jetty.util.log.Log;
/* --------------------------------------------------------------------- */
@ -132,49 +131,6 @@ public class FilterHolder extends Holder
return getName();
}
public FilterRegistration getRegistration()
{
return new Registration();
}
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
protected class Registration extends HolderRegistration implements FilterRegistration
{
/* ------------------------------------------------------------ */
public boolean addMappingForServletNames(EnumSet<DispatcherType> dispatcherTypes, boolean isMatchAfter, String... servletNames)
{
illegalStateIfContextStarted();
FilterMapping mapping = new FilterMapping();
mapping.setFilterHolder(FilterHolder.this);
mapping.setServletNames(servletNames);
mapping.setDispatcherTypes(dispatcherTypes);
if (isMatchAfter)
_servletHandler.addFilterMapping(mapping);
else
_servletHandler.prependFilterMapping(mapping);
return true;
}
public boolean addMappingForUrlPatterns(EnumSet<DispatcherType> dispatcherTypes, boolean isMatchAfter, String... urlPatterns)
{
illegalStateIfContextStarted();
FilterMapping mapping = new FilterMapping();
mapping.setFilterHolder(FilterHolder.this);
mapping.setPathSpecs(urlPatterns);
mapping.setDispatcherTypes(dispatcherTypes);
if (isMatchAfter)
_servletHandler.addFilterMapping(mapping);
else
_servletHandler.prependFilterMapping(mapping);
return true;
}
}
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */

View File

@ -16,9 +16,9 @@ package org.eclipse.jetty.servlet;
import java.util.Arrays;
import java.util.EnumSet;
import javax.servlet.DispatcherType;
import org.eclipse.jetty.http.PathMap;
import org.eclipse.jetty.server.DispatcherType;
import org.eclipse.jetty.server.Handler;

View File

@ -33,14 +33,14 @@ import org.eclipse.jetty.util.log.Log;
/**
*
*/
public class Holder extends AbstractLifeCycle implements Serializable
public class Holder extends AbstractLifeCycle
{
protected transient Class _class;
protected transient Class<?> _class;
protected String _className;
protected String _displayName;
protected Map _initParams;
protected boolean _extInstance;
protected boolean _asyncSupported;
protected boolean _asyncSupported=true;
protected AttributesMap _initAttributes;
/* ---------------------------------------------------------------- */
@ -296,80 +296,6 @@ public class Holder extends AbstractLifeCycle implements Serializable
return Holder.this._initAttributes.keySet();
return Collections.emptySet();
}
}
/* -------------------------------------------------------- */
/* -------------------------------------------------------- */
/* -------------------------------------------------------- */
protected class HolderRegistration
{
public boolean setAsyncSupported(boolean isAsyncSupported)
{
illegalStateIfContextStarted();
Holder.this.setAsyncSupported(isAsyncSupported);
return true;
}
public boolean setDescription(String description)
{
return true;
}
public boolean setInitParameter(String name, String value)
{
illegalStateIfContextStarted();
if (Holder.this.getInitParameter(name)!=null)
return false;
Holder.this.setInitParameter(name,value);
return true;
}
public boolean setInitParameters(Map<String, String> initParameters)
{
illegalStateIfContextStarted();
for (String name : initParameters.keySet())
if (Holder.this.getInitParameter(name)!=null)
return false;
Holder.this.setInitParameters(initParameters);
return true;
}
/* ------------------------------------------------------------ */
/**
* @see javax.servlet.ServletRegistration#setInitAttribute(java.lang.String, java.lang.Object)
*/
public boolean setInitAttribute(String name, Object value)
{
illegalStateIfContextStarted();
if (_initAttributes==null)
_initAttributes=new AttributesMap();
else if (_initAttributes.getAttribute(name)!=null)
return false;
_initAttributes.setAttribute(name,value);
return true;
}
/* ------------------------------------------------------------ */
/**
* @see javax.servlet.ServletRegistration#setInitAttributes(java.util.Map)
*/
public boolean setInitAttributes(Map<String, Object> initAttributes)
{
illegalStateIfContextStarted();
if (_initAttributes==null)
_initAttributes=new AttributesMap();
else
{
for (String name : initAttributes.keySet())
if (_initAttributes.getAttribute(name)!=null)
return false;
}
for (String name : initAttributes.keySet())
_initAttributes.setAttribute(name,initAttributes.get(name));
return true;
};
}
}

View File

@ -15,23 +15,19 @@ package org.eclipse.jetty.servlet;
import java.util.EnumSet;
import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.FilterRegistration;
import javax.servlet.RequestDispatcher;
import javax.servlet.Servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletRegistration;
import javax.servlet.SessionTrackingMode;
import org.eclipse.jetty.security.SecurityHandler;
import org.eclipse.jetty.server.Dispatcher;
import org.eclipse.jetty.server.DispatcherType;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.HandlerContainer;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.ErrorHandler;
import org.eclipse.jetty.server.session.SessionHandler;
import org.eclipse.jetty.util.log.Log;
/* ------------------------------------------------------------ */
@ -352,150 +348,6 @@ public class ServletContextHandler extends ContextHandler
handler.addServlet(holder);
}
/* ------------------------------------------------------------ */
/**
* @see javax.servlet.ServletContext#addFilter(java.lang.String, java.lang.Class)
*/
public FilterRegistration addFilter(String filterName, Class<? extends Filter> filterClass)
{
if (isStarted())
throw new IllegalStateException();
final ServletHandler handler = ServletContextHandler.this.getServletHandler();
final FilterHolder holder= handler.newFilterHolder();
holder.setName(filterName);
holder.setHeldClass(filterClass);
handler.addFilter(holder);
return holder.getRegistration();
}
/* ------------------------------------------------------------ */
/**
* @see javax.servlet.ServletContext#addFilter(java.lang.String, java.lang.String)
*/
public FilterRegistration addFilter(String filterName, String className)
{
if (isStarted())
throw new IllegalStateException();
final ServletHandler handler = ServletContextHandler.this.getServletHandler();
final FilterHolder holder= handler.newFilterHolder();
holder.setName(filterName);
holder.setClassName(className);
handler.addFilter(holder);
return holder.getRegistration();
}
/* ------------------------------------------------------------ */
/**
* @see javax.servlet.ServletContext#addFilter(java.lang.String, javax.servlet.Filter)
*/
public FilterRegistration addFilter(String filterName, Filter filter)
{
if (isStarted())
throw new IllegalStateException();
final ServletHandler handler = ServletContextHandler.this.getServletHandler();
final FilterHolder holder= handler.newFilterHolder();
holder.setName(filterName);
holder.setFilter(filter);
handler.addFilter(holder);
return holder.getRegistration();
}
/* ------------------------------------------------------------ */
/**
* @see javax.servlet.ServletContext#addServlet(java.lang.String, java.lang.Class)
*/
public ServletRegistration addServlet(String servletName, Class<? extends Servlet> servletClass)
{
if (!isStarting())
throw new IllegalStateException();
final ServletHandler handler = ServletContextHandler.this.getServletHandler();
final ServletHolder holder= handler.newServletHolder();
holder.setName(servletName);
holder.setHeldClass(servletClass);
handler.addServlet(holder);
return holder.getRegistration();
}
/* ------------------------------------------------------------ */
/**
* @see javax.servlet.ServletContext#addServlet(java.lang.String, java.lang.String)
*/
public ServletRegistration addServlet(String servletName, String className)
{
if (!isStarting())
throw new IllegalStateException();
final ServletHandler handler = ServletContextHandler.this.getServletHandler();
final ServletHolder holder= handler.newServletHolder();
holder.setName(servletName);
holder.setClassName(className);
handler.addServlet(holder);
return holder.getRegistration();
}
/* ------------------------------------------------------------ */
/**
* @see javax.servlet.ServletContext#addServlet(java.lang.String, javax.servlet.Servlet)
*/
public ServletRegistration addServlet(String servletName, Servlet servlet)
{
if (!isStarting())
throw new IllegalStateException();
final ServletHandler handler = ServletContextHandler.this.getServletHandler();
final ServletHolder holder= handler.newServletHolder();
holder.setName(servletName);
holder.setServlet(servlet);
handler.addServlet(holder);
return holder.getRegistration();
}
/* ------------------------------------------------------------ */
/**
* @see javax.servlet.ServletContext#findFilterRegistration(java.lang.String)
*/
public FilterRegistration findFilterRegistration(String filterName)
{
final ServletHandler handler = ServletContextHandler.this.getServletHandler();
final FilterHolder holder=handler.getFilter(filterName);
return (holder==null)?null:holder.getRegistration();
}
/* ------------------------------------------------------------ */
/**
* @see javax.servlet.ServletContext#findServletRegistration(java.lang.String)
*/
public ServletRegistration findServletRegistration(String servletName)
{
final ServletHandler handler = ServletContextHandler.this.getServletHandler();
final ServletHolder holder=handler.getServlet(servletName);
return (holder==null)?null:holder.getRegistration();
}
/* ------------------------------------------------------------ */
/**
* @see javax.servlet.ServletContext#getDefaultSessionTrackingModes()
*/
public EnumSet<SessionTrackingMode> getDefaultSessionTrackingModes()
{
return SessionHandler.DEFAULT_TRACKING;
}
/* ------------------------------------------------------------ */
/**
* @see javax.servlet.ServletContext#getEffectiveSessionTrackingModes()
*/
public EnumSet<SessionTrackingMode> getEffectiveSessionTrackingModes()
{
Log.warn("Not Implemented");
return null;
}
}

View File

@ -21,7 +21,6 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.RequestDispatcher;
@ -42,6 +41,7 @@ import org.eclipse.jetty.io.HttpException;
import org.eclipse.jetty.security.IdentityService;
import org.eclipse.jetty.security.SecurityHandler;
import org.eclipse.jetty.server.Dispatcher;
import org.eclipse.jetty.server.DispatcherType;
import org.eclipse.jetty.server.HttpConnection;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.RetryRequest;

View File

@ -22,7 +22,6 @@ import java.util.Stack;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.SingleThreadModel;
@ -554,34 +553,6 @@ public class ServletHolder extends Holder implements UserIdentity.Scope, Compara
}
/* -------------------------------------------------------- */
/* -------------------------------------------------------- */
/* -------------------------------------------------------- */
protected class Registration extends HolderRegistration implements ServletRegistration
{
public boolean addMapping(String... urlPatterns)
{
illegalStateIfContextStarted();
ServletMapping mapping = new ServletMapping();
mapping.setServletName(ServletHolder.this.getName());
mapping.setPathSpecs(urlPatterns);
_servletHandler.addServletMapping(mapping);
return true;
}
public boolean setLoadOnStartup(int loadOnStartup)
{
illegalStateIfContextStarted();
ServletHolder.this.setInitOrder(loadOnStartup);
return false;
}
}
public ServletRegistration getRegistration()
{
return new Registration();
}
/* -------------------------------------------------------- */
/* -------------------------------------------------------- */
/* -------------------------------------------------------- */

View File

@ -28,6 +28,7 @@ import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.SessionIdManager;
import org.eclipse.jetty.server.SessionManager;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
@ -76,7 +77,7 @@ public abstract class SessionTestServer extends Server
pathInfo = pathInfo.substring(8);
String cpath = pathInfo.substring(0, pathInfo.indexOf('/', 1));
pathInfo = pathInfo.substring(cpath.length());
ServletContext context = request.getServletContext().getContext(cpath);
ServletContext context = ((Request)request).getServletContext().getContext(cpath);
RequestDispatcher dispatcher = context.getRequestDispatcher(pathInfo);
dispatcher.forward(request, response);
}

View File

@ -52,6 +52,11 @@
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-continuation</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>

View File

@ -1,352 +0,0 @@
// ========================================================================
// Copyright (c) 2006-2009 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.servlets;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.Socket;
import java.util.Enumeration;
import java.util.HashSet;
import javax.servlet.AsyncContext;
import javax.servlet.DispatcherType;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.HttpExchange;
import org.eclipse.jetty.http.HttpHeaders;
import org.eclipse.jetty.http.HttpSchemes;
import org.eclipse.jetty.http.HttpURI;
import org.eclipse.jetty.io.Buffer;
import org.eclipse.jetty.io.EofException;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.log.Log;
/**
* EXPERIMENTAL Proxy servlet.
*
*
*/
public class AsyncProxyServlet implements Servlet
{
HttpClient _client;
protected HashSet<String> _DontProxyHeaders = new HashSet<String>();
{
_DontProxyHeaders.add("proxy-connection");
_DontProxyHeaders.add("connection");
_DontProxyHeaders.add("keep-alive");
_DontProxyHeaders.add("transfer-encoding");
_DontProxyHeaders.add("te");
_DontProxyHeaders.add("trailer");
_DontProxyHeaders.add("proxy-authorization");
_DontProxyHeaders.add("proxy-authenticate");
_DontProxyHeaders.add("upgrade");
}
private ServletConfig config;
private ServletContext context;
/* (non-Javadoc)
* @see javax.servlet.Servlet#init(javax.servlet.ServletConfig)
*/
public void init(ServletConfig config) throws ServletException
{
this.config=config;
this.context=config.getServletContext();
_client=new HttpClient();
//_client.setConnectorType(HttpClient.CONNECTOR_SOCKET);
_client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
try
{
_client.start();
}
catch (Exception e)
{
throw new ServletException(e);
}
}
/* (non-Javadoc)
* @see javax.servlet.Servlet#getServletConfig()
*/
public ServletConfig getServletConfig()
{
return config;
}
/* (non-Javadoc)
* @see javax.servlet.Servlet#service(javax.servlet.ServletRequest, javax.servlet.ServletResponse)
*/
public void service(ServletRequest req, ServletResponse res) throws ServletException,
IOException
{
final HttpServletRequest request = (HttpServletRequest)req;
final HttpServletResponse response = (HttpServletResponse)res;
if ("CONNECT".equalsIgnoreCase(request.getMethod()))
{
handleConnect(request,response);
}
else
{
final InputStream in=request.getInputStream();
final OutputStream out=response.getOutputStream();
if (request.getDispatcherType()!=DispatcherType.ASYNC)
{
String uri=request.getRequestURI();
if (request.getQueryString()!=null)
uri+="?"+request.getQueryString();
HttpURI url=proxyHttpURI(request.getScheme(),
request.getServerName(),
request.getServerPort(),
uri);
if (url==null)
{
response.sendError(HttpServletResponse.SC_FORBIDDEN);
return;
}
final AsyncContext async=request.startAsync(request,response);
HttpExchange exchange = new HttpExchange()
{
protected void onRequestCommitted() throws IOException
{
}
protected void onRequestComplete() throws IOException
{
}
protected void onResponseComplete() throws IOException
{
async.complete();
}
protected void onResponseContent(Buffer content) throws IOException
{
content.writeTo(out);
}
protected void onResponseHeaderComplete() throws IOException
{
}
protected void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException
{
if (reason!=null && reason.length()>0)
response.setStatus(status,reason.toString());
else
response.setStatus(status);
}
protected void onResponseHeader(Buffer name, Buffer value) throws IOException
{
String s = name.toString().toLowerCase();
if (!_DontProxyHeaders.contains(s))
response.addHeader(name.toString(),value.toString());
}
protected void onConnectionFailed(Throwable ex)
{
onException(ex);
}
protected void onException(Throwable ex)
{
if (ex instanceof EofException)
{
Log.ignore(ex);
return;
}
Log.warn(ex.toString());
Log.debug(ex);
if (!response.isCommitted())
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
async.complete();
}
protected void onExpire()
{
if (!response.isCommitted())
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
async.complete();
}
};
exchange.setScheme(HttpSchemes.HTTPS.equals(request.getScheme())?HttpSchemes.HTTPS_BUFFER:HttpSchemes.HTTP_BUFFER);
exchange.setMethod(request.getMethod());
exchange.setURL(url.toString());
exchange.setVersion(request.getProtocol());
if (Log.isDebugEnabled())
Log.debug("PROXY TO "+url);
// check connection header
String connectionHdr = request.getHeader("Connection");
if (connectionHdr!=null)
{
connectionHdr=connectionHdr.toLowerCase();
if (connectionHdr.indexOf("keep-alive")<0 &&
connectionHdr.indexOf("close")<0)
connectionHdr=null;
}
// copy headers
boolean xForwardedFor=false;
boolean hasContent=false;
long contentLength=-1;
Enumeration<?> enm = request.getHeaderNames();
while (enm.hasMoreElements())
{
// TODO could be better than this!
String hdr=(String)enm.nextElement();
String lhdr=hdr.toLowerCase();
if (_DontProxyHeaders.contains(lhdr))
continue;
if (connectionHdr!=null && connectionHdr.indexOf(lhdr)>=0)
continue;
if ("content-type".equals(lhdr))
hasContent=true;
if ("content-length".equals(lhdr))
{
contentLength=request.getContentLength();
exchange.setRequestHeader(HttpHeaders.CONTENT_LENGTH,TypeUtil.toString(contentLength));
if (contentLength>0)
hasContent=true;
}
Enumeration<?> vals = request.getHeaders(hdr);
while (vals.hasMoreElements())
{
String val = (String)vals.nextElement();
if (val!=null)
{
exchange.setRequestHeader(lhdr,val);
xForwardedFor|="X-Forwarded-For".equalsIgnoreCase(hdr);
}
}
}
// Proxy headers
exchange.setRequestHeader("Via","1.1 (jetty)");
if (!xForwardedFor)
exchange.addRequestHeader("X-Forwarded-For",
request.getRemoteAddr());
if (hasContent)
exchange.setRequestContentSource(in);
_client.send(exchange);
}
}
}
/* ------------------------------------------------------------ */
public void handleConnect(HttpServletRequest request,
HttpServletResponse response)
throws IOException
{
String uri = request.getRequestURI();
context.log("CONNECT: "+uri);
String port = "";
String host = "";
int c = uri.indexOf(':');
if (c>=0)
{
port = uri.substring(c+1);
host = uri.substring(0,c);
if (host.indexOf('/')>0)
host = host.substring(host.indexOf('/')+1);
}
// TODO - make this async!
InetSocketAddress inetAddress = new InetSocketAddress (host, Integer.parseInt(port));
//if (isForbidden(HttpMessage.__SSL_SCHEME,addrPort.getHost(),addrPort.getPort(),false))
//{
// sendForbid(request,response,uri);
//}
//else
{
InputStream in=request.getInputStream();
OutputStream out=response.getOutputStream();
Socket socket = new Socket(inetAddress.getAddress(),inetAddress.getPort());
context.log("Socket: "+socket);
response.setStatus(200);
response.setHeader("Connection","close");
response.flushBuffer();
// TODO prevent real close!
context.log("out<-in");
IO.copyThread(socket.getInputStream(),out);
context.log("in->out");
IO.copy(in,socket.getOutputStream());
}
}
/* ------------------------------------------------------------ */
protected HttpURI proxyHttpURI(String scheme, String serverName, int serverPort, String uri)
throws MalformedURLException
{
return new HttpURI(scheme+"://"+serverName+":"+serverPort+uri);
}
/* (non-Javadoc)
* @see javax.servlet.Servlet#getServletInfo()
*/
public String getServletInfo()
{
return "Proxy Servlet";
}
/* (non-Javadoc)
* @see javax.servlet.Servlet#destroy()
*/
public void destroy()
{
}
}

View File

@ -21,8 +21,6 @@ import java.util.Set;
import java.util.StringTokenizer;
import java.util.zip.GZIPOutputStream;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
@ -33,6 +31,10 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import org.eclipse.jetty.continuation.Continuation;
import org.eclipse.jetty.continuation.ContinuationEvent;
import org.eclipse.jetty.continuation.ContinuationListener;
import org.eclipse.jetty.continuation.ContinuationSupport;
import org.eclipse.jetty.util.ByteArrayOutputStream2;
import org.eclipse.jetty.util.StringUtil;
@ -132,16 +134,17 @@ public class GzipFilter extends UserAgentFilter
}
finally
{
if (request.isAsyncStarted() && !req.getAsyncContext().hasOriginalRequestAndResponse())
Continuation continuation = ContinuationSupport.getContinuation(request);
if (continuation.isSuspended() && continuation.wrappersKept())
{
request.addAsyncListener(new AsyncListener()
continuation.addContinuationListener(new ContinuationListener()
{
public void onComplete(AsyncEvent event) throws IOException
public void onComplete(ContinuationEvent event) throws IOException
{
wrappedResponse.finish();
}
public void onTimeout(AsyncEvent event) throws IOException
public void onTimeout(ContinuationEvent event) throws IOException
{}
});
}

View File

@ -1,5 +1,5 @@
// ========================================================================
// Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd.
// Copyright (c) 2006-2009 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
@ -13,14 +13,13 @@
package org.eclipse.jetty.servlets;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.Socket;
import java.net.URL;
import java.net.URLConnection;
import java.util.Enumeration;
import java.util.HashSet;
@ -33,7 +32,18 @@ import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.HttpExchange;
import org.eclipse.jetty.continuation.Continuation;
import org.eclipse.jetty.continuation.ContinuationSupport;
import org.eclipse.jetty.http.HttpHeaders;
import org.eclipse.jetty.http.HttpSchemes;
import org.eclipse.jetty.http.HttpURI;
import org.eclipse.jetty.io.Buffer;
import org.eclipse.jetty.io.EofException;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.log.Log;
@ -44,9 +54,9 @@ import org.eclipse.jetty.util.IO;
*/
public class ProxyServlet implements Servlet
{
private int _tunnelTimeoutMs=300000;
protected final HashSet _DontProxyHeaders = new HashSet();
HttpClient _client;
protected HashSet<String> _DontProxyHeaders = new HashSet<String>();
{
_DontProxyHeaders.add("proxy-connection");
_DontProxyHeaders.add("connection");
@ -58,10 +68,10 @@ public class ProxyServlet implements Servlet
_DontProxyHeaders.add("proxy-authenticate");
_DontProxyHeaders.add("upgrade");
}
private ServletConfig config;
private ServletContext context;
/* (non-Javadoc)
* @see javax.servlet.Servlet#init(javax.servlet.ServletConfig)
*/
@ -69,6 +79,18 @@ public class ProxyServlet implements Servlet
{
this.config=config;
this.context=config.getServletContext();
_client=new HttpClient();
//_client.setConnectorType(HttpClient.CONNECTOR_SOCKET);
_client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
try
{
_client.start();
}
catch (Exception e)
{
throw new ServletException(e);
}
}
/* (non-Javadoc)
@ -85,161 +107,175 @@ public class ProxyServlet implements Servlet
public void service(ServletRequest req, ServletResponse res) throws ServletException,
IOException
{
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)res;
final HttpServletRequest request = (HttpServletRequest)req;
final HttpServletResponse response = (HttpServletResponse)res;
if ("CONNECT".equalsIgnoreCase(request.getMethod()))
{
handleConnect(request,response);
}
else
{
String uri=request.getRequestURI();
if (request.getQueryString()!=null)
uri+="?"+request.getQueryString();
URL url = new URL(request.getScheme(),
request.getServerName(),
request.getServerPort(),
uri);
final InputStream in=request.getInputStream();
final OutputStream out=response.getOutputStream();
final Continuation continuation = ContinuationSupport.getContinuation(request);
context.log("URL="+url);
URLConnection connection = url.openConnection();
connection.setAllowUserInteraction(false);
// Set method
HttpURLConnection http = null;
if (connection instanceof HttpURLConnection)
if (!continuation.isInitial())
response.sendError(HttpServletResponse.SC_GATEWAY_TIMEOUT); // Need better test that isInitial
else
{
http = (HttpURLConnection)connection;
http.setRequestMethod(request.getMethod());
http.setInstanceFollowRedirects(false);
}
String uri=request.getRequestURI();
if (request.getQueryString()!=null)
uri+="?"+request.getQueryString();
// check connection header
String connectionHdr = request.getHeader("Connection");
if (connectionHdr!=null)
{
connectionHdr=connectionHdr.toLowerCase();
if (connectionHdr.equals("keep-alive")||
connectionHdr.equals("close"))
connectionHdr=null;
}
// copy headers
boolean xForwardedFor=false;
boolean hasContent=false;
Enumeration enm = request.getHeaderNames();
while (enm.hasMoreElements())
{
// TODO could be better than this!
String hdr=(String)enm.nextElement();
String lhdr=hdr.toLowerCase();
HttpURI url=proxyHttpURI(request.getScheme(),
request.getServerName(),
request.getServerPort(),
uri);
if (url==null)
{
response.sendError(HttpServletResponse.SC_FORBIDDEN);
return;
}
if (_DontProxyHeaders.contains(lhdr))
continue;
if (connectionHdr!=null && connectionHdr.indexOf(lhdr)>=0)
continue;
if ("content-type".equals(lhdr))
hasContent=true;
Enumeration vals = request.getHeaders(hdr);
while (vals.hasMoreElements())
HttpExchange exchange = new HttpExchange()
{
String val = (String)vals.nextElement();
if (val!=null)
protected void onRequestCommitted() throws IOException
{
connection.addRequestProperty(hdr,val);
context.log("req "+hdr+": "+val);
xForwardedFor|="X-Forwarded-For".equalsIgnoreCase(hdr);
}
protected void onRequestComplete() throws IOException
{
}
protected void onResponseComplete() throws IOException
{
continuation.complete();
}
protected void onResponseContent(Buffer content) throws IOException
{
content.writeTo(out);
}
protected void onResponseHeaderComplete() throws IOException
{
}
protected void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException
{
if (reason!=null && reason.length()>0)
response.setStatus(status,reason.toString());
else
response.setStatus(status);
}
protected void onResponseHeader(Buffer name, Buffer value) throws IOException
{
String s = name.toString().toLowerCase();
if (!_DontProxyHeaders.contains(s))
response.addHeader(name.toString(),value.toString());
}
protected void onConnectionFailed(Throwable ex)
{
onException(ex);
}
protected void onException(Throwable ex)
{
if (ex instanceof EofException)
{
Log.ignore(ex);
return;
}
Log.warn(ex.toString());
Log.debug(ex);
if (!response.isCommitted())
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
continuation.complete();
}
protected void onExpire()
{
if (!response.isCommitted())
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
continuation.complete();
}
};
exchange.setScheme(HttpSchemes.HTTPS.equals(request.getScheme())?HttpSchemes.HTTPS_BUFFER:HttpSchemes.HTTP_BUFFER);
exchange.setMethod(request.getMethod());
exchange.setURL(url.toString());
exchange.setVersion(request.getProtocol());
if (Log.isDebugEnabled())
Log.debug("PROXY TO "+url);
// check connection header
String connectionHdr = request.getHeader("Connection");
if (connectionHdr!=null)
{
connectionHdr=connectionHdr.toLowerCase();
if (connectionHdr.indexOf("keep-alive")<0 &&
connectionHdr.indexOf("close")<0)
connectionHdr=null;
}
// copy headers
boolean xForwardedFor=false;
boolean hasContent=false;
long contentLength=-1;
Enumeration<?> enm = request.getHeaderNames();
while (enm.hasMoreElements())
{
// TODO could be better than this!
String hdr=(String)enm.nextElement();
String lhdr=hdr.toLowerCase();
if (_DontProxyHeaders.contains(lhdr))
continue;
if (connectionHdr!=null && connectionHdr.indexOf(lhdr)>=0)
continue;
if ("content-type".equals(lhdr))
hasContent=true;
if ("content-length".equals(lhdr))
{
contentLength=request.getContentLength();
exchange.setRequestHeader(HttpHeaders.CONTENT_LENGTH,TypeUtil.toString(contentLength));
if (contentLength>0)
hasContent=true;
}
Enumeration<?> vals = request.getHeaders(hdr);
while (vals.hasMoreElements())
{
String val = (String)vals.nextElement();
if (val!=null)
{
exchange.setRequestHeader(lhdr,val);
xForwardedFor|="X-Forwarded-For".equalsIgnoreCase(hdr);
}
}
}
}
// Proxy headers
connection.setRequestProperty("Via","1.1 (jetty)");
if (!xForwardedFor)
connection.addRequestProperty("X-Forwarded-For",
request.getRemoteAddr());
// Proxy headers
exchange.setRequestHeader("Via","1.1 (jetty)");
if (!xForwardedFor)
exchange.addRequestHeader("X-Forwarded-For",
request.getRemoteAddr());
// a little bit of cache control
String cache_control = request.getHeader("Cache-Control");
if (cache_control!=null &&
(cache_control.indexOf("no-cache")>=0 ||
cache_control.indexOf("no-store")>=0))
connection.setUseCaches(false);
// customize Connection
try
{
connection.setDoInput(true);
// do input thang!
InputStream in=request.getInputStream();
if (hasContent)
{
connection.setDoOutput(true);
IO.copy(in,connection.getOutputStream());
}
// Connect
connection.connect();
}
catch (Exception e)
{
context.log("proxy",e);
}
InputStream proxy_in = null;
exchange.setRequestContentSource(in);
// handler status codes etc.
int code=500;
if (http!=null)
{
proxy_in = http.getErrorStream();
code=http.getResponseCode();
response.setStatus(code, http.getResponseMessage());
context.log("response = "+http.getResponseCode());
}
if (proxy_in==null)
{
try {proxy_in=connection.getInputStream();}
catch (Exception e)
{
context.log("stream",e);
proxy_in = http.getErrorStream();
}
}
// clear response defaults.
response.setHeader("Date",null);
response.setHeader("Server",null);
// set response headers
int h=0;
String hdr=connection.getHeaderFieldKey(h);
String val=connection.getHeaderField(h);
while(hdr!=null || val!=null)
{
String lhdr = hdr!=null?hdr.toLowerCase():null;
if (hdr!=null && val!=null && !_DontProxyHeaders.contains(lhdr))
response.addHeader(hdr,val);
continuation.suspend();
continuation.keepWrappers();
_client.send(exchange);
context.log("res "+hdr+": "+val);
h++;
hdr=connection.getHeaderFieldKey(h);
val=connection.getHeaderField(h);
}
response.addHeader("Via","1.1 (jetty)");
// Handle
if (proxy_in!=null)
IO.copy(proxy_in,response.getOutputStream());
}
}
@ -250,12 +286,12 @@ public class ProxyServlet implements Servlet
throws IOException
{
String uri = request.getRequestURI();
context.log("CONNECT: "+uri);
String port = "";
String host = "";
int c = uri.indexOf(':');
if (c>=0)
{
@ -265,11 +301,11 @@ public class ProxyServlet implements Servlet
host = host.substring(host.indexOf('/')+1);
}
// TODO - make this async!
InetSocketAddress inetAddress = new InetSocketAddress (host, Integer.parseInt(port));
//if (isForbidden(HttpMessage.__SSL_SCHEME,addrPort.getHost(),addrPort.getPort(),false))
//{
// sendForbid(request,response,uri);
@ -278,15 +314,14 @@ public class ProxyServlet implements Servlet
{
InputStream in=request.getInputStream();
OutputStream out=response.getOutputStream();
Socket socket = new Socket(inetAddress.getAddress(),inetAddress.getPort());
context.log("Socket: "+socket);
response.setStatus(200);
response.setHeader("Connection","close");
response.flushBuffer();
// TODO prevent real close!
context.log("out<-in");
IO.copyThread(socket.getInputStream(),out);
@ -294,10 +329,15 @@ public class ProxyServlet implements Servlet
IO.copy(in,socket.getOutputStream());
}
}
/* ------------------------------------------------------------ */
protected HttpURI proxyHttpURI(String scheme, String serverName, int serverPort, String uri)
throws MalformedURLException
{
return new HttpURI(scheme+"://"+serverName+":"+serverPort+uri);
}
/* (non-Javadoc)
* @see javax.servlet.Servlet#getServletInfo()
*/
@ -313,4 +353,5 @@ public class ProxyServlet implements Servlet
{
}
}

View File

@ -29,6 +29,8 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.eclipse.jetty.continuation.Continuation;
import org.eclipse.jetty.continuation.ContinuationSupport;
import org.eclipse.jetty.util.ArrayQueue;
/**
@ -77,7 +79,7 @@ public class QoSFilter implements Filter
long _waitMs;
long _suspendMs;
Semaphore _passes;
Queue<ServletRequest>[] _queue;
Queue<Continuation>[] _queue;
String _suspended="QoSFilter@"+this.hashCode();
public void init(FilterConfig filterConfig)
@ -89,7 +91,7 @@ public class QoSFilter implements Filter
max_priority=Integer.parseInt(filterConfig.getInitParameter(MAX_PRIORITY_INIT_PARAM));
_queue=new Queue[max_priority+1];
for (int p=0;p<_queue.length;p++)
_queue[p]=new ArrayQueue<ServletRequest>();
_queue[p]=new ArrayQueue<Continuation>();
int passes=__DEFAULT_PASSES;
if (filterConfig.getInitParameter(MAX_REQUESTS_INIT_PARAM)!=null)
@ -123,12 +125,13 @@ public class QoSFilter implements Filter
else
{
request.setAttribute(_suspended,Boolean.TRUE);
Continuation continuation = ContinuationSupport.getContinuation(request);
if (_suspendMs>0)
request.setAsyncTimeout(_suspendMs);
request.startAsync();
continuation.setTimeout(_suspendMs);
continuation.suspend();
int priority = getPriority(request);
_queue[priority].add(request);
_queue[priority].add(continuation);
return;
}
}
@ -182,10 +185,10 @@ public class QoSFilter implements Filter
{
for (int p=_queue.length;p-->0;)
{
ServletRequest r=_queue[p].poll();
if (r!=null)
Continuation continutaion=_queue[p].poll();
if (continutaion!=null)
{
r.getAsyncContext().dispatch();
continutaion.resume();
break;
}
}

View File

@ -118,10 +118,10 @@
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jsp-api-2.1-glassfish</artifactId>
<version>9.1.02.B04.p0</version>
<scope>provided</scope>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>

View File

@ -19,14 +19,14 @@ import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import javax.servlet.AsyncContext;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.continuation.Continuation;
import org.eclipse.jetty.continuation.ContinuationSupport;
// Simple asynchronous Chat room.
@ -34,22 +34,12 @@ import javax.servlet.http.HttpServletResponse;
// Some code is duplicated for clarity.
public class ChatServlet extends HttpServlet
{
AsyncListener _asyncListener = new AsyncListener()
{
public void onComplete(AsyncEvent event) throws IOException
{}
public void onTimeout(AsyncEvent event) throws IOException
{
event.getRequest().getAsyncContext().dispatch();
}
};
// inner class to hold message queue for each chat room member
class Member
{
String _name;
AsyncContext _asyncContext;
Continuation _continuation;
Queue<String> _queue = new LinkedList<String>();
}
@ -105,43 +95,50 @@ public class ChatServlet extends HttpServlet
return;
}
if (member._queue.size()>0)
synchronized(member)
{
// Send one chat message
response.setContentType("text/json;charset=utf-8");
StringBuilder buf=new StringBuilder();
buf.append("{\"action\":\"poll\",");
buf.append("\"from\":\"");
buf.append(member._queue.poll());
buf.append("\",");
String message = member._queue.poll();
int quote=message.indexOf('"');
while (quote>=0)
if (member._queue.size()>0)
{
message=message.substring(0,quote)+'\\'+message.substring(quote);
quote=message.indexOf('"',quote+2);
// Send one chat message
response.setContentType("text/json;charset=utf-8");
StringBuilder buf=new StringBuilder();
buf.append("{\"action\":\"poll\",");
buf.append("\"from\":\"");
buf.append(member._queue.poll());
buf.append("\",");
String message = member._queue.poll();
int quote=message.indexOf('"');
while (quote>=0)
{
message=message.substring(0,quote)+'\\'+message.substring(quote);
quote=message.indexOf('"',quote+2);
}
buf.append("\"chat\":\"");
buf.append(message);
buf.append("\"}");
byte[] bytes = buf.toString().getBytes("utf-8");
response.setContentLength(bytes.length);
response.getOutputStream().write(bytes);
}
else
{
Continuation continuation = ContinuationSupport.getContinuation(request);
if (continuation.isInitial())
{
// No chat in queue, so suspend and wait for timeout or chat
continuation.suspend();
member._continuation=continuation;
}
else
{
// Timeout so send empty response
response.setContentType("text/json;charset=utf-8");
PrintWriter out=response.getWriter();
out.print("{action:\"poll\"}");
}
}
buf.append("\"chat\":\"");
buf.append(message);
buf.append("\"}");
byte[] bytes = buf.toString().getBytes("utf-8");
response.setContentLength(bytes.length);
response.getOutputStream().write(bytes);
}
else if (request.isAsyncStarted())
{
// Timeout so send empty response
response.setContentType("text/json;charset=utf-8");
PrintWriter out=response.getWriter();
out.print("{action:\"poll\"}");
}
else
{
// No chat in queue, so suspend and wait for timeout or chat
request.addAsyncListener(_asyncListener);
member._asyncContext=request.startAsync();
}
}
@ -152,14 +149,17 @@ public class ChatServlet extends HttpServlet
// Post chat to all members
for (Member m:room.values())
{
m._queue.add(username); // from
m._queue.add(message); // chat
// wakeup member if polling
if (m._asyncContext!=null)
synchronized (m)
{
m._asyncContext.dispatch();
m._asyncContext=null;
m._queue.add(username); // from
m._queue.add(message); // chat
// wakeup member if polling
if (m._continuation!=null)
{
m._continuation.resume();
m._continuation=null;
}
}
}

View File

@ -1,85 +0,0 @@
// ========================================================================
// Copyright (c) 2004-2009 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 com.acme;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.util.ajax.Continuation;
import org.eclipse.jetty.util.ajax.ContinuationSupport;
/** CometServlet
* This servlet implements the Comet API from tc6.x with the exception of the read method.
*
*
*
*/
public class CometServlet extends HttpServlet
{
public void begin(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
request.setAttribute("org.apache.tomcat.comet",Boolean.TRUE);
}
public void end(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
synchronized(request)
{
request.removeAttribute("org.apache.tomcat.comet");
Continuation continuation=ContinuationSupport.getContinuation(request,request);
if (continuation.isPending())
continuation.resume();
}
}
public void error(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
end(request,response);
}
public boolean read(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
throw new UnsupportedOperationException();
}
protected void service(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
synchronized(request)
{
// TODO: wrap response so we can reset timeout on writes.
Continuation continuation=ContinuationSupport.getContinuation(request,request);
if (!continuation.isPending())
begin(request,response);
Integer timeout=(Integer)request.getAttribute("org.apache.tomcat.comet.timeout");
boolean resumed=continuation.suspend(timeout==null?60000:timeout.intValue());
if (!resumed)
error(request,response);
}
}
public void setTimeout(HttpServletRequest request, HttpServletResponse response, int timeout) throws IOException, ServletException,
UnsupportedOperationException
{
request.setAttribute("org.apache.tomcat.comet.timeout",new Integer(timeout));
}
}

View File

@ -1,48 +0,0 @@
// ========================================================================
// Copyright (c) 2004-2009 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 com.acme;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.StringTokenizer;
import javax.servlet.jsp.JspContext;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.SimpleTagSupport;
public class Date2Tag extends SimpleTagSupport
{
String format;
public void setFormat(String value) {
this.format = value;
}
public void doTag() throws JspException, IOException {
String formatted =
new SimpleDateFormat("long".equals(format)?"EEE 'the' d:MMM:yyyy":"d:MM:yy")
.format(new Date());
StringTokenizer tok = new StringTokenizer(formatted,":");
JspContext context = getJspContext();
context.setAttribute("day", tok.nextToken() );
context.setAttribute("month", tok.nextToken() );
context.setAttribute("year", tok.nextToken() );
JspFragment fragment = getJspBody();
fragment.invoke(null);
}
}

View File

@ -1,65 +0,0 @@
// ========================================================================
// Copyright (c) 2004-2009 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 com.acme;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspTagException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.BodyContent;
import javax.servlet.jsp.tagext.BodyTagSupport;
import javax.servlet.jsp.tagext.Tag;
public class DateTag extends BodyTagSupport
{
Tag parent;
BodyContent body;
String tz="GMT";
public void setParent(Tag parent) {this.parent=parent;}
public Tag getParent() {return parent;}
public void setBodyContent(BodyContent content) {body=content;}
public void setPageContext(PageContext pageContext) {}
public void setTz(String value) {tz=value;}
public int doStartTag() throws JspException {return EVAL_BODY_TAG;}
public int doEndTag() throws JspException {return EVAL_PAGE;}
public void doInitBody() throws JspException {}
public int doAfterBody() throws JspException {
try
{
SimpleDateFormat format = new SimpleDateFormat(body.getString());
format.setTimeZone(TimeZone.getTimeZone(tz));
body.getEnclosingWriter().write(format.format(new Date()));
return SKIP_BODY;
}
catch (Exception ex) {
ex.printStackTrace();
throw new JspTagException(ex.toString());
}
}
public void release()
{
body=null;
}
}

View File

@ -23,8 +23,6 @@ import java.lang.reflect.Field;
import java.util.Enumeration;
import java.util.Locale;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
@ -39,10 +37,10 @@ import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import org.eclipse.jetty.continuation.Continuation;
import org.eclipse.jetty.continuation.ContinuationSupport;
import org.eclipse.jetty.http.HttpHeaders;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.ajax.Continuation;
import org.eclipse.jetty.util.ajax.ContinuationSupport;
@ -73,7 +71,7 @@ public class Dump extends HttpServlet
}
/* ------------------------------------------------------------ */
public void doGet(final HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
public void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException
{
if(request.getPathInfo()!=null && request.getPathInfo().toLowerCase().indexOf("script")!=-1)
{
@ -131,19 +129,20 @@ public class Dump extends HttpServlet
{
e.printStackTrace();
}
Continuation continuation = ContinuationSupport.getContinuation(request, null);
Continuation continuation = ContinuationSupport.getContinuation(request);
continuation.resume();
}
}).start();
}
if (request.getParameter("continue")!=null)
if (request.getParameter("suspend")!=null)
{
try
{
Continuation continuation = ContinuationSupport.getContinuation(request, null);
continuation.suspend(Long.parseLong(request.getParameter("continue")));
Continuation continuation = ContinuationSupport.getContinuation(request);
continuation.setTimeout(Long.parseLong(request.getParameter("suspend")));
continuation.suspend();
}
catch(Exception e)
{
@ -151,84 +150,37 @@ public class Dump extends HttpServlet
}
}
if (request.getAttribute("ASYNC")==null)
if (request.getParameter("complete")!=null)
{
request.setAttribute("ASYNC",Boolean.TRUE);
if (request.getParameter("dispatch")!=null)
final long complete=Long.parseLong(request.getParameter("complete"));
new Thread(new Runnable()
{
final long resume=Long.parseLong(request.getParameter("dispatch"));
final String path=request.getParameter("dispatchPath");
new Thread(new Runnable()
public void run()
{
public void run()
try
{
try
{
Thread.sleep(resume);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
if (path!=null)
request.getAsyncContext().dispatch(path);
else
request.getAsyncContext().dispatch();
Thread.sleep(complete);
}
}).start();
}
if (request.getParameter("complete")!=null)
{
final long complete=Long.parseLong(request.getParameter("complete"));
new Thread(new Runnable()
{
public void run()
catch (InterruptedException e)
{
try
{
Thread.sleep(complete);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
try
{
HttpServletResponse response = (HttpServletResponse) request.getAsyncContext().getResponse();
response.setContentType("text/html");
response.getOutputStream().println("<h1>COMPLETED</h1>");
request.getAsyncContext().complete();
}
catch (IOException e)
{
e.printStackTrace();
}
e.printStackTrace();
}
}).start();
}
if (request.getParameter("async")!=null)
{
final long async=Long.parseLong(request.getParameter("async"));
request.addAsyncListener(new AsyncListener(){
public void onComplete(AsyncEvent event) throws IOException
try
{
response.setContentType("text/html");
response.getOutputStream().println("<h1>COMPLETED</h1>");
Continuation continuation = ContinuationSupport.getContinuation(request);
continuation.complete();
}
public void onTimeout(AsyncEvent event) throws IOException
catch (IOException e)
{
event.getRequest().getAsyncContext().dispatch();
e.printStackTrace();
}
});
request.setAsyncTimeout(async);
request.startAsync();
return;
}
}
}).start();
}
request.setAttribute("Dump", this);
getServletContext().setAttribute("Dump",this);
@ -442,10 +394,6 @@ public class Dump extends HttpServlet
pout.write("<h1>Dump Servlet</h1>\n");
pout.write("<table width=\"95%\">");
pout.write("<tr>\n");
pout.write("<th align=\"right\">getDispatcherTYpe:&nbsp;</th>");
pout.write("<td>" + request.getDispatcherType()+"</td>");
pout.write("</tr><tr>\n");
pout.write("<tr>\n");
pout.write("<th align=\"right\">getMethod:&nbsp;</th>");
pout.write("<td>" + notag(request.getMethod())+"</td>");
pout.write("</tr><tr>\n");
@ -476,13 +424,6 @@ public class Dump extends HttpServlet
pout.write("<th align=\"right\">getQueryString:&nbsp;</th>");
pout.write("<td>"+notag(request.getQueryString())+"</td>");
pout.write("</tr><tr>\n");
pout.write("<th align=\"right\">isAsyncSupported:&nbsp;</th>");
pout.write("<td>"+request.isAsyncSupported()+"</td>");
pout.write("</tr><tr>\n");
pout.write("<th align=\"right\">isAsyncStarted:&nbsp;</th>");
pout.write("<td>"+request.isAsyncStarted()+"</td>");
pout.write("</tr><tr>\n");
pout.write("<th align=\"right\">getProtocol:&nbsp;</th>");
pout.write("<td>"+request.getProtocol()+"</td>");
@ -772,22 +713,12 @@ public class Dump extends HttpServlet
pout.write("resource: <input type=\"text\" name=\"resource\" /><br/>\n");
pout.write("<input type=\"submit\" name=\"Action\" value=\"getResource\">");
pout.write("</form>\n");
}
catch (Exception e)
{
getServletContext().log("dump", e);
}
if (request.getParameter("stream")!=null)
{
pout.flush();
Continuation continuation = ContinuationSupport.getContinuation(request, null);
continuation.suspend(Long.parseLong(request.getParameter("stream")));
}
String lines= request.getParameter("lines");
if (lines!=null)
{

View File

@ -1,135 +0,0 @@
// ========================================================================
// Copyright (c) 2004-2009 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 com.acme;
import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class TagListener implements HttpSessionListener, HttpSessionAttributeListener, HttpSessionActivationListener, ServletContextListener, ServletContextAttributeListener, ServletRequestListener, ServletRequestAttributeListener
{
public void attributeAdded(HttpSessionBindingEvent se)
{
//System.err.println("tagListener: attributedAdded "+se);
}
public void attributeRemoved(HttpSessionBindingEvent se)
{
//System.err.println("tagListener: attributeRemoved "+se);
}
public void attributeReplaced(HttpSessionBindingEvent se)
{
//System.err.println("tagListener: attributeReplaced "+se);
}
public void sessionWillPassivate(HttpSessionEvent se)
{
//System.err.println("tagListener: sessionWillPassivate "+se);
}
public void sessionDidActivate(HttpSessionEvent se)
{
//System.err.println("tagListener: sessionDidActivate "+se);
}
public void contextInitialized(ServletContextEvent sce)
{
//System.err.println("tagListener: contextInitialized "+sce);
}
public void contextDestroyed(ServletContextEvent sce)
{
//System.err.println("tagListener: contextDestroyed "+sce);
}
public void attributeAdded(ServletContextAttributeEvent scab)
{
//System.err.println("tagListener: attributeAdded "+scab);
}
public void attributeRemoved(ServletContextAttributeEvent scab)
{
//System.err.println("tagListener: attributeRemoved "+scab);
}
public void attributeReplaced(ServletContextAttributeEvent scab)
{
//System.err.println("tagListener: attributeReplaced "+scab);
}
public void requestDestroyed(ServletRequestEvent sre)
{
//System.err.println("tagListener: requestDestroyed "+sre);
}
public void requestInitialized(ServletRequestEvent sre)
{
//System.err.println("tagListener: requestInitialized "+sre);
}
public void attributeAdded(ServletRequestAttributeEvent srae)
{
//System.err.println("tagListener: attributeAdded "+srae);
}
public void attributeRemoved(ServletRequestAttributeEvent srae)
{
//System.err.println("tagListener: attributeRemoved "+srae);
}
public void attributeReplaced(ServletRequestAttributeEvent srae)
{
//System.err.println("tagListener: attributeReplaced "+srae);
}
public void sessionCreated(HttpSessionEvent se)
{
//System.err.println("tagListener: sessionCreated "+se);
}
public void sessionDestroyed(HttpSessionEvent se)
{
//System.err.println("tagListener: sessionDestroyed "+se);
}
public void requestCompleted(ServletRequestEvent rre)
{
// TODO Auto-generated method stub
}
public void requestResumed(ServletRequestEvent rre)
{
// TODO Auto-generated method stub
}
public void requestSuspended(ServletRequestEvent rre)
{
// TODO Auto-generated method stub
}
}

View File

@ -13,10 +13,6 @@
package com.acme;
import java.util.EnumSet;
import javax.servlet.DispatcherType;
import javax.servlet.FilterRegistration;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;
@ -64,13 +60,16 @@ public class TestListener implements HttpSessionListener, HttpSessionAttributeL
{
ServletContext context=sce.getServletContext();
FilterRegistration registration=context.addFilter("TestFilter",TestFilter.class.getName());
/* TODO for servlet 3.0
* FilterRegistration registration=context.addFilter("TestFilter",TestFilter.class.getName());
registration.setAsyncSupported(true);
registration.addMappingForUrlPatterns(
EnumSet.of(DispatcherType.ERROR,DispatcherType.ASYNC,DispatcherType.FORWARD,DispatcherType.INCLUDE,DispatcherType.REQUEST),
true,
new String[]{"/dump/*","/dispatch/*","*.dump"});
*/
}
public void contextDestroyed(ServletContextEvent sce)

View File

@ -150,17 +150,6 @@
<url-pattern>/dispatch/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>JspSnoop</servlet-name>
<jsp-file>/snoop.jsp</jsp-file>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>JspSnoop</servlet-name>
<url-pattern>/jspsnoop/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>CGI</servlet-name>
<servlet-class>org.eclipse.jetty.servlets.CGI</servlet-class>
@ -186,12 +175,7 @@
<error-page>
<error-code>404</error-code>
<location>/jspsnoop/ERROR/404</location>
</error-page>
<error-page>
<exception-type>java.io.IOException</exception-type>
<location>/jspsnoop/IOException</location>
<location>/error404.html</location>
</error-page>
<security-constraint>
@ -266,26 +250,6 @@
<form-error-page>/logonError.html?param=test</form-error-page>
</form-login-config>
</login-config>
<jsp-config>
<taglib>
<taglib-uri>
http://www.acme.com/taglib
</taglib-uri>
<taglib-location>
/WEB-INF/acme-taglib.tld
</taglib-location>
</taglib>
<taglib>
<taglib-uri>
http://www.acme.com/taglib2
</taglib-uri>
<taglib-location>
/WEB-INF/acme-taglib2.tld
</taglib-location>
</taglib>
</jsp-config>
<session-config>
<session-timeout>5</session-timeout>

View File

@ -0,0 +1,4 @@
<HTML>
<H1>Not Found ERROR</H1>
custom 404 page
</HTML>

View File

@ -28,8 +28,6 @@ This is a test context that serves:
<li>a <a href="dump/info">Request Dump Servlet</a></li>
<li>a <a href="session/">Session Dump Servlet</a></li>
<li>a <a href="cookie/">Cookie Dump Servlet</a></li>
<li>a <a href="snoop.jsp">Request Dump JSP</a></li>
<li>a <a href="jsp/">Other JSP Tests</a></li>
<li>a <a href="dispatch">Dispatcher Servlet</a></li>
<li>a <a href="cgi-bin/hello.sh">CGI script</a>(unix only)</li>
</ul>

View File

@ -1,15 +0,0 @@
<html>
<%@ page session="true"%>
<body>
<jsp:useBean id='counter' scope='session' class='com.acme.Counter' type="com.acme.Counter" />
<h1>JSP1.2 Beans: 1</h1>
Counter accessed <jsp:getProperty name="counter" property="count"/> times.<br/>
Counter last accessed by <jsp:getProperty name="counter" property="last"/><br/>
<jsp:setProperty name="counter" property="last" value="<%= request.getRequestURI()%>"/>
<a href="bean2.jsp">Goto bean2.jsp</a>
</body>
</html>

View File

@ -1,15 +0,0 @@
<html>
<%@ page session="true"%>
<body>
<jsp:useBean id='counter' scope='session' class='com.acme.Counter' type="com.acme.Counter" />
<h1>JSP1.2 Beans: 2</h1>
Counter accessed <jsp:getProperty name="counter" property="count"/> times.<br/>
Counter last accessed by <jsp:getProperty name="counter" property="last"/><br/>
<jsp:setProperty name="counter" property="last" value="<%= request.getRequestURI()%>"/>
<a href="bean1.jsp">Goto bean1.jsp</a>
</body>
</html>

View File

@ -1,23 +0,0 @@
<html><head>
<%@ page import="java.util.Enumeration" %>
</head><body>
<h1>JSP Dump</h1>
<table border="1">
<tr><th>Request URI:</th><td><%= request.getRequestURI() %></td></tr>
<tr><th>ServletPath:</th><td><%= request.getServletPath() %></td></tr>
<tr><th>PathInfo:</th><td><%= request.getPathInfo() %></td></tr>
<%
Enumeration e =request.getParameterNames();
while(e.hasMoreElements())
{
String name = (String)e.nextElement();
%>
<tr>
<th>getParameter("<%= name %>")</th>
<td><%= request.getParameter(name) %></td></tr>
<% } %>
</table>
</body></html>

View File

@ -1,23 +0,0 @@
<html>
<h1>JSP2.0 Expressions</h1>
<table border="1">
<tr><th>Expression</th><th>Result</th></tr>
<tr>
<td>\${param["A"]}</td>
<td>${param["A"]}&nbsp;</td>
</tr><tr>
<td>\${header["host"]}</td>
<td>${header["host"]}</td>
</tr><tr>
<td>\${header["user-agent"]}</td>
<td>${header["user-agent"]}</td>
</tr><tr>
<td>\${1+1}</td>
<td>${1+1}</td>
</tr><tr>
<td>\${param["A"] * 2}</td>
<td>${param["A"] * 2}&nbsp;</td>
</tr>
</table>
</html>

View File

@ -1,15 +0,0 @@
<html>
<body>
<h1>Day2</h1>
<a href="dump.jsp">JSP 1.2 embedded java</a><br/>
<a href="bean1.jsp">JSP 1.2 Bean demo</a><br/>
<a href="tag.jsp">JSP 1.2 BodyTag demo</a><br/>
<a href="tag2.jsp">JSP 2.0 SimpleTag demo</a><br/>
<a href="tagfile.jsp">JSP 2.0 Tag File demo</a><br/>
<a href="expr.jsp?A=1">JSP 2.0 Tag Expression</a><br/>
</body>
</html>

View File

@ -1,16 +0,0 @@
<html>
<body>
<%@ taglib uri="http://www.acme.com/taglib" prefix="acme" %>
<small>&lt;acme:date tz="GMT"&gt;EEE, dd/MMM/yyyy HH:mm:ss ZZZ&lt;/acme:date&gt;
==&gt;</small>
<acme:date tz="GMT">EEE, dd/MMM/yyyy HH:mm:ss ZZZ</acme:date>
<br/>
<small>&lt;acme:date tz="EST"&gt;EEE, dd-MMM-yyyy HH:mm:ss ZZZ&lt;/acme:date&gt;
==&gt;</small>
<acme:date tz="EST">EEE, dd-MMM-yyyy HH:mm:ss ZZZ</acme:date>
<br/>
</body>
</html>

View File

@ -1,19 +0,0 @@
<html>
<body>
<%@ taglib uri="http://www.acme.com/taglib2" prefix="acme" %>
<acme:date2 format="long">
On ${day} of ${month} in the year ${year}
</acme:date2>
<br/>
<acme:date2 format="short">
${day} - ${month} - ${year}
</acme:date2>
<br/>
</body>
</html>

View File

@ -1,37 +0,0 @@
<%@ taglib prefix="acme" tagdir="/WEB-INF/tags" %>
<html>
<head>
</head>
<body>
<h1>JSP 2.0 Tag File Example</h1>
<hr>
<p>Panel tag created from JSP fragment file in WEB-INF/tags
<hr>
<table border="0">
<tr valign="top">
<td>
<acme:panel color="#ff8080" bgcolor="#ffc0c0" title="Panel 1">
First panel.<br/>
</acme:panel>
</td>
<td>
<acme:panel color="#80ff80" bgcolor="#c0ffc0" title="Panel 2">
Second panel.<br/>
Second panel.<br/>
Second panel.<br/>
Second panel.<br/>
</acme:panel>
</td>
<td>
<acme:panel color="#8080ff" bgcolor="#c0c0ff" title="Panel 3">
Third panel.<br/>
<acme:panel color="#ff80ff" bgcolor="#ffc0ff" title="Inner">
A panel in a panel.
</acme:panel>
Third panel.<br/>
</acme:panel>
</td>
</tr>
</table>
</body>
</html>

View File

@ -1,201 +0,0 @@
<HTML>
<HEAD>
<TITLE>JSP snoop page</TITLE>
<%@ page import="javax.servlet.http.HttpUtils,java.util.Enumeration" %>
</HEAD>
<BODY>
<H1>WebApp JSP Snoop page</H1>
<H2>Request information</H2>
<TABLE>
<TR>
<TH align=right>Requested URL:</TH>
<TD><%= HttpUtils.getRequestURL(request) %></TD>
</TR>
<TR>
<TH align=right>Request method:</TH>
<TD><%= request.getMethod() %></TD>
</TR>
<TR>
<TH align=right>Request URI:</TH>
<TD><%= request.getRequestURI() %></TD>
</TR>
<TR>
<TH align=right>Request protocol:</TH>
<TD><%= request.getProtocol() %></TD>
</TR>
<TR>
<TH align=right>Servlet path:</TH>
<TD><%= request.getServletPath() %></TD>
</TR>
<TR>
<TH align=right>Path info:</TH>
<TD><%= request.getPathInfo() %></TD>
</TR>
<TR>
<TH align=right>Path translated:</TH>
<TD><%= request.getPathTranslated() %></TD>
</TR>
<TR>
<TH align=right>Query string:</TH>
<TD><% if(request.getQueryString()!=null) out.write(request.getQueryString().replaceAll("<", "&lt;").replaceAll(">","&gt;")); %></TD>
</TR>
<TR>
<TH align=right>Content length:</TH>
<TD><%= request.getContentLength() %></TD>
</TR>
<TR>
<TH align=right>Content type:</TH>
<TD><%= request.getContentType() %></TD>
<TR>
<TR>
<TH align=right>Server name:</TH>
<TD><%= request.getServerName() %></TD>
<TR>
<TR>
<TH align=right>Server port:</TH>
<TD><%= request.getServerPort() %></TD>
<TR>
<TR>
<TH align=right>Remote user:</TH>
<TD><%= request.getRemoteUser() %></TD>
<TR>
<TR>
<TH align=right>Remote address:</TH>
<TD><%= request.getRemoteAddr() %></TD>
<TR>
<TR>
<TH align=right>Remote host:</TH>
<TD><%= request.getRemoteHost() %></TD>
<TR>
<TR>
<TH align=right>Authorization scheme:</TH>
<TD><%= request.getAuthType() %></TD>
<TR>
</TABLE>
<%
Enumeration e = request.getHeaderNames();
if(e != null && e.hasMoreElements()) {
%>
<H2>Request headers</H2>
<TABLE>
<TR>
<TH align=left>Header:</TH>
<TH align=left>Value:</TH>
</TR>
<%
while(e.hasMoreElements()) {
String k = (String) e.nextElement();
%>
<TR>
<TD><%= k %></TD>
<TD><%= request.getHeader(k) %></TD>
</TR>
<%
}
%>
</TABLE>
<%
}
%>
<%
e = request.getParameterNames();
if(e != null && e.hasMoreElements()) {
%>
<H2>Request parameters</H2>
<TABLE>
<TR valign=top>
<TH align=left>Parameter:</TH>
<TH align=left>Value:</TH>
<TH align=left>Multiple values:</TH>
</TR>
<%
while(e.hasMoreElements()) {
String k = (String) e.nextElement();
String val = request.getParameter(k);
String vals[] = request.getParameterValues(k);
%>
<TR valign=top>
<TD><%= k.replaceAll("<", "&lt;").replaceAll(">","&gt;") %></TD>
<TD><%= val.replaceAll("<", "&lt;").replaceAll(">","&gt;") %></TD>
<TD><%
for(int i = 0; i < vals.length; i++) {
if(i > 0)
out.print("<BR>");
out.print(vals[i].replaceAll("<", "&lt;").replaceAll(">","&gt;"));
}
%></TD>
</TR>
<%
}
%>
</TABLE>
<%
}
%>
<%
e = request.getAttributeNames();
if(e != null && e.hasMoreElements()) {
%>
<H2>Request Attributes</H2>
<TABLE>
<TR valign=top>
<TH align=left>Attribute:</TH>
<TH align=left>Value:</TH>
</TR>
<%
while(e.hasMoreElements()) {
String k = (String) e.nextElement();
Object val = request.getAttribute(k);
%>
<TR valign=top>
<TD><%= k.replaceAll("<", "&lt;").replaceAll(">","&gt;") %></TD>
<TD><%= val.toString().replaceAll("<", "&lt;").replaceAll(">","&gt;") %></TD>
</TR>
<%
}
%>
</TABLE>
<%
}
%>
<%
e = getServletConfig().getInitParameterNames();
if(e != null && e.hasMoreElements()) {
%>
<H2>Init parameters</H2>
<TABLE>
<TR valign=top>
<TH align=left>Parameter:</TH>
<TH align=left>Value:</TH>
</TR>
<%
while(e.hasMoreElements()) {
String k = (String) e.nextElement();
String val = getServletConfig().getInitParameter(k);
%>
<TR valign=top>
<TD><%= k %></TD>
<TD><%= val %></TD>
</TR>
<%
}
%>
</TABLE>
<%
}
%>
</BODY>
</HTML>

View File

@ -1,117 +0,0 @@
// ========================================================================
// Copyright (c) 2004-2009 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.util.ajax;
import javax.servlet.ServletRequest;
/* ------------------------------------------------------------ */
/** Continuation.
*
* A continuation is a mechanism by which a HTTP Request can be
* suspended and restarted after a timeout or an asynchronous event
* has occured.
* Blocking continuations will block the process of the request during a
* call to {@link #suspend(long)}.
* Non-blocking continuation can abort the current request and arrange for it
* to be retried when {@link #resume()} is called or the timeout expires.
*
* In order to supprt non-blocking continuations, it is important that
* all actions taken by a filter or servlet before a call to
* {@link #suspend(long)} are either idempotent (can be retried) or
* are made conditional on {@link #isPending} so they are not performed on
* retried requests.
*
* With the appropriate HTTP Connector, this allows threadless waiting
* for events (see {@link org.eclipse.jetty.nio.SelectChannelConnector}).
*
*
* @deprecated use {@link ServletRequest#suspend()}
*
*/
public interface Continuation
{
/* ------------------------------------------------------------ */
/** Suspend handling.
* This method will suspend the request for the timeout or until resume is
* called.
* @param timeout. A timeout of < 0 will cause an immediate return. I timeout of 0 will wait indefinitely.
* @return True if resume called or false if timeout.
*/
public boolean suspend(long timeout);
/* ------------------------------------------------------------ */
/** Resume the request.
* Resume a suspended request. The passed event will be returned in the getObject method.
*/
public void resume();
/* ------------------------------------------------------------ */
/** Reset the continuation.
* Cancel any pending status of the continuation.
*/
public void reset();
/* ------------------------------------------------------------ */
/** Is this a newly created Continuation.
* <p>
* A newly created continuation has not had {@link #getEvent(long)} called on it.
* </p>
* @return True if the continuation has just been created and has not yet suspended the request.
*/
public boolean isNew();
/* ------------------------------------------------------------ */
/** Get the pending status?
* A continuation is pending while the handling of a call to suspend has not completed.
* For blocking continuations, pending is true only during the call to {@link #suspend(long)}.
* For non-blocking continuations, pending is true until a second call to {@link #suspend(long)} or
* a call to {@link #reset()}, thus this method can be used to determine if a request is being
* retried.
* @return True if the continuation is handling a call to suspend.
*/
public boolean isPending();
/* ------------------------------------------------------------ */
/** Get the resumed status?
* @return True if the continuation is has been resumed.
*/
public boolean isResumed();
/* ------------------------------------------------------------ */
/** Get the resumed status?
* @return True if the continuation is has been expired.
*/
public boolean isExpired();
/* ------------------------------------------------------------ */
/** Arbitrary object associated with the continuation for context.
* @return An arbitrary object associated with the continuation
*/
public Object getObject();
/* ------------------------------------------------------------ */
/** Arbitrary object associated with the continuation for context.
* @param o An arbitrary object to associate with the continuation
*/
public void setObject(Object o);
/* ------------------------------------------------------------ */
/**
*/
public void setMutex(Object mutex);
}

View File

@ -1,153 +0,0 @@
// ========================================================================
// Copyright (c) 2004-2009 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.util.ajax;
import org.eclipse.jetty.util.log.Log;
public class WaitingContinuation implements org.eclipse.jetty.util.ajax.Continuation
{
Object _mutex;
Object _object;
boolean _new=true;
boolean _resumed=false;
boolean _pending=false;
boolean _expired=false;
public WaitingContinuation()
{
_mutex=this;
}
public WaitingContinuation(Object mutex)
{
_mutex=mutex==null?this:mutex;
}
public void resume()
{
synchronized (_mutex)
{
_resumed=true;
_mutex.notify();
}
}
public void reset()
{
synchronized (_mutex)
{
_resumed=false;
_pending=false;
_expired=false;
_mutex.notify();
}
}
public boolean isNew()
{
return _new;
}
public boolean suspend(long timeout)
{
synchronized (_mutex)
{
_new=false;
_pending=true;
boolean result;
try
{
if (!_resumed && timeout>=0)
{
if (timeout==0)
_mutex.wait();
else if (timeout>0)
_mutex.wait(timeout);
}
}
catch (InterruptedException e)
{
_expired=true;
Log.ignore(e);
}
finally
{
result=_resumed;
_resumed=false;
_pending=false;
}
return result;
}
}
public boolean isPending()
{
synchronized (_mutex)
{
return _pending;
}
}
public boolean isResumed()
{
synchronized (_mutex)
{
return _resumed;
}
}
public boolean isExpired()
{
synchronized (_mutex)
{
return _expired;
}
}
public Object getObject()
{
return _object;
}
public void setObject(Object object)
{
_object = object;
}
public Object getMutex()
{
return _mutex;
}
public void setMutex(Object mutex)
{
if (_pending && mutex!=_mutex)
throw new IllegalStateException();
_mutex = mutex==null ? this : mutex;
}
public String toString()
{
synchronized (this)
{
return "WaitingContinuation@"+hashCode()+
(_new?",new":"")+
(_pending?",pending":"")+
(_resumed?",resumed":"")+
(_expired?",expired":"");
}
}
}

View File

@ -271,7 +271,7 @@ public class Timeout
boolean _expired=false;
/* ------------------------------------------------------------ */
public Task()
protected Task()
{
_next=_prev=this;
}
@ -372,7 +372,7 @@ public class Timeout
* the {@link #isExpired()} state to true.
* @see #expired() For an unsynchronized callback.
*/
public void expire(){}
protected void expire(){}
/* ------------------------------------------------------------ */
/** Expire task.
@ -380,7 +380,7 @@ public class Timeout
* outside of any synchronization scope and may be delayed.
*
*/
public void expired(){}
protected void expired(){}
}

View File

@ -65,6 +65,7 @@ import org.eclipse.jetty.util.resource.Resource;
*/
public class WebAppContext extends ServletContextHandler
{
public static final String TEMPDIR = "javax.servlet.context.tempdir";
public final static String WEB_DEFAULTS_XML="org/eclipse/jetty/webapp/webdefault.xml";
public final static String ERROR_PAGE="org.eclipse.jetty.server.error_page";
@ -94,16 +95,16 @@ public class WebAppContext extends ServletContextHandler
"org.w3c.",
"org.apache.commons.logging.",
"org.apache.log4j.",
"org.eclipse.jetty.servlet.", // webapp cannot change default servlets
"org.eclipse.util.ajax.", // webapp cannot change continuation classes
"org.eclipse.naming." // webapp cannot change naming classes
"org.eclipse.jetty.servlet.", // webapp cannot change default servlets
"org.eclipse.jetty.continuation.", // webapp cannot change continuation classes
"org.eclipse.jetty.naming." // webapp cannot change naming classes
};
private String[] _serverClasses = {
"-org.eclipse.naming.", // don't hide naming classes
"-org.eclipse.util.ajax.", // don't hide continuation classes
"-org.eclipse.jetty.plus.jaas.", //don't hide jaas modules
"org.eclipse.", // hide rest of eclipse classes
"org.slf4j." // hide slf4j
"-org.eclipse.jetty.naming.", // don't hide naming classes
"-org.eclipse.jetty.continuation.", // don't hide continuation classes
"-org.eclipse.jetty.plus.jaas.", // don't hide jaas modules
"org.eclipse.jetty.", // hide rest of jetty classes
"org.slf4j." // hide slf4j
};
private File _tmpDir;
private boolean _isExistingTmpDir;
@ -602,7 +603,7 @@ public class WebAppContext extends ServletContextHandler
//
// I'm afraid that this is very much black magic.
// but if you can think of better....
Object t = getAttribute(ServletContext.TEMPDIR);
Object t = getAttribute(TEMPDIR);
if (t!=null && (t instanceof File))
{
@ -620,7 +621,7 @@ public class WebAppContext extends ServletContextHandler
if (_tmpDir.isDirectory() && _tmpDir.canWrite())
{
if(Log.isDebugEnabled())Log.debug("Converted to File "+_tmpDir+" for "+this);
setAttribute(ServletContext.TEMPDIR,_tmpDir);
setAttribute(TEMPDIR,_tmpDir);
return _tmpDir;
}
}
@ -715,7 +716,7 @@ public class WebAppContext extends ServletContextHandler
}
}
setAttribute(ServletContext.TEMPDIR,_tmpDir);
setAttribute(TEMPDIR,_tmpDir);
return _tmpDir;
}
@ -1134,7 +1135,7 @@ public class WebAppContext extends ServletContextHandler
throw new IllegalArgumentException("Bad temp directory: "+dir);
_tmpDir=dir;
setAttribute(ServletContext.TEMPDIR,_tmpDir);
setAttribute(TEMPDIR,_tmpDir);
}
/* ------------------------------------------------------------ */
@ -1203,8 +1204,8 @@ public class WebAppContext extends ServletContextHandler
&& work.isDirectory()
&& work.getFile() != null
&& work.getFile().canWrite()
&& getAttribute(ServletContext.TEMPDIR) == null)
setAttribute(ServletContext.TEMPDIR, work.getFile());
&& getAttribute(TEMPDIR) == null)
setAttribute(TEMPDIR, work.getFile());
}
// Configure webapp

View File

@ -72,8 +72,15 @@ public class XmlConfiguration
{
URL configURL = Loader.getResource(XmlConfiguration.class, "org/eclipse/jetty/xml/configure_6_0.dtd", true);
__parser.redirectEntity("configure.dtd", configURL);
__parser.redirectEntity("configure_1_0.dtd", configURL);
__parser.redirectEntity("configure_1_1.dtd", configURL);
__parser.redirectEntity("configure_1_2.dtd", configURL);
__parser.redirectEntity("configure_1_3.dtd", configURL);
__parser.redirectEntity("configure_6_0.dtd", configURL);
__parser.redirectEntity("http://jetty.mortbay.org/configure.dtd", configURL);
__parser.redirectEntity("http://jetty.eclipse.org/configure.dtd", configURL);
__parser.redirectEntity("-//Mort Bay Consulting//DTD Configure//EN", configURL);
__parser.redirectEntity("http://jetty.eclipse.org/configure_1_3.dtd", configURL);
__parser.redirectEntity("-//Mort Bay Consulting//DTD Configure 1.3//EN", configURL);

View File

@ -13,8 +13,7 @@
<packaging>pom</packaging>
<properties>
<!--servlet-api-version>2.5-20081211</servlet-api-version-->
<servlet-api-version>3.0-SNAPSHOT</servlet-api-version>
<servlet-api-version>2.5-20081211</servlet-api-version>
<activation-version>1.1</activation-version>
<ant-version>1.6.5</ant-version>
<jta-spec-version>1.1.1</jta-spec-version>
@ -98,12 +97,10 @@
</pluginManagement>
</build>
<modules>
<!-- commented out because of missing servlet specific annotations
<module>jetty-test-annotation-webapp</module>
-->
<module>jetty-util</module>
<module>jetty-io</module>
<module>jetty-http</module>
<module>jetty-continuation</module>
<module>jetty-server</module>
<module>jetty-client</module>
<module>jetty-xml</module>
@ -113,9 +110,9 @@
<module>jetty-servlets</module>
<module>jetty-deploy</module>
<module>jetty-ajp</module>
<module>jetty-annotations</module>
<module>jetty-jmx</module>
<module>jetty-jndi</module>
<module>jetty-annotations</module>
<module>jetty-plus</module>
<module>jetty-rewrite</module>
<module>jetty-servlet-tester</module>