Servlet Context/Handler/Holder cleanups (#3767)

Issue #3749 #3755 Servlet annotation cleanups
Cleanups when checking thread safety of lazy servlet/filter introspection.

 + Handle multiple holders for annotated servlets
 + Replaced duplicate code with common methods

Signed-off-by: Greg Wilkins <gregw@webtide.com>
This commit is contained in:
Greg Wilkins 2019-06-12 08:00:01 +02:00 committed by GitHub
parent 2ea0bca333
commit 819c379975
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 72 additions and 169 deletions

View File

@ -62,9 +62,7 @@ public class MultiPartConfigAnnotationHandler extends AbstractIntrospectableAnno
//How to identify the correct Servlet? If the Servlet has no WebServlet annotation on it, does it mean that this MultipartConfig //How to identify the correct Servlet? If the Servlet has no WebServlet annotation on it, does it mean that this MultipartConfig
//annotation applies to all declared instances in web.xml/programmatically? //annotation applies to all declared instances in web.xml/programmatically?
//Assuming TRUE for now. //Assuming TRUE for now.
for (ServletHolder holder : _context.getServletHandler().getServlets(clazz))
ServletHolder holder = getServletHolderForClass(clazz);
if (holder != null)
{ {
Descriptor d = metaData.getOriginDescriptor(holder.getName()+".servlet.multipart-config"); Descriptor d = metaData.getOriginDescriptor(holder.getName()+".servlet.multipart-config");
//if a descriptor has already set the value for multipart config, do not //if a descriptor has already set the value for multipart config, do not
@ -76,21 +74,4 @@ public class MultiPartConfigAnnotationHandler extends AbstractIntrospectableAnno
} }
} }
} }
private ServletHolder getServletHolderForClass (Class clazz)
{
ServletHolder holder = null;
ServletHolder[] holders = _context.getServletHandler().getServlets();
if (holders != null)
{
for (ServletHolder h : holders)
{
if (h.getClassName() != null && h.getClassName().equals(clazz.getName()))
{
holder = h;
}
}
}
return holder;
}
} }

View File

@ -56,8 +56,7 @@ public class RunAsAnnotationHandler extends AbstractIntrospectableAnnotationHand
String role = runAs.value(); String role = runAs.value();
if (role != null) if (role != null)
{ {
ServletHolder holder = getServletHolderForClass(clazz); for (ServletHolder holder : _context.getServletHandler().getServlets(clazz))
if (holder != null)
{ {
MetaData metaData = _context.getMetaData(); MetaData metaData = _context.getMetaData();
Descriptor d = metaData.getOriginDescriptor(holder.getName()+".servlet.run-as"); Descriptor d = metaData.getOriginDescriptor(holder.getName()+".servlet.run-as");
@ -82,7 +81,6 @@ public class RunAsAnnotationHandler extends AbstractIntrospectableAnnotationHand
else else
LOG.warn("Bad value for @RunAs annotation on class "+clazz.getName()); LOG.warn("Bad value for @RunAs annotation on class "+clazz.getName());
} }
} }
public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation) public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation)
@ -94,21 +92,4 @@ public class RunAsAnnotationHandler extends AbstractIntrospectableAnnotationHand
{ {
LOG.warn("@RunAs annotation ignored on method: "+className+"."+methodName+" "+signature); LOG.warn("@RunAs annotation ignored on method: "+className+"."+methodName+" "+signature);
} }
private ServletHolder getServletHolderForClass (Class clazz)
{
ServletHolder holder = null;
ServletHolder[] holders = _context.getServletHandler().getServlets();
if (holders != null)
{
for (ServletHolder h : holders)
{
if (h.getClassName() != null && h.getClassName().equals(clazz.getName()))
{
holder = h;
}
}
}
return holder;
}
} }

View File

@ -29,7 +29,6 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import javax.servlet.DispatcherType; import javax.servlet.DispatcherType;
import javax.servlet.Filter; import javax.servlet.Filter;
import javax.servlet.FilterRegistration; import javax.servlet.FilterRegistration;
@ -61,12 +60,12 @@ import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.HandlerContainer; import org.eclipse.jetty.server.HandlerContainer;
import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.ErrorHandler; import org.eclipse.jetty.server.handler.ErrorHandler;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.server.handler.HandlerWrapper; import org.eclipse.jetty.server.handler.HandlerWrapper;
import org.eclipse.jetty.server.handler.gzip.GzipHandler; import org.eclipse.jetty.server.handler.gzip.GzipHandler;
import org.eclipse.jetty.server.session.SessionHandler; import org.eclipse.jetty.server.session.SessionHandler;
import org.eclipse.jetty.util.DecoratedObjectFactory; import org.eclipse.jetty.util.DecoratedObjectFactory;
import org.eclipse.jetty.util.DeprecationWarning; import org.eclipse.jetty.util.DeprecationWarning;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.annotation.ManagedAttribute; import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject; import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.component.LifeCycle; import org.eclipse.jetty.util.component.LifeCycle;
@ -255,7 +254,6 @@ public class ServletContextHandler extends ContextHandler
handler=_gzipHandler; handler=_gzipHandler;
} }
// link servlet handler // link servlet handler
if (getServletHandler()!=null) if (getServletHandler()!=null)
{ {
@ -267,7 +265,6 @@ public class ServletContextHandler extends ContextHandler
doSetHandler(handler,_servletHandler); doSetHandler(handler,_servletHandler);
handler=_servletHandler; handler=_servletHandler;
} }
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@ -566,21 +563,32 @@ public class ServletContextHandler extends ContextHandler
super.callContextDestroyed(l, e); super.callContextDestroyed(l, e);
} }
private boolean replaceHandler(Handler handler,Handler replace) private void replaceHandler(HandlerWrapper handler, HandlerWrapper replacement)
{ {
HandlerWrapper wrapper=this; if (isStarted())
while(true) throw new IllegalStateException("STARTED");
{
if (wrapper.getHandler()==handler)
{
doSetHandler(wrapper,replace);
return true;
}
if (!(wrapper.getHandler() instanceof HandlerWrapper)) Handler next=null;
return false; if (handler!=null)
wrapper = (HandlerWrapper)wrapper.getHandler(); {
next=handler.getHandler();
handler.setHandler(null);
HandlerWrapper wrapper=this;
while(wrapper != null)
{
if (wrapper.getHandler() == handler)
{
doSetHandler(wrapper,replacement);
break;
}
wrapper = (wrapper.getHandler() instanceof HandlerWrapper) ? (HandlerWrapper)wrapper.getHandler() : null;
}
} }
if (next!=null && replacement.getHandler()==null)
replacement.setHandler(next);
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@ -589,20 +597,8 @@ public class ServletContextHandler extends ContextHandler
*/ */
public void setSessionHandler(SessionHandler sessionHandler) public void setSessionHandler(SessionHandler sessionHandler)
{ {
if (isStarted()) replaceHandler(_sessionHandler, sessionHandler);
throw new IllegalStateException("STARTED");
Handler next=null;
if (_sessionHandler!=null)
{
next=_sessionHandler.getHandler();
_sessionHandler.setHandler(null);
replaceHandler(_sessionHandler,sessionHandler);
}
_sessionHandler = sessionHandler; _sessionHandler = sessionHandler;
if (next!=null && _sessionHandler.getHandler()==null)
_sessionHandler.setHandler(next);
relinkHandlers(); relinkHandlers();
} }
@ -612,44 +608,19 @@ public class ServletContextHandler extends ContextHandler
*/ */
public void setSecurityHandler(SecurityHandler securityHandler) public void setSecurityHandler(SecurityHandler securityHandler)
{ {
if (isStarted()) replaceHandler(_sessionHandler, securityHandler);
throw new IllegalStateException("STARTED");
Handler next=null;
if (_securityHandler!=null)
{
next=_securityHandler.getHandler();
_securityHandler.setHandler(null);
replaceHandler(_securityHandler,securityHandler);
}
_securityHandler = securityHandler; _securityHandler = securityHandler;
if (next!=null && _securityHandler.getHandler()==null)
_securityHandler.setHandler(next);
relinkHandlers(); relinkHandlers();
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
* @param gzipHandler The {@link GzipHandler} to set on this context. * @param gzipHandler The {@link GzipHandler} to set on this context.
*/ */
public void setGzipHandler(GzipHandler gzipHandler) public void setGzipHandler(GzipHandler gzipHandler)
{ {
if (isStarted()) replaceHandler(_gzipHandler, gzipHandler);
throw new IllegalStateException("STARTED");
Handler next=null;
if (_gzipHandler!=null)
{
next=_gzipHandler.getHandler();
_gzipHandler.setHandler(null);
replaceHandler(_gzipHandler,gzipHandler);
}
_gzipHandler = gzipHandler; _gzipHandler = gzipHandler;
if (next!=null && _gzipHandler.getHandler()==null)
_gzipHandler.setHandler(next);
relinkHandlers(); relinkHandlers();
} }
@ -659,23 +630,11 @@ public class ServletContextHandler extends ContextHandler
*/ */
public void setServletHandler(ServletHandler servletHandler) public void setServletHandler(ServletHandler servletHandler)
{ {
if (isStarted()) replaceHandler(_servletHandler, servletHandler);
throw new IllegalStateException("STARTED");
Handler next=null;
if (_servletHandler!=null)
{
next=_servletHandler.getHandler();
_servletHandler.setHandler(null);
replaceHandler(_servletHandler,servletHandler);
}
_servletHandler = servletHandler; _servletHandler = servletHandler;
if (next!=null && _servletHandler.getHandler()==null)
_servletHandler.setHandler(next);
relinkHandlers(); relinkHandlers();
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
* Insert a HandlerWrapper before the first Session,Security or ServletHandler * Insert a HandlerWrapper before the first Session,Security or ServletHandler
@ -1102,6 +1061,18 @@ public class ServletContextHandler extends ContextHandler
return new Dispatcher(context, name); return new Dispatcher(context, name);
} }
private void checkDynamicName(String name)
{
if (isStarted())
throw new IllegalStateException();
if (StringUtil.isBlank(name))
throw new IllegalStateException("Missing name");
if (!_enabled)
throw new UnsupportedOperationException();
}
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
* @since servlet-api-3.0 * @since servlet-api-3.0
@ -1109,14 +1080,7 @@ public class ServletContextHandler extends ContextHandler
@Override @Override
public FilterRegistration.Dynamic addFilter(String filterName, Class<? extends Filter> filterClass) public FilterRegistration.Dynamic addFilter(String filterName, Class<? extends Filter> filterClass)
{ {
if (isStarted()) checkDynamicName(filterName);
throw new IllegalStateException();
if (filterName == null || "".equals(filterName.trim()))
throw new IllegalStateException("Missing filter name");
if (!_enabled)
throw new UnsupportedOperationException();
final ServletHandler handler = ServletContextHandler.this.getServletHandler(); final ServletHandler handler = ServletContextHandler.this.getServletHandler();
FilterHolder holder = handler.getFilter(filterName); FilterHolder holder = handler.getFilter(filterName);
@ -1146,14 +1110,7 @@ public class ServletContextHandler extends ContextHandler
@Override @Override
public FilterRegistration.Dynamic addFilter(String filterName, String className) public FilterRegistration.Dynamic addFilter(String filterName, String className)
{ {
if (isStarted()) checkDynamicName(filterName);
throw new IllegalStateException();
if (filterName == null || "".equals(filterName.trim()))
throw new IllegalStateException("Missing filter name");
if (!_enabled)
throw new UnsupportedOperationException();
final ServletHandler handler = ServletContextHandler.this.getServletHandler(); final ServletHandler handler = ServletContextHandler.this.getServletHandler();
FilterHolder holder = handler.getFilter(filterName); FilterHolder holder = handler.getFilter(filterName);
@ -1184,14 +1141,7 @@ public class ServletContextHandler extends ContextHandler
@Override @Override
public FilterRegistration.Dynamic addFilter(String filterName, Filter filter) public FilterRegistration.Dynamic addFilter(String filterName, Filter filter)
{ {
if (isStarted()) checkDynamicName(filterName);
throw new IllegalStateException();
if (filterName == null || "".equals(filterName.trim()))
throw new IllegalStateException("Missing filter name");
if (!_enabled)
throw new UnsupportedOperationException();
final ServletHandler handler = ServletContextHandler.this.getServletHandler(); final ServletHandler handler = ServletContextHandler.this.getServletHandler();
FilterHolder holder = handler.getFilter(filterName); FilterHolder holder = handler.getFilter(filterName);
@ -1222,14 +1172,7 @@ public class ServletContextHandler extends ContextHandler
@Override @Override
public ServletRegistration.Dynamic addServlet(String servletName, Class<? extends Servlet> servletClass) public ServletRegistration.Dynamic addServlet(String servletName, Class<? extends Servlet> servletClass)
{ {
if (!isStarting()) checkDynamicName(servletName);
throw new IllegalStateException();
if (servletName == null || "".equals(servletName.trim()))
throw new IllegalStateException("Missing servlet name");
if (!_enabled)
throw new UnsupportedOperationException();
final ServletHandler handler = ServletContextHandler.this.getServletHandler(); final ServletHandler handler = ServletContextHandler.this.getServletHandler();
ServletHolder holder = handler.getServlet(servletName); ServletHolder holder = handler.getServlet(servletName);
@ -1260,15 +1203,7 @@ public class ServletContextHandler extends ContextHandler
@Override @Override
public ServletRegistration.Dynamic addServlet(String servletName, String className) public ServletRegistration.Dynamic addServlet(String servletName, String className)
{ {
if (!isStarting()) checkDynamicName(servletName);
throw new IllegalStateException();
if (servletName == null || "".equals(servletName.trim()))
throw new IllegalStateException("Missing servlet name");
if (!_enabled)
throw new UnsupportedOperationException();
final ServletHandler handler = ServletContextHandler.this.getServletHandler(); final ServletHandler handler = ServletContextHandler.this.getServletHandler();
ServletHolder holder = handler.getServlet(servletName); ServletHolder holder = handler.getServlet(servletName);
@ -1299,14 +1234,7 @@ public class ServletContextHandler extends ContextHandler
@Override @Override
public ServletRegistration.Dynamic addServlet(String servletName, Servlet servlet) public ServletRegistration.Dynamic addServlet(String servletName, Servlet servlet)
{ {
if (!isStarting()) checkDynamicName(servletName);
throw new IllegalStateException();
if (servletName == null || "".equals(servletName.trim()))
throw new IllegalStateException("Missing servlet name");
if (!_enabled)
throw new UnsupportedOperationException();
final ServletHandler handler = ServletContextHandler.this.getServletHandler(); final ServletHandler handler = ServletContextHandler.this.getServletHandler();
ServletHolder holder = handler.getServlet(servletName); ServletHolder holder = handler.getServlet(servletName);

View File

@ -33,7 +33,6 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import java.util.stream.Stream; import java.util.stream.Stream;
import javax.servlet.DispatcherType; import javax.servlet.DispatcherType;
import javax.servlet.Filter; import javax.servlet.Filter;
import javax.servlet.FilterChain; import javax.servlet.FilterChain;
@ -427,6 +426,23 @@ public class ServletHandler extends ScopedHandler
return _servlets; return _servlets;
} }
public List<ServletHolder> getServlets(Class<?> clazz)
{
List<ServletHolder> holders = null;
for (ServletHolder holder : _servlets)
{
Class<? extends Servlet> held = holder.getHeldClass();
if ((held == null && holder.getClassName() != null && holder.getClassName().equals(clazz.getName())) ||
(held != null && clazz.isAssignableFrom(holder.getHeldClass())))
{
if (holders == null)
holders = new ArrayList<>();
holders.add(holder);
}
}
return holders == null ? Collections.emptyList() : holders;
}
public ServletHolder getServlet(String name) public ServletHolder getServlet(String name)
{ {
return _servletNameMap.get(name); return _servletNameMap.get(name);

View File

@ -70,7 +70,6 @@ import org.eclipse.jetty.util.log.Logger;
@ManagedObject("Servlet Holder") @ManagedObject("Servlet Holder")
public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope, Comparable<ServletHolder> public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope, Comparable<ServletHolder>
{ {
/* ---------------------------------------------------------------- */ /* ---------------------------------------------------------------- */
private static final Logger LOG = Log.getLogger(ServletHolder.class); private static final Logger LOG = Log.getLogger(ServletHolder.class);
private int _initOrder = -1; private int _initOrder = -1;
@ -89,11 +88,9 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
private boolean _enabled = true; private boolean _enabled = true;
private UnavailableException _unavailableEx; private UnavailableException _unavailableEx;
public static final String APACHE_SENTINEL_CLASS = "org.apache.tomcat.InstanceManager"; public static final String APACHE_SENTINEL_CLASS = "org.apache.tomcat.InstanceManager";
public static final String JSP_GENERATED_PACKAGE_NAME = "org.eclipse.jetty.servlet.jspPackagePrefix"; public static final String JSP_GENERATED_PACKAGE_NAME = "org.eclipse.jetty.servlet.jspPackagePrefix";
public static final Map<String,String> NO_MAPPED_ROLES = Collections.emptyMap(); public enum JspContainer {APACHE, OTHER}
public static enum JspContainer {APACHE, OTHER};
/* ---------------------------------------------------------------- */ /* ---------------------------------------------------------------- */
/** Constructor . /** Constructor .
@ -1304,9 +1301,9 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
try try
{ {
ServletContext ctx = getServletHandler().getServletContext(); ServletContext ctx = getServletHandler().getServletContext();
if (ctx instanceof ServletContextHandler.Context) if (ctx == null)
return ((ServletContextHandler.Context)ctx).createServlet(getHeldClass()); return getHeldClass().getDeclaredConstructor().newInstance();
return getHeldClass().getDeclaredConstructor().newInstance(); return ctx.createServlet(getHeldClass());
} }
catch (ServletException se) catch (ServletException se)
{ {