Merge remote-tracking branch 'origin/jetty-9.4.x' into jetty-10.0.x
This commit is contained in:
commit
a8db28f706
|
@ -19,6 +19,7 @@
|
||||||
package org.eclipse.jetty.servlet;
|
package org.eclipse.jetty.servlet;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
import javax.servlet.ServletContext;
|
import javax.servlet.ServletContext;
|
||||||
import javax.servlet.UnavailableException;
|
import javax.servlet.UnavailableException;
|
||||||
|
|
||||||
|
@ -239,6 +240,47 @@ public abstract class BaseHolder<T> extends AbstractLifeCycle implements Dumpabl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrap component using component specific Wrapper Function beans.
|
||||||
|
*
|
||||||
|
* @param component the component to optionally wrap
|
||||||
|
* @param wrapperFunctionType the bean class type to look for in the {@link ServletContextHandler}
|
||||||
|
* @param function the BiFunction to execute for each {@code wrapperFunctionType} Bean found (passing in the component and component type)
|
||||||
|
* @param <W> the "wrapper function" implementation. (eg: {@code ServletHolder.WrapperFunction} or {@code FilterHolder.WrapperFunction}, etc)
|
||||||
|
* @return the component that has passed through all Wrapper Function beans found.
|
||||||
|
*/
|
||||||
|
protected <W> T wrap(final T component, final Class<W> wrapperFunctionType, final BiFunction<W, T, T> function)
|
||||||
|
{
|
||||||
|
T ret = component;
|
||||||
|
ServletContextHandler contextHandler = getServletHandler().getServletContextHandler();
|
||||||
|
if (contextHandler == null)
|
||||||
|
{
|
||||||
|
ContextHandler.Context context = ContextHandler.getCurrentContext();
|
||||||
|
contextHandler = (ServletContextHandler)(context == null ? null : context.getContextHandler());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (contextHandler != null)
|
||||||
|
{
|
||||||
|
for (W wrapperFunction : contextHandler.getBeans(wrapperFunctionType))
|
||||||
|
{
|
||||||
|
ret = function.apply(wrapperFunction, ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected T unwrap(final T component)
|
||||||
|
{
|
||||||
|
T ret = component;
|
||||||
|
|
||||||
|
while (ret instanceof Wrapped)
|
||||||
|
{
|
||||||
|
// noinspection unchecked,rawtypes
|
||||||
|
ret = (T)((Wrapped)ret).getWrapped();
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dump(Appendable out, String indent) throws IOException
|
public void dump(Appendable out, String indent) throws IOException
|
||||||
{
|
{
|
||||||
|
@ -250,4 +292,9 @@ public abstract class BaseHolder<T> extends AbstractLifeCycle implements Dumpabl
|
||||||
{
|
{
|
||||||
return Dumpable.dump(this);
|
return Dumpable.dump(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface Wrapped<C>
|
||||||
|
{
|
||||||
|
C getWrapped();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,12 +24,16 @@ import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
import javax.servlet.DispatcherType;
|
import javax.servlet.DispatcherType;
|
||||||
import javax.servlet.Filter;
|
import javax.servlet.Filter;
|
||||||
|
import javax.servlet.FilterChain;
|
||||||
import javax.servlet.FilterConfig;
|
import javax.servlet.FilterConfig;
|
||||||
import javax.servlet.FilterRegistration;
|
import javax.servlet.FilterRegistration;
|
||||||
import javax.servlet.ServletContext;
|
import javax.servlet.ServletContext;
|
||||||
import javax.servlet.ServletException;
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.ServletRequest;
|
||||||
|
import javax.servlet.ServletResponse;
|
||||||
|
|
||||||
import org.eclipse.jetty.util.TypeUtil;
|
import org.eclipse.jetty.util.TypeUtil;
|
||||||
import org.eclipse.jetty.util.component.Dumpable;
|
import org.eclipse.jetty.util.component.Dumpable;
|
||||||
|
@ -126,6 +130,7 @@ public class FilterHolder extends Holder<Filter>
|
||||||
throw ex;
|
throw ex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_filter = wrap(_filter, FilterHolder.WrapFunction.class, FilterHolder.WrapFunction::wrapFilter);
|
||||||
_config = new Config();
|
_config = new Config();
|
||||||
if (LOG.isDebugEnabled())
|
if (LOG.isDebugEnabled())
|
||||||
LOG.debug("Filter.init {}", _filter);
|
LOG.debug("Filter.init {}", _filter);
|
||||||
|
@ -170,13 +175,19 @@ public class FilterHolder extends Holder<Filter>
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void destroyInstance(Object o)
|
public void destroyInstance(Object o)
|
||||||
throws Exception
|
|
||||||
{
|
{
|
||||||
if (o == null)
|
if (o == null)
|
||||||
return;
|
return;
|
||||||
Filter f = (Filter)o;
|
|
||||||
f.destroy();
|
Filter filter = (Filter)o;
|
||||||
getServletHandler().destroyFilter(f);
|
|
||||||
|
// need to use the unwrapped filter because lifecycle callbacks such as
|
||||||
|
// postconstruct and predestroy are based off the classname and the wrapper
|
||||||
|
// classes are unknown outside the ServletHolder
|
||||||
|
getServletHandler().destroyFilter(unwrap(filter));
|
||||||
|
|
||||||
|
// destroy the wrapped filter, in case there is special behaviour
|
||||||
|
filter.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFilter(Filter filter)
|
public void setFilter(Filter filter)
|
||||||
|
@ -189,6 +200,13 @@ public class FilterHolder extends Holder<Filter>
|
||||||
return _filter;
|
return _filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void doFilter(ServletRequest request, ServletResponse response,
|
||||||
|
FilterChain chain)
|
||||||
|
throws IOException, ServletException
|
||||||
|
{
|
||||||
|
_filter.doFilter(request, response, chain);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dump(Appendable out, String indent) throws IOException
|
public void dump(Appendable out, String indent) throws IOException
|
||||||
{
|
{
|
||||||
|
@ -278,11 +296,69 @@ public class FilterHolder extends Holder<Filter>
|
||||||
|
|
||||||
class Config extends HolderConfig implements FilterConfig
|
class Config extends HolderConfig implements FilterConfig
|
||||||
{
|
{
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getFilterName()
|
public String getFilterName()
|
||||||
{
|
{
|
||||||
return getName();
|
return getName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Experimental Wrapper mechanism for Filter objects.
|
||||||
|
* <p>
|
||||||
|
* Beans in {@code ServletContextHandler} or {@code WebAppContext} that implement this interface
|
||||||
|
* will be called to optionally wrap any newly created Filters
|
||||||
|
* (before their {@link Filter#init(FilterConfig)} method is called)
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public interface WrapFunction
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Optionally wrap the Filter.
|
||||||
|
*
|
||||||
|
* @param filter the Filter being passed in.
|
||||||
|
* @return the Filter (extend from {@link FilterHolder.Wrapper} if you do wrap the Filter)
|
||||||
|
*/
|
||||||
|
Filter wrapFilter(Filter filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Wrapper implements Filter, Wrapped<Filter>
|
||||||
|
{
|
||||||
|
private final Filter _filter;
|
||||||
|
|
||||||
|
public Wrapper(Filter filter)
|
||||||
|
{
|
||||||
|
_filter = Objects.requireNonNull(filter, "Filter cannot be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Filter getWrapped()
|
||||||
|
{
|
||||||
|
return _filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(FilterConfig filterConfig) throws ServletException
|
||||||
|
{
|
||||||
|
_filter.init(filterConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
|
||||||
|
{
|
||||||
|
_filter.doFilter(request, response, chain);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroy()
|
||||||
|
{
|
||||||
|
_filter.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return String.format("%s:%s", this.getClass().getSimpleName(), _filter.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,6 +101,7 @@ public class ListenerHolder extends BaseHolder<EventListener>
|
||||||
throw ex;
|
throw ex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_listener = wrap(_listener, WrapFunction.class, WrapFunction::wrapEventListener);
|
||||||
contextHandler.addEventListener(_listener);
|
contextHandler.addEventListener(_listener);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -132,7 +133,7 @@ public class ListenerHolder extends BaseHolder<EventListener>
|
||||||
ContextHandler contextHandler = ContextHandler.getCurrentContext().getContextHandler();
|
ContextHandler contextHandler = ContextHandler.getCurrentContext().getContextHandler();
|
||||||
if (contextHandler != null)
|
if (contextHandler != null)
|
||||||
contextHandler.removeEventListener(_listener);
|
contextHandler.removeEventListener(_listener);
|
||||||
getServletHandler().destroyListener(_listener);
|
getServletHandler().destroyListener(unwrap(_listener));
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
@ -146,4 +147,46 @@ public class ListenerHolder extends BaseHolder<EventListener>
|
||||||
{
|
{
|
||||||
return super.toString() + ": " + getClassName();
|
return super.toString() + ": " + getClassName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Experimental Wrapper mechanism for Servlet EventListeners.
|
||||||
|
* <p>
|
||||||
|
* Beans in {@code ServletContextHandler} or {@code WebAppContext} that implement this interface
|
||||||
|
* will be called to optionally wrap any newly created Servlet EventListeners before
|
||||||
|
* they are used for the first time.
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public interface WrapFunction
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Optionally wrap the Servlet EventListener.
|
||||||
|
*
|
||||||
|
* @param listener the Servlet EventListener being passed in.
|
||||||
|
* @return the Servlet EventListener (extend from {@link ListenerHolder.Wrapper}
|
||||||
|
* if you do wrap the Servlet EventListener)
|
||||||
|
*/
|
||||||
|
EventListener wrapEventListener(EventListener listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Wrapper implements EventListener, Wrapped<EventListener>
|
||||||
|
{
|
||||||
|
final EventListener _listener;
|
||||||
|
|
||||||
|
public Wrapper(EventListener listener)
|
||||||
|
{
|
||||||
|
_listener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EventListener getWrapped()
|
||||||
|
{
|
||||||
|
return _listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return String.format("%s:%s", this.getClass().getSimpleName(), _listener.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -377,6 +377,11 @@ public class ServletHandler extends ScopedHandler
|
||||||
return _servletContext;
|
return _servletContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ServletContextHandler getServletContextHandler()
|
||||||
|
{
|
||||||
|
return _contextHandler;
|
||||||
|
}
|
||||||
|
|
||||||
@ManagedAttribute(value = "mappings of servlets", readonly = true)
|
@ManagedAttribute(value = "mappings of servlets", readonly = true)
|
||||||
public ServletMapping[] getServletMappings()
|
public ServletMapping[] getServletMappings()
|
||||||
{
|
{
|
||||||
|
@ -1575,7 +1580,6 @@ public class ServletHandler extends ScopedHandler
|
||||||
{
|
{
|
||||||
if (LOG.isDebugEnabled())
|
if (LOG.isDebugEnabled())
|
||||||
LOG.debug("call filter {}", _filterHolder);
|
LOG.debug("call filter {}", _filterHolder);
|
||||||
Filter filter = _filterHolder.getFilter();
|
|
||||||
|
|
||||||
//if the request already does not support async, then the setting for the filter
|
//if the request already does not support async, then the setting for the filter
|
||||||
//is irrelevant. However if the request supports async but this filter does not
|
//is irrelevant. However if the request supports async but this filter does not
|
||||||
|
@ -1585,7 +1589,7 @@ public class ServletHandler extends ScopedHandler
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
baseRequest.setAsyncSupported(false, _filterHolder.toString());
|
baseRequest.setAsyncSupported(false, _filterHolder.toString());
|
||||||
filter.doFilter(request, response, _next);
|
_filterHolder.doFilter(request, response, _next);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
@ -1593,7 +1597,7 @@ public class ServletHandler extends ScopedHandler
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
filter.doFilter(request, response, _next);
|
_filterHolder.doFilter(request, response, _next);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1648,7 +1652,6 @@ public class ServletHandler extends ScopedHandler
|
||||||
FilterHolder holder = _chain.get(_filter++);
|
FilterHolder holder = _chain.get(_filter++);
|
||||||
if (LOG.isDebugEnabled())
|
if (LOG.isDebugEnabled())
|
||||||
LOG.debug("call filter {}", holder);
|
LOG.debug("call filter {}", holder);
|
||||||
Filter filter = holder.getFilter();
|
|
||||||
|
|
||||||
//if the request already does not support async, then the setting for the filter
|
//if the request already does not support async, then the setting for the filter
|
||||||
//is irrelevant. However if the request supports async but this filter does not
|
//is irrelevant. However if the request supports async but this filter does not
|
||||||
|
@ -1658,7 +1661,7 @@ public class ServletHandler extends ScopedHandler
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_baseRequest.setAsyncSupported(false, holder.toString());
|
_baseRequest.setAsyncSupported(false, holder.toString());
|
||||||
filter.doFilter(request, response, this);
|
holder.doFilter(request, response, this);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
@ -1666,7 +1669,7 @@ public class ServletHandler extends ScopedHandler
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
filter.doFilter(request, response, this);
|
holder.doFilter(request, response, this);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@ import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.Stack;
|
import java.util.Stack;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
@ -445,19 +446,18 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void destroyInstance(Object o)
|
public void destroyInstance(Object o)
|
||||||
throws Exception
|
|
||||||
{
|
{
|
||||||
if (o == null)
|
if (o == null)
|
||||||
return;
|
return;
|
||||||
Servlet servlet = ((Servlet)o);
|
|
||||||
//need to use the unwrapped servlet because lifecycle callbacks such as
|
Servlet servlet = (Servlet)o;
|
||||||
//postconstruct and predestroy are based off the classname and the wrapper
|
|
||||||
//classes are unknown outside the ServletHolder
|
// need to use the unwrapped servlet because lifecycle callbacks such as
|
||||||
Servlet unwrapped = servlet;
|
// postconstruct and predestroy are based off the classname and the wrapper
|
||||||
while (WrapperServlet.class.isAssignableFrom(unwrapped.getClass()))
|
// classes are unknown outside the ServletHolder
|
||||||
unwrapped = ((WrapperServlet)unwrapped).getWrappedServlet();
|
getServletHandler().destroyServlet(unwrap(servlet));
|
||||||
getServletHandler().destroyServlet(unwrapped);
|
|
||||||
//destroy the wrapped servlet, in case there is special behaviour
|
// destroy the wrapped servlet, in case there is special behaviour
|
||||||
servlet.destroy();
|
servlet.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -582,14 +582,13 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
|
||||||
_identityService = getServletHandler().getIdentityService();
|
_identityService = getServletHandler().getIdentityService();
|
||||||
if (_identityService != null)
|
if (_identityService != null)
|
||||||
{
|
{
|
||||||
|
|
||||||
_runAsToken = _identityService.newRunAsToken(_runAsRole);
|
_runAsToken = _identityService.newRunAsToken(_runAsRole);
|
||||||
_servlet = new RunAsServlet(_servlet, _identityService, _runAsToken);
|
_servlet = new RunAs(_servlet, _identityService, _runAsToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isAsyncSupported())
|
if (!isAsyncSupported())
|
||||||
_servlet = new NotAsyncServlet(_servlet);
|
_servlet = new NotAsync(_servlet);
|
||||||
|
|
||||||
// Handle configuring servlets that implement org.apache.jasper.servlet.JspServlet
|
// Handle configuring servlets that implement org.apache.jasper.servlet.JspServlet
|
||||||
if (isJspServlet())
|
if (isJspServlet())
|
||||||
|
@ -600,6 +599,8 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
|
||||||
else if (_forcedPath != null)
|
else if (_forcedPath != null)
|
||||||
detectJspContainer();
|
detectJspContainer();
|
||||||
|
|
||||||
|
_servlet = wrap(_servlet, WrapFunction.class, WrapFunction::wrapServlet);
|
||||||
|
|
||||||
if (LOG.isDebugEnabled())
|
if (LOG.isDebugEnabled())
|
||||||
LOG.debug("Servlet.init {} for {}", _servlet, getName());
|
LOG.debug("Servlet.init {} for {}", _servlet, getName());
|
||||||
_servlet.init(_config);
|
_servlet.init(_config);
|
||||||
|
@ -1235,13 +1236,38 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class WrapperServlet implements Servlet
|
/**
|
||||||
|
* Experimental Wrapper mechanism for Servlet objects.
|
||||||
|
* <p>
|
||||||
|
* Beans in {@code ServletContextHandler} or {@code WebAppContext} that implement this interface
|
||||||
|
* will be called to optionally wrap any newly created Servlets
|
||||||
|
* (before their {@link Servlet#init(ServletConfig)} method is called)
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public interface WrapFunction
|
||||||
{
|
{
|
||||||
final Servlet _servlet;
|
/**
|
||||||
|
* Optionally wrap the Servlet.
|
||||||
|
*
|
||||||
|
* @param servlet the servlet being passed in.
|
||||||
|
* @return the servlet (extend from {@link ServletHolder.Wrapper} if you do wrap the Servlet)
|
||||||
|
*/
|
||||||
|
Servlet wrapServlet(Servlet servlet);
|
||||||
|
}
|
||||||
|
|
||||||
public WrapperServlet(Servlet servlet)
|
public static class Wrapper implements Servlet, Wrapped<Servlet>
|
||||||
{
|
{
|
||||||
_servlet = servlet;
|
private final Servlet _servlet;
|
||||||
|
|
||||||
|
public Wrapper(Servlet servlet)
|
||||||
|
{
|
||||||
|
_servlet = Objects.requireNonNull(servlet, "Servlet cannot be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Servlet getWrapped()
|
||||||
|
{
|
||||||
|
return _servlet;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1274,14 +1300,6 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
|
||||||
_servlet.destroy();
|
_servlet.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the original servlet
|
|
||||||
*/
|
|
||||||
public Servlet getWrappedServlet()
|
|
||||||
{
|
|
||||||
return _servlet;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
|
@ -1289,12 +1307,12 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class RunAsServlet extends WrapperServlet
|
private static class RunAs extends Wrapper
|
||||||
{
|
{
|
||||||
final IdentityService _identityService;
|
final IdentityService _identityService;
|
||||||
final RunAsToken _runAsToken;
|
final RunAsToken _runAsToken;
|
||||||
|
|
||||||
public RunAsServlet(Servlet servlet, IdentityService identityService, RunAsToken runAsToken)
|
public RunAs(Servlet servlet, IdentityService identityService, RunAsToken runAsToken)
|
||||||
{
|
{
|
||||||
super(servlet);
|
super(servlet);
|
||||||
_identityService = identityService;
|
_identityService = identityService;
|
||||||
|
@ -1307,7 +1325,7 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
|
||||||
Object oldRunAs = _identityService.setRunAs(_identityService.getSystemUserIdentity(), _runAsToken);
|
Object oldRunAs = _identityService.setRunAs(_identityService.getSystemUserIdentity(), _runAsToken);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_servlet.init(config);
|
getWrapped().init(config);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
@ -1321,7 +1339,7 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
|
||||||
Object oldRunAs = _identityService.setRunAs(_identityService.getSystemUserIdentity(), _runAsToken);
|
Object oldRunAs = _identityService.setRunAs(_identityService.getSystemUserIdentity(), _runAsToken);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_servlet.service(req, res);
|
getWrapped().service(req, res);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
@ -1335,7 +1353,7 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
|
||||||
Object oldRunAs = _identityService.setRunAs(_identityService.getSystemUserIdentity(), _runAsToken);
|
Object oldRunAs = _identityService.setRunAs(_identityService.getSystemUserIdentity(), _runAsToken);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_servlet.destroy();
|
getWrapped().destroy();
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
@ -1344,9 +1362,9 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class NotAsyncServlet extends WrapperServlet
|
private static class NotAsync extends Wrapper
|
||||||
{
|
{
|
||||||
public NotAsyncServlet(Servlet servlet)
|
public NotAsync(Servlet servlet)
|
||||||
{
|
{
|
||||||
super(servlet);
|
super(servlet);
|
||||||
}
|
}
|
||||||
|
@ -1360,7 +1378,7 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
baseRequest.setAsyncSupported(false, this.toString());
|
baseRequest.setAsyncSupported(false, this.toString());
|
||||||
_servlet.service(req, res);
|
getWrapped().service(req, res);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
@ -1369,7 +1387,7 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_servlet.service(req, res);
|
getWrapped().service(req, res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,292 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
|
||||||
|
//
|
||||||
|
// This program and the accompanying materials are made available under
|
||||||
|
// the terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
// https://www.eclipse.org/legal/epl-2.0
|
||||||
|
//
|
||||||
|
// This Source Code may also be made available under the following
|
||||||
|
// Secondary Licenses when the conditions for such availability set
|
||||||
|
// forth in the Eclipse Public License, v. 2.0 are satisfied:
|
||||||
|
// the Apache License v2.0 which is available at
|
||||||
|
// https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||||
|
// ========================================================================
|
||||||
|
//
|
||||||
|
|
||||||
|
package org.eclipse.jetty.servlet;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.EnumSet;
|
||||||
|
import java.util.EventListener;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
import javax.servlet.DispatcherType;
|
||||||
|
import javax.servlet.Filter;
|
||||||
|
import javax.servlet.FilterChain;
|
||||||
|
import javax.servlet.FilterConfig;
|
||||||
|
import javax.servlet.Servlet;
|
||||||
|
import javax.servlet.ServletConfig;
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.ServletRequest;
|
||||||
|
import javax.servlet.ServletRequestEvent;
|
||||||
|
import javax.servlet.ServletRequestListener;
|
||||||
|
import javax.servlet.ServletResponse;
|
||||||
|
import javax.servlet.http.HttpServlet;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.client.HttpClient;
|
||||||
|
import org.eclipse.jetty.client.api.ContentResponse;
|
||||||
|
import org.eclipse.jetty.http.HttpStatus;
|
||||||
|
import org.eclipse.jetty.server.Server;
|
||||||
|
import org.eclipse.jetty.server.ServerConnector;
|
||||||
|
import org.eclipse.jetty.util.component.LifeCycle;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.is;
|
||||||
|
|
||||||
|
public class ComponentWrapTest
|
||||||
|
{
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(ComponentWrapTest.class);
|
||||||
|
private Server server;
|
||||||
|
private HttpClient client;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void setUp() throws Exception
|
||||||
|
{
|
||||||
|
server = new Server();
|
||||||
|
ServerConnector connector = new ServerConnector(server);
|
||||||
|
connector.setPort(0);
|
||||||
|
server.addConnector(connector);
|
||||||
|
|
||||||
|
client = new HttpClient();
|
||||||
|
client.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void tearDown()
|
||||||
|
{
|
||||||
|
LifeCycle.stop(client);
|
||||||
|
LifeCycle.stop(server);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSimpleFilterServletAndListener() throws Exception
|
||||||
|
{
|
||||||
|
EventQueue events = new EventQueue();
|
||||||
|
WrapHandler wrapHandler = new WrapHandler(events);
|
||||||
|
|
||||||
|
ServletContextHandler contextHandler = new ServletContextHandler();
|
||||||
|
contextHandler.setContextPath("/");
|
||||||
|
ServletHolder servletHolder = new ServletHolder(new HttpServlet()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException
|
||||||
|
{
|
||||||
|
resp.setContentType("text/plain");
|
||||||
|
resp.setCharacterEncoding("utf-8");
|
||||||
|
resp.getWriter().println("hello");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
contextHandler.addServlet(servletHolder, "/hello");
|
||||||
|
FilterHolder filterHolder = new FilterHolder(new Filter()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void init(FilterConfig filterConfig)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
|
||||||
|
{
|
||||||
|
chain.doFilter(request, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroy()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
});
|
||||||
|
contextHandler.addFilter(filterHolder, "/*", EnumSet.of(DispatcherType.REQUEST));
|
||||||
|
|
||||||
|
ListenerHolder listenerHolder = new ListenerHolder(LoggingRequestListener.class);
|
||||||
|
contextHandler.getServletHandler().addListener(listenerHolder);
|
||||||
|
|
||||||
|
contextHandler.addBean(wrapHandler);
|
||||||
|
server.setHandler(contextHandler);
|
||||||
|
server.start();
|
||||||
|
|
||||||
|
ContentResponse response = client.GET(server.getURI().resolve("/hello"));
|
||||||
|
assertThat("Response.status", response.getStatus(), is(HttpStatus.OK_200));
|
||||||
|
|
||||||
|
List<String> expectedEvents = new ArrayList<>();
|
||||||
|
expectedEvents.add("TestWrapFilter.init()");
|
||||||
|
expectedEvents.add("TestWrapServlet.init()");
|
||||||
|
expectedEvents.add("TestWrapListener.requestInitialized()");
|
||||||
|
expectedEvents.add("TestWrapFilter.doFilter()");
|
||||||
|
expectedEvents.add("TestWrapServlet.service()");
|
||||||
|
expectedEvents.add("TestWrapListener.requestDestroyed()");
|
||||||
|
|
||||||
|
List<String> actualEvents = new ArrayList<>();
|
||||||
|
actualEvents.addAll(events);
|
||||||
|
|
||||||
|
assertThat("Metrics Events Count", actualEvents.size(), is(expectedEvents.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class LoggingRequestListener implements ServletRequestListener
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void requestDestroyed(ServletRequestEvent sre)
|
||||||
|
{
|
||||||
|
LOG.info("requestDestroyed()");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void requestInitialized(ServletRequestEvent sre)
|
||||||
|
{
|
||||||
|
LOG.info("requestInitialized()");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class EventQueue extends LinkedBlockingQueue<String>
|
||||||
|
{
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(EventQueue.class);
|
||||||
|
|
||||||
|
public void addEvent(String format, Object... args)
|
||||||
|
{
|
||||||
|
String eventText = String.format(format, args);
|
||||||
|
offer(eventText);
|
||||||
|
Throwable cause = null;
|
||||||
|
if (args.length > 0)
|
||||||
|
{
|
||||||
|
Object lastArg = args[args.length - 1];
|
||||||
|
if (lastArg instanceof Throwable)
|
||||||
|
{
|
||||||
|
cause = (Throwable)lastArg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LOG.info("[EVENT] {}", eventText, cause);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class WrapHandler implements
|
||||||
|
FilterHolder.WrapFunction,
|
||||||
|
ServletHolder.WrapFunction,
|
||||||
|
ListenerHolder.WrapFunction
|
||||||
|
{
|
||||||
|
private EventQueue events;
|
||||||
|
|
||||||
|
public WrapHandler(EventQueue events)
|
||||||
|
{
|
||||||
|
this.events = events;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Filter wrapFilter(Filter filter)
|
||||||
|
{
|
||||||
|
return new TestWrapFilter(filter, events);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EventListener wrapEventListener(EventListener listener)
|
||||||
|
{
|
||||||
|
if (listener instanceof ServletRequestListener)
|
||||||
|
{
|
||||||
|
return new TestWrapListener((ServletRequestListener)listener, events);
|
||||||
|
}
|
||||||
|
return listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Servlet wrapServlet(Servlet servlet)
|
||||||
|
{
|
||||||
|
return new TestWrapServlet(servlet, events);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class TestWrapFilter extends FilterHolder.Wrapper
|
||||||
|
{
|
||||||
|
private EventQueue events;
|
||||||
|
|
||||||
|
public TestWrapFilter(Filter filter, EventQueue events)
|
||||||
|
{
|
||||||
|
super(filter);
|
||||||
|
this.events = events;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(FilterConfig filterConfig) throws ServletException
|
||||||
|
{
|
||||||
|
events.addEvent("TestWrapFilter.init()");
|
||||||
|
super.init(filterConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
|
||||||
|
{
|
||||||
|
events.addEvent("TestWrapFilter.doFilter()");
|
||||||
|
super.doFilter(request, response, chain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class TestWrapServlet extends ServletHolder.Wrapper
|
||||||
|
{
|
||||||
|
private EventQueue events;
|
||||||
|
|
||||||
|
public TestWrapServlet(Servlet servlet, EventQueue events)
|
||||||
|
{
|
||||||
|
super(servlet);
|
||||||
|
this.events = events;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(ServletConfig config) throws ServletException
|
||||||
|
{
|
||||||
|
events.addEvent("TestWrapServlet.init()");
|
||||||
|
super.init(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException
|
||||||
|
{
|
||||||
|
events.addEvent("TestWrapServlet.service()");
|
||||||
|
super.service(req, res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class TestWrapListener extends ListenerHolder.Wrapper implements ServletRequestListener
|
||||||
|
{
|
||||||
|
private ServletRequestListener requestListener;
|
||||||
|
private EventQueue events;
|
||||||
|
|
||||||
|
public TestWrapListener(ServletRequestListener listener, EventQueue events)
|
||||||
|
{
|
||||||
|
super(listener);
|
||||||
|
this.requestListener = listener;
|
||||||
|
this.events = events;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void requestDestroyed(ServletRequestEvent sre)
|
||||||
|
{
|
||||||
|
this.events.addEvent("TestWrapListener.requestDestroyed()");
|
||||||
|
requestListener.requestDestroyed(sre);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void requestInitialized(ServletRequestEvent sre)
|
||||||
|
{
|
||||||
|
this.events.addEvent("TestWrapListener.requestInitialized()");
|
||||||
|
requestListener.requestInitialized(sre);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -108,10 +108,10 @@ public class ServletLifeCycleTest
|
||||||
server.stop();
|
server.stop();
|
||||||
|
|
||||||
assertThat(events, Matchers.contains(
|
assertThat(events, Matchers.contains(
|
||||||
"destroy class org.eclipse.jetty.servlet.ServletLifeCycleTest$TestFilter2",
|
|
||||||
"Destroy class org.eclipse.jetty.servlet.ServletLifeCycleTest$TestFilter2",
|
"Destroy class org.eclipse.jetty.servlet.ServletLifeCycleTest$TestFilter2",
|
||||||
"destroy class org.eclipse.jetty.servlet.ServletLifeCycleTest$TestFilter",
|
"destroy class org.eclipse.jetty.servlet.ServletLifeCycleTest$TestFilter2",
|
||||||
"Destroy class org.eclipse.jetty.servlet.ServletLifeCycleTest$TestFilter",
|
"Destroy class org.eclipse.jetty.servlet.ServletLifeCycleTest$TestFilter",
|
||||||
|
"destroy class org.eclipse.jetty.servlet.ServletLifeCycleTest$TestFilter",
|
||||||
"Destroy class org.eclipse.jetty.servlet.ServletLifeCycleTest$TestServlet3",
|
"Destroy class org.eclipse.jetty.servlet.ServletLifeCycleTest$TestServlet3",
|
||||||
"destroy class org.eclipse.jetty.servlet.ServletLifeCycleTest$TestServlet3",
|
"destroy class org.eclipse.jetty.servlet.ServletLifeCycleTest$TestServlet3",
|
||||||
"Destroy class org.eclipse.jetty.servlet.ServletLifeCycleTest$TestServlet2",
|
"Destroy class org.eclipse.jetty.servlet.ServletLifeCycleTest$TestServlet2",
|
||||||
|
|
|
@ -179,4 +179,74 @@ public interface Configuration
|
||||||
* @return true if configuration should be aborted
|
* @return true if configuration should be aborted
|
||||||
*/
|
*/
|
||||||
boolean abort(WebAppContext context);
|
boolean abort(WebAppContext context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Experimental Wrapper mechanism for WebApp Configuration components.
|
||||||
|
* <p>
|
||||||
|
* Beans in WebAppContext that implement this interface
|
||||||
|
* will be called to optionally wrap any newly created {@link Configuration}
|
||||||
|
* objects before they are used for the first time.
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
interface WrapperFunction
|
||||||
|
{
|
||||||
|
Configuration wrapConfiguration(Configuration configuration);
|
||||||
|
}
|
||||||
|
|
||||||
|
class Wrapper implements Configuration
|
||||||
|
{
|
||||||
|
private Configuration delegate;
|
||||||
|
|
||||||
|
public Wrapper(Configuration delegate)
|
||||||
|
{
|
||||||
|
this.delegate = delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Configuration getWrapped()
|
||||||
|
{
|
||||||
|
return delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void preConfigure(WebAppContext context) throws Exception
|
||||||
|
{
|
||||||
|
delegate.preConfigure(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configure(WebAppContext context) throws Exception
|
||||||
|
{
|
||||||
|
delegate.configure(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void postConfigure(WebAppContext context) throws Exception
|
||||||
|
{
|
||||||
|
delegate.postConfigure(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deconfigure(WebAppContext context) throws Exception
|
||||||
|
{
|
||||||
|
delegate.deconfigure(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroy(WebAppContext context) throws Exception
|
||||||
|
{
|
||||||
|
delegate.destroy(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEnabledByDefault()
|
||||||
|
{
|
||||||
|
return delegate.isEnabledByDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean abort(WebAppContext context)
|
||||||
|
{
|
||||||
|
return delegate.abort(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -532,6 +532,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
||||||
_metadata.setAllowDuplicateFragmentNames(isAllowDuplicateFragmentNames());
|
_metadata.setAllowDuplicateFragmentNames(isAllowDuplicateFragmentNames());
|
||||||
Boolean validate = (Boolean)getAttribute(MetaData.VALIDATE_XML);
|
Boolean validate = (Boolean)getAttribute(MetaData.VALIDATE_XML);
|
||||||
_metadata.setValidateXml((validate != null && validate));
|
_metadata.setValidateXml((validate != null && validate));
|
||||||
|
wrapConfigurations();
|
||||||
preConfigure();
|
preConfigure();
|
||||||
super.doStart();
|
super.doStart();
|
||||||
postConfigure();
|
postConfigure();
|
||||||
|
@ -550,6 +551,26 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void wrapConfigurations()
|
||||||
|
{
|
||||||
|
Collection<Configuration.WrapperFunction> wrappers = getBeans(Configuration.WrapperFunction.class);
|
||||||
|
if (wrappers == null || wrappers.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
List<Configuration> configs = new ArrayList<>(_configurations.getConfigurations());
|
||||||
|
_configurations.clear();
|
||||||
|
|
||||||
|
for (Configuration config : configs)
|
||||||
|
{
|
||||||
|
Configuration wrapped = config;
|
||||||
|
for (Configuration.WrapperFunction wrapperFunction : getBeans(Configuration.WrapperFunction.class))
|
||||||
|
{
|
||||||
|
wrapped = wrapperFunction.wrapConfiguration(wrapped);
|
||||||
|
}
|
||||||
|
_configurations.add(wrapped);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void destroy()
|
public void destroy()
|
||||||
{
|
{
|
||||||
|
|
|
@ -185,15 +185,22 @@ public class WebAppContextTest
|
||||||
Configurations.cleanKnown();
|
Configurations.cleanKnown();
|
||||||
WebAppContext wac = new WebAppContext();
|
WebAppContext wac = new WebAppContext();
|
||||||
wac.setServer(new Server());
|
wac.setServer(new Server());
|
||||||
assertThat(wac.getConfigurations().stream().map(c -> c.getClass().getName()).collect(Collectors.toList()),
|
List<String> actualConfigurations = wac.getConfigurations().stream().map(c -> c.getClass().getName()).collect(Collectors.toList());
|
||||||
Matchers.contains(
|
List<String> expectedConfigurations = new ArrayList<>();
|
||||||
"org.eclipse.jetty.webapp.JmxConfiguration",
|
|
||||||
"org.eclipse.jetty.webapp.WebInfConfiguration",
|
JmxConfiguration jmx = new JmxConfiguration();
|
||||||
"org.eclipse.jetty.webapp.WebXmlConfiguration",
|
if (jmx.isAvailable()) // depending on JVM runtime, this might not be available when this test is run
|
||||||
"org.eclipse.jetty.webapp.MetaInfConfiguration",
|
{
|
||||||
"org.eclipse.jetty.webapp.FragmentConfiguration",
|
expectedConfigurations.add("org.eclipse.jetty.webapp.JmxConfiguration");
|
||||||
"org.eclipse.jetty.webapp.WebAppConfiguration",
|
}
|
||||||
"org.eclipse.jetty.webapp.JettyWebXmlConfiguration"));
|
expectedConfigurations.add("org.eclipse.jetty.webapp.WebInfConfiguration");
|
||||||
|
expectedConfigurations.add("org.eclipse.jetty.webapp.WebXmlConfiguration");
|
||||||
|
expectedConfigurations.add("org.eclipse.jetty.webapp.MetaInfConfiguration");
|
||||||
|
expectedConfigurations.add("org.eclipse.jetty.webapp.FragmentConfiguration");
|
||||||
|
expectedConfigurations.add("org.eclipse.jetty.webapp.WebAppConfiguration");
|
||||||
|
expectedConfigurations.add("org.eclipse.jetty.webapp.JettyWebXmlConfiguration");
|
||||||
|
|
||||||
|
assertThat(actualConfigurations, Matchers.contains(expectedConfigurations.toArray()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
Loading…
Reference in New Issue