Merge remote-tracking branch 'origin/jetty-8'

Conflicts:
	jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java
	jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletContextHandler.java
	jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java
	jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java
This commit is contained in:
Jan Bartel 2013-06-17 13:13:59 +10:00
commit 232eb4491a
9 changed files with 113 additions and 28 deletions

View File

@ -30,6 +30,7 @@ import java.security.CodeSource;
import java.security.PermissionCollection; import java.security.PermissionCollection;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.EventListener;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
@ -50,9 +51,12 @@ import org.eclipse.jetty.ant.utils.TaskLog;
import org.eclipse.jetty.plus.webapp.EnvConfiguration; import org.eclipse.jetty.plus.webapp.EnvConfiguration;
import org.eclipse.jetty.plus.webapp.PlusConfiguration; import org.eclipse.jetty.plus.webapp.PlusConfiguration;
import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.FilterMapping;
import org.eclipse.jetty.servlet.Holder; import org.eclipse.jetty.servlet.Holder;
import org.eclipse.jetty.servlet.ServletHandler; import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.servlet.ServletMapping;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.Resource; import org.eclipse.jetty.util.resource.Resource;
@ -676,6 +680,13 @@ public class AntWebAppContext extends WebAppContext
TaskLog.logWithTimestamp("Stopping web application "+this); TaskLog.logWithTimestamp("Stopping web application "+this);
Thread.currentThread().sleep(500L); Thread.currentThread().sleep(500L);
super.doStop(); super.doStop();
//remove all filters, servlets and listeners. They will be recreated
//either via application of a context xml file or web.xml or annotation or servlet api
setEventListeners(new EventListener[0]);
getServletHandler().setFilters(new FilterHolder[0]);
getServletHandler().setFilterMappings(new FilterMapping[0]);
getServletHandler().setServlets(new ServletHolder[0]);
getServletHandler().setServletMappings(new ServletMapping[0]);
} }
catch (InterruptedException e) catch (InterruptedException e)
{ {

View File

@ -22,6 +22,7 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.EventListener;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -29,6 +30,10 @@ import java.util.Set;
import java.util.TreeSet; import java.util.TreeSet;
import org.eclipse.jetty.plus.webapp.EnvConfiguration; import org.eclipse.jetty.plus.webapp.EnvConfiguration;
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.URIUtil; import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.Logger;
@ -296,6 +301,14 @@ public class JettyWebAppContext extends WebAppContext
//just wait a little while to ensure no requests are still being processed //just wait a little while to ensure no requests are still being processed
Thread.currentThread().sleep(500L); Thread.currentThread().sleep(500L);
super.doStop(); super.doStop();
//remove all listeners, servlets and filters. This is because we will re-apply
//any context xml file, which means they would potentially be added multiple times.
setEventListeners(new EventListener[0]);
getServletHandler().setFilters(new FilterHolder[0]);
getServletHandler().setFilterMappings(new FilterMapping[0]);
getServletHandler().setServlets(new ServletHolder[0]);
getServletHandler().setServletMappings(new ServletMapping[0]);
} }
@Override @Override

View File

@ -169,6 +169,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
private final List<ServletContextAttributeListener> _contextAttributeListeners=new CopyOnWriteArrayList<>(); private final List<ServletContextAttributeListener> _contextAttributeListeners=new CopyOnWriteArrayList<>();
private final List<ServletRequestListener> _requestListeners=new CopyOnWriteArrayList<>(); private final List<ServletRequestListener> _requestListeners=new CopyOnWriteArrayList<>();
private final List<ServletRequestAttributeListener> _requestAttributeListeners=new CopyOnWriteArrayList<>(); private final List<ServletRequestAttributeListener> _requestAttributeListeners=new CopyOnWriteArrayList<>();
private final List<EventListener> _durableListeners = new CopyOnWriteArrayList<>();
private Map<String, Object> _managedAttributes; private Map<String, Object> _managedAttributes;
private String[] _protectedTargets; private String[] _protectedTargets;
private final CopyOnWriteArrayList<AliasCheck> _aliasChecks = new CopyOnWriteArrayList<ContextHandler.AliasCheck>(); private final CopyOnWriteArrayList<AliasCheck> _aliasChecks = new CopyOnWriteArrayList<ContextHandler.AliasCheck>();
@ -567,6 +568,9 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
{ {
_eventListeners.add(listener); _eventListeners.add(listener);
if (!(isStarted() || isStarting()))
_durableListeners.add(listener);
if (listener instanceof ServletContextListener) if (listener instanceof ServletContextListener)
_contextListeners.add((ServletContextListener)listener); _contextListeners.add((ServletContextListener)listener);
@ -623,6 +627,8 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
return _programmaticListeners.contains(listener); return _programmaticListeners.contains(listener);
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
* @return true if this context is accepting new requests * @return true if this context is accepting new requests
@ -821,6 +827,10 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
for (int i = _contextListeners.size(); i-->0;) for (int i = _contextListeners.size(); i-->0;)
callContextDestroyed(_contextListeners.get(i),event); callContextDestroyed(_contextListeners.get(i),event);
} }
//retain only durable listeners
setEventListeners(_durableListeners.toArray(new EventListener[_durableListeners.size()]));
_durableListeners.clear();
if (_errorHandler != null) if (_errorHandler != null)
_errorHandler.stop(); _errorHandler.stop();
@ -1821,8 +1831,6 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
query = uriInContext.substring(q + 1); query = uriInContext.substring(q + 1);
uriInContext = uriInContext.substring(0,q); uriInContext = uriInContext.substring(0,q);
} }
// if ((q = uriInContext.indexOf(';')) > 0)
// uriInContext = uriInContext.substring(0,q);
String pathInContext = URIUtil.canonicalPath(URIUtil.decodePath(uriInContext)); String pathInContext = URIUtil.canonicalPath(URIUtil.decodePath(uriInContext));
if (pathInContext!=null) if (pathInContext!=null)

View File

@ -1022,8 +1022,6 @@ public class ServletContextHandler extends ContextHandler
if (!_enabled) if (!_enabled)
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
//TODO handle partial registrations
final ServletHandler handler = ServletContextHandler.this.getServletHandler(); final ServletHandler handler = ServletContextHandler.this.getServletHandler();
ServletHolder holder = handler.getServlet(servletName); ServletHolder holder = handler.getServlet(servletName);
if (holder == null) if (holder == null)

View File

@ -21,10 +21,12 @@ package org.eclipse.jetty.servlet;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.ListIterator;
import java.util.Map; import java.util.Map;
import java.util.Queue; import java.util.Queue;
import java.util.Set; import java.util.Set;
@ -187,30 +189,81 @@ public class ServletHandler extends ScopedHandler
super.doStop(); super.doStop();
// Stop filters // Stop filters
List<FilterHolder> filterHolders = new ArrayList<FilterHolder>();
List<FilterMapping> filterMappings = ArrayUtil.asMutableList(_filterMappings);
if (_filters!=null) if (_filters!=null)
{ {
for (int i=_filters.length; i-->0;) for (int i=_filters.length; i-->0;)
{ {
try { _filters[i].stop(); }catch(Exception e){LOG.warn(Log.EXCEPTION,e);} try { _filters[i].stop(); }catch(Exception e){LOG.warn(Log.EXCEPTION,e);}
if (_filters[i].getSource() != Source.EMBEDDED)
{
//remove all of the mappings that were for non-embedded filters
_filterNameMap.remove(_filters[i].getName());
//remove any mappings associated with this filter
ListIterator<FilterMapping> fmitor = filterMappings.listIterator();
while (fmitor.hasNext())
{
FilterMapping fm = fmitor.next();
if (fm.getFilterName().equals(_filters[i].getName()))
fmitor.remove();
}
}
else
filterHolders.add(_filters[i]); //only retain embedded
} }
} }
//Retain only filters and mappings that were added using jetty api (ie Source.EMBEDDED)
FilterHolder[] fhs = (FilterHolder[]) LazyList.toArray(filterHolders, FilterHolder.class);
updateBeans(_filters, fhs);
_filters = fhs;
FilterMapping[] fms = (FilterMapping[]) LazyList.toArray(filterMappings, FilterMapping.class);
updateBeans(_filterMappings, fms);
_filterMappings = fms;
_matchAfterIndex = (_filterMappings == null || _filterMappings.length == 0 ? -1 : _filterMappings.length-1);
_matchBeforeIndex = -1;
// Stop servlets // Stop servlets
List<ServletHolder> servletHolders = new ArrayList<ServletHolder>(); //will be remaining servlets
List<ServletMapping> servletMappings = ArrayUtil.asMutableList(_servletMappings); //will be remaining mappings
if (_servlets!=null) if (_servlets!=null)
{ {
for (int i=_servlets.length; i-->0;) for (int i=_servlets.length; i-->0;)
{ {
try { _servlets[i].stop(); }catch(Exception e){LOG.warn(Log.EXCEPTION,e);} try { _servlets[i].stop(); }catch(Exception e){LOG.warn(Log.EXCEPTION,e);}
if (_servlets[i].getSource() != Source.EMBEDDED)
{
//remove from servlet name map
_servletNameMap.remove(_servlets[i].getName());
//remove any mappings associated with this servlet
ListIterator<ServletMapping> smitor = servletMappings.listIterator();
while (smitor.hasNext())
{
ServletMapping sm = smitor.next();
if (sm.getServletName().equals(_servlets[i].getName()))
smitor.remove();
}
}
else
servletHolders.add(_servlets[i]); //only retain embedded
} }
} }
//Retain only Servlets and mappings added via jetty apis (ie Source.EMBEDDED)
ServletHolder[] shs = (ServletHolder[]) LazyList.toArray(servletHolders, ServletHolder.class);
updateBeans(_servlets, shs);
_servlets = shs;
ServletMapping[] sms = (ServletMapping[])LazyList.toArray(servletMappings, ServletMapping.class);
updateBeans(_servletMappings, sms);
_servletMappings = sms;
//will be regenerated on next start
_filterPathMappings=null; _filterPathMappings=null;
_filterNameMappings=null; _filterNameMappings=null;
_servletPathMap=null; _servletPathMap=null;
_matchBeforeIndex=-1;
_matchAfterIndex=-1;
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@ -786,7 +839,7 @@ public class ServletHandler extends ScopedHandler
*/ */
public ServletHolder addServletWithMapping (String className,String pathSpec) public ServletHolder addServletWithMapping (String className,String pathSpec)
{ {
ServletHolder holder = newServletHolder(null); ServletHolder holder = newServletHolder(Holder.Source.EMBEDDED);
holder.setName(className+"-"+(_servlets==null?0:_servlets.length)); holder.setName(className+"-"+(_servlets==null?0:_servlets.length));
holder.setClassName(className); holder.setClassName(className);
addServletWithMapping(holder,pathSpec); addServletWithMapping(holder,pathSpec);
@ -801,7 +854,6 @@ public class ServletHandler extends ScopedHandler
{ {
ServletHolder holder = newServletHolder(Holder.Source.EMBEDDED); ServletHolder holder = newServletHolder(Holder.Source.EMBEDDED);
holder.setHeldClass(servlet); holder.setHeldClass(servlet);
setServlets(ArrayUtil.addToArray(getServlets(), holder, ServletHolder.class));
addServletWithMapping(holder,pathSpec); addServletWithMapping(holder,pathSpec);
return holder; return holder;
@ -969,7 +1021,7 @@ public class ServletHandler extends ScopedHandler
*/ */
public FilterHolder addFilterWithMapping (String className,String pathSpec,int dispatches) public FilterHolder addFilterWithMapping (String className,String pathSpec,int dispatches)
{ {
FilterHolder holder = newFilterHolder(null); FilterHolder holder = newFilterHolder(Holder.Source.EMBEDDED);
holder.setName(className+"-"+_filters.length); holder.setName(className+"-"+_filters.length);
holder.setClassName(className); holder.setClassName(className);
@ -1116,7 +1168,7 @@ public class ServletHandler extends ScopedHandler
{ {
//programmatically defined filter mappings are prepended to mapping list in the order //programmatically defined filter mappings are prepended to mapping list in the order
//in which they were defined. In other words, insert this mapping at the tail of the //in which they were defined. In other words, insert this mapping at the tail of the
//programmatically added filter mappings, BEFORE the first web.xml defined filter mapping. //programmatically prepended filter mappings, BEFORE the first web.xml defined filter mapping.
if (_matchBeforeIndex < 0) if (_matchBeforeIndex < 0)
{ {
@ -1159,14 +1211,15 @@ public class ServletHandler extends ScopedHandler
{ {
if (pos < 0) if (pos < 0)
throw new IllegalArgumentException("FilterMapping insertion pos < 0"); throw new IllegalArgumentException("FilterMapping insertion pos < 0");
FilterMapping[] mappings = getFilterMappings(); FilterMapping[] mappings = getFilterMappings();
if (mappings==null || mappings.length==0) if (mappings==null || mappings.length==0)
{ {
return new FilterMapping[] {mapping}; return new FilterMapping[] {mapping};
} }
FilterMapping[] new_mappings = new FilterMapping[mappings.length+1]; FilterMapping[] new_mappings = new FilterMapping[mappings.length+1];
if (before) if (before)
{ {
//copy existing filter mappings up to but not including the pos //copy existing filter mappings up to but not including the pos
@ -1375,6 +1428,7 @@ public class ServletHandler extends ScopedHandler
if (holders!=null) if (holders!=null)
for (ServletHolder holder:holders) for (ServletHolder holder:holders)
holder.setServletHandler(this); holder.setServletHandler(this);
updateBeans(_servlets,holders); updateBeans(_servlets,holders);
_servlets=holders; _servlets=holders;
updateNameMappings(); updateNameMappings();

View File

@ -226,7 +226,20 @@ public class DispatcherTest
_contextHandler.addServlet(DispatchServletServlet.class, "/dispatch/*"); _contextHandler.addServlet(DispatchServletServlet.class, "/dispatch/*");
_contextHandler.addServlet(RogerThatServlet.class, "/roger/that"); _contextHandler.addServlet(RogerThatServlet.class, "/roger/that");
String requests="GET /context/dispatch/test?forward=%2e%2e/roger/that HTTP/1.0\n" + "Host: localhost\n\n"; String requests="GET /context/dispatch/test?forward=/%2e%2e/roger/that HTTP/1.0\n" + "Host: localhost\n\n";
String responses = _connector.getResponses(requests);
assertThat(responses,startsWith("HTTP/1.1 404 "));
}
@Test
public void testServletForwardEncodedDotDot() throws Exception
{
_contextHandler.addServlet(DispatchServletServlet.class, "/dispatch/*");
_contextHandler.addServlet(RogerThatServlet.class, "/roger/that");
String requests="GET /context/dispatch/test?forward=/%252e%252e/roger/that HTTP/1.0\n" + "Host: localhost\n\n";
String responses = _connector.getResponses(requests); String responses = _connector.getResponses(requests);

View File

@ -1080,6 +1080,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
* @param extractWAR True if war files are extracted * @param extractWAR True if war files are extracted

View File

@ -120,25 +120,13 @@ public class WebXmlConfiguration extends AbstractConfiguration
/* ------------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------------- */
@Override @Override
public void deconfigure (WebAppContext context) throws Exception public void deconfigure (WebAppContext context) throws Exception
{ {
// TODO preserve any configuration that pre-existed.
ServletHandler _servletHandler = context.getServletHandler();
_servletHandler.setFilters(null);
_servletHandler.setFilterMappings(null);
_servletHandler.setServlets(null);
_servletHandler.setServletMappings(null);
context.setEventListeners(null);
context.setWelcomeFiles(null); context.setWelcomeFiles(null);
if (context.getErrorHandler() instanceof ErrorPageErrorHandler) if (context.getErrorHandler() instanceof ErrorPageErrorHandler)
((ErrorPageErrorHandler) ((ErrorPageErrorHandler)
context.getErrorHandler()).setErrorPages(null); context.getErrorHandler()).setErrorPages(null);
// TODO remove classpaths from classloader // TODO remove classpaths from classloader
} }
} }

View File

@ -113,7 +113,6 @@ public class ReloadedSessionMissingClassTest
webApp.stop(); webApp.stop();
webApp.setClassLoader(loaderWithoutFoo); webApp.setClassLoader(loaderWithoutFoo);
webApp.addServlet("Bar", "/bar");
//restart webapp //restart webapp
webApp.start(); webApp.start();