mirror of
https://github.com/jetty/jetty.project.git
synced 2025-03-01 03:19:13 +00:00
413018 ServletContext.addListener() should throw IllegalArgumentException if arg is not correct type of listener
This commit is contained in:
parent
89b33f5b88
commit
47a8809ec7
@ -22,6 +22,7 @@ import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.ServletContainerInitializer;
|
||||
import javax.servlet.ServletContextListener;
|
||||
|
||||
import org.eclipse.jetty.util.Loader;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
@ -101,11 +102,12 @@ public class ContainerInitializer
|
||||
for (String s : _applicableTypeNames)
|
||||
classes.add(Loader.loadClass(context.getClass(), s));
|
||||
}
|
||||
|
||||
context.getServletContext().setExtendedListenerTypes(true);
|
||||
_target.onStartup(classes, context.getServletContext());
|
||||
}
|
||||
finally
|
||||
{
|
||||
{
|
||||
context.getServletContext().setExtendedListenerTypes(false);
|
||||
Thread.currentThread().setContextClassLoader(oldLoader);
|
||||
}
|
||||
}
|
||||
|
@ -40,6 +40,7 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import javax.servlet.DispatcherType;
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterRegistration;
|
||||
@ -61,6 +62,9 @@ import javax.servlet.SessionTrackingMode;
|
||||
import javax.servlet.descriptor.JspConfigDescriptor;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSessionAttributeListener;
|
||||
import javax.servlet.http.HttpSessionIdListener;
|
||||
import javax.servlet.http.HttpSessionListener;
|
||||
|
||||
import org.eclipse.jetty.http.MimeTypes;
|
||||
import org.eclipse.jetty.server.ClassLoaderDump;
|
||||
@ -103,11 +107,17 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
|
||||
{
|
||||
public static int SERVLET_MAJOR_VERSION=3;
|
||||
public static int SERVLET_MINOR_VERSION=0;
|
||||
public static final Class[] SERVLET_LISTENER_TYPES = new Class[] {ServletContextListener.class,
|
||||
ServletContextAttributeListener.class,
|
||||
ServletRequestListener.class,
|
||||
ServletRequestAttributeListener.class};
|
||||
|
||||
public static final int DEFAULT_LISTENER_TYPE_INDEX = 1;
|
||||
public static final int EXTENDED_LISTENER_TYPE_INDEX = 0;
|
||||
|
||||
|
||||
final private static String __unimplmented="Unimplemented - use org.eclipse.jetty.servlet.ServletContextHandler";
|
||||
|
||||
|
||||
|
||||
private static final Logger LOG = Log.getLogger(ContextHandler.class);
|
||||
|
||||
private static final ThreadLocal<Context> __context = new ThreadLocal<Context>();
|
||||
@ -1721,6 +1731,8 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
|
||||
public class Context extends NoContext
|
||||
{
|
||||
protected boolean _enabled = true; //whether or not the dynamic API is enabled for callers
|
||||
protected boolean _extendedListenerTypes = false;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected Context()
|
||||
@ -2125,6 +2137,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
|
||||
try
|
||||
{
|
||||
Class<? extends EventListener> clazz = _classLoader==null?Loader.loadClass(ContextHandler.class,className):_classLoader.loadClass(className);
|
||||
checkListener(clazz);
|
||||
addListener(clazz);
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
@ -2138,6 +2151,9 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
|
||||
{
|
||||
if (!_enabled)
|
||||
throw new UnsupportedOperationException();
|
||||
|
||||
checkListener(t.getClass());
|
||||
|
||||
ContextHandler.this.addEventListener(t);
|
||||
ContextHandler.this.addProgrammaticListener(t);
|
||||
}
|
||||
@ -2148,6 +2164,8 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
|
||||
if (!_enabled)
|
||||
throw new UnsupportedOperationException();
|
||||
|
||||
checkListener(listenerClass);
|
||||
|
||||
try
|
||||
{
|
||||
EventListener e = createListener(listenerClass);
|
||||
@ -2173,6 +2191,34 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void checkListener (Class<? extends EventListener> listener) throws IllegalStateException
|
||||
{
|
||||
boolean ok = false;
|
||||
int startIndex = (isExtendedListenerTypes()?EXTENDED_LISTENER_TYPE_INDEX:DEFAULT_LISTENER_TYPE_INDEX);
|
||||
for (int i=startIndex;i<SERVLET_LISTENER_TYPES.length;i++)
|
||||
{
|
||||
if (SERVLET_LISTENER_TYPES[i].isAssignableFrom(listener))
|
||||
{
|
||||
ok = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!ok)
|
||||
throw new IllegalArgumentException("Inappropriate listener class "+listener.getName());
|
||||
}
|
||||
|
||||
public void setExtendedListenerTypes (boolean extended)
|
||||
{
|
||||
_extendedListenerTypes = extended;
|
||||
}
|
||||
|
||||
public boolean isExtendedListenerTypes()
|
||||
{
|
||||
return _extendedListenerTypes;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ClassLoader getClassLoader()
|
||||
{
|
||||
@ -2210,7 +2256,8 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
|
||||
{
|
||||
return _enabled;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public <T> T createInstance (Class<T> clazz) throws Exception
|
||||
{
|
||||
|
@ -29,6 +29,9 @@ import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import javax.servlet.http.HttpSessionAttributeListener;
|
||||
import javax.servlet.http.HttpSessionIdListener;
|
||||
import javax.servlet.http.HttpSessionListener;
|
||||
|
||||
import org.eclipse.jetty.http.HttpCookie;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
@ -46,6 +49,11 @@ public class SessionHandler extends ScopedHandler
|
||||
final static Logger LOG = Log.getLogger("org.eclipse.jetty.server.session");
|
||||
|
||||
public final static EnumSet<SessionTrackingMode> DEFAULT_TRACKING = EnumSet.of(SessionTrackingMode.COOKIE,SessionTrackingMode.URL);
|
||||
|
||||
public static final Class[] SESSION_LISTENER_TYPES = new Class[] {HttpSessionAttributeListener.class,
|
||||
HttpSessionIdListener.class,
|
||||
HttpSessionListener.class};
|
||||
|
||||
|
||||
|
||||
/* -------------------------------------------------------------- */
|
||||
|
@ -95,6 +95,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
||||
|
||||
private String[] __dftProtectedTargets = {"/web-inf", "/meta-inf"};
|
||||
|
||||
|
||||
public static String[] DEFAULT_CONFIGURATION_CLASSES =
|
||||
{
|
||||
"org.eclipse.jetty.webapp.WebInfConfiguration",
|
||||
@ -1402,6 +1403,32 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
||||
/* ------------------------------------------------------------ */
|
||||
public class Context extends ServletContextHandler.Context
|
||||
{
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public void checkListener(Class<? extends EventListener> listener) throws IllegalStateException
|
||||
{
|
||||
try
|
||||
{
|
||||
super.checkListener(listener);
|
||||
}
|
||||
catch (IllegalArgumentException e)
|
||||
{
|
||||
//not one of the standard servlet listeners, check our extended session listener types
|
||||
boolean ok = false;
|
||||
for (Class l:SessionHandler.SESSION_LISTENER_TYPES)
|
||||
{
|
||||
if (l.isAssignableFrom(listener))
|
||||
{
|
||||
ok = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!ok)
|
||||
throw new IllegalArgumentException("Inappropriate listener type "+listener.getName());
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public URL getResource(String path) throws MalformedURLException
|
||||
@ -1448,7 +1475,6 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -197,14 +197,14 @@ public class AnnotationTest extends HttpServlet
|
||||
out.println("<pre>");
|
||||
out.println("initParams={@WebInitParam(name=\"fromAnnotation\", value=\"xyz\")}");
|
||||
out.println("</pre>");
|
||||
out.println("<br/><b>Result: "+("xyz".equals(config.getInitParameter("fromAnnotation"))? "<span class=\"pass\">PASS": "<span class=\"fail\">FAIL")+"</span>");
|
||||
out.println("<p><b>Result: "+("xyz".equals(config.getInitParameter("fromAnnotation"))? "<span class=\"pass\">PASS": "<span class=\"fail\">FAIL")+"</span></p>");
|
||||
|
||||
out.println("<h2>Init Params from web-fragment</h2>");
|
||||
out.println("<pre>");
|
||||
out.println("extra1=123, extra2=345");
|
||||
out.println("</pre>");
|
||||
boolean fragInitParamResult = "123".equals(config.getInitParameter("extra1")) && "345".equals(config.getInitParameter("extra2"));
|
||||
out.println("<br/><b>Result: "+(fragInitParamResult? "<span class=\"pass\">PASS": "<span class=\"fail\">FAIL")+"</span>");
|
||||
out.println("<p><b>Result: "+(fragInitParamResult? "<span class=\"pass\">PASS": "<span class=\"fail\">FAIL")+"</span></p>");
|
||||
|
||||
|
||||
__HandlesTypes = Arrays.asList( "javax.servlet.GenericServlet",
|
||||
@ -221,7 +221,7 @@ public class AnnotationTest extends HttpServlet
|
||||
out.println("<pre>");
|
||||
out.println("@HandlesTypes({javax.servlet.Servlet.class, Foo.class})");
|
||||
out.println("</pre>");
|
||||
out.print("<br/><b>Result: ");
|
||||
out.print("<p><b>Result: ");
|
||||
List<Class> classes = (List<Class>)config.getServletContext().getAttribute("com.acme.Foo");
|
||||
List<String> classNames = new ArrayList<String>();
|
||||
if (classes != null)
|
||||
@ -241,19 +241,28 @@ public class AnnotationTest extends HttpServlet
|
||||
}
|
||||
else
|
||||
out.print("<br/><span class=\"fail\">FAIL</span> (No such attribute com.acme.Foo)");
|
||||
out.println("</b>");
|
||||
out.println("</b></p>");
|
||||
|
||||
out.println("<h2>Complete Servlet Registration</h2>");
|
||||
Boolean complete = (Boolean)config.getServletContext().getAttribute("com.acme.AnnotationTest.complete");
|
||||
out.println("<br/><b>Result: "+(complete.booleanValue()?"<span class=\"pass\">PASS":"<span class=\"fail\">FAIL")+"</span></b>");
|
||||
out.println("<p><b>Result: "+(complete.booleanValue()?"<span class=\"pass\">PASS":"<span class=\"fail\">FAIL")+"</span></b></p>");
|
||||
|
||||
out.println("<h2>ServletContextListener Programmatic Registration from ServletContainerInitializer</h2>");
|
||||
Boolean programmaticListener = (Boolean)config.getServletContext().getAttribute("com.acme.AnnotationTest.listenerTest");
|
||||
out.println("<br/><b>Result: "+(programmaticListener.booleanValue()?"<span class=\"pass\">PASS":"<span class=\"fail\">FAIL")+"</span></b>");
|
||||
out.println("<p><b>Result: "+(programmaticListener.booleanValue()?"<span class=\"pass\">PASS":"<span class=\"fail\">FAIL")+"</span></b></p>");
|
||||
|
||||
out.println("<h2>ServletContextListener Programmatic Registration Prevented from ServletContextListener</h2>");
|
||||
Boolean programmaticListenerPrevention = (Boolean)config.getServletContext().getAttribute("com.acme.AnnotationTest.listenerRegoTest");
|
||||
out.println("<br/><b>Result: "+(programmaticListenerPrevention.booleanValue()?"<span class=\"pass\">PASS":"<span class=\"fail\">FAIL")+"</span></b>");
|
||||
out.println("<p><b>Result: "+(programmaticListenerPrevention.booleanValue()?"<span class=\"pass\">PASS":"<span class=\"fail\">FAIL")+"</span></b></p>");
|
||||
|
||||
out.println("<h2>ServletContextListener Registration Prevented from ServletContextListener</h2>");
|
||||
Boolean webListenerPrevention = (Boolean)config.getServletContext().getAttribute("com.acme.AnnotationTest.sclFromSclRegoTest");
|
||||
out.println("<p><b>Result: "+(webListenerPrevention.booleanValue()?"<span class=\"pass\">PASS":"<span class=\"fail\">FAIL")+"</span></b></p>");
|
||||
|
||||
out.println("<h2>Invalid Type for Listener Detection</h2>");
|
||||
Boolean badListener = (Boolean)config.getServletContext().getAttribute("com.acme.AnnotationTest.invalidListenerRegoTest");
|
||||
out.println("<p><b>Result: "+(badListener.booleanValue()?"<span class=\"pass\">PASS":"<span class=\"fail\">FAIL")+"</span></b></p>");
|
||||
|
||||
|
||||
out.println("<h2>@PostConstruct Callback</h2>");
|
||||
out.println("<pre>");
|
||||
@ -261,7 +270,7 @@ public class AnnotationTest extends HttpServlet
|
||||
out.println("private void myPostConstructMethod ()");
|
||||
out.println("{}");
|
||||
out.println("</pre>");
|
||||
out.println("<br/><b>Result: "+postConstructResult+"</b>");
|
||||
out.println("<p><b>Result: "+postConstructResult+"</b></p>");
|
||||
|
||||
|
||||
out.println("<h2>@Resource Injection for DataSource</h2>");
|
||||
@ -272,8 +281,8 @@ public class AnnotationTest extends HttpServlet
|
||||
out.println("myDS=ds;");
|
||||
out.println("}");
|
||||
out.println("</pre>");
|
||||
out.println("<br/><b>Result: "+dsResult+"</b>");
|
||||
out.println("<br/><b>JNDI Lookup Result: "+dsLookupResult+"</b>");
|
||||
out.println("<p><b>Result: "+dsResult+"</b>");
|
||||
out.println("<br/><b>JNDI Lookup Result: "+dsLookupResult+"</b></p>");
|
||||
|
||||
|
||||
out.println("<h2>@Resource Injection for env-entry </h2>");
|
||||
@ -283,19 +292,20 @@ public class AnnotationTest extends HttpServlet
|
||||
out.println("@Resource(name=\"minAmount\")");
|
||||
out.println("private Double minAmount;");
|
||||
out.println("</pre>");
|
||||
out.println("<br/><b>Result: "+envResult+": "+(maxAmount.compareTo(new Double(55))==0?" <span class=\"pass\">PASS":" <span class=\"fail\">FAIL")+"</span></b>");
|
||||
out.println("<p><b>Result: "+envResult+": "+(maxAmount.compareTo(new Double(55))==0?" <span class=\"pass\">PASS":" <span class=\"fail\">FAIL")+"</span></b>");
|
||||
out.println("<br/><b>JNDI Lookup Result: "+envLookupResult+"</b>");
|
||||
out.println("<br/><b>Result: "+envResult2+": "+(minAmount.compareTo(new Double("0.99"))==0?" <span class=\"pass\">PASS":" <span class=\"fail\">FAIL")+"</span></b>");
|
||||
out.println("<br/><b>JNDI Lookup Result: "+envLookupResult2+"</b>");
|
||||
out.println("<br/><b>Result: "+envResult3+": "+(avgAmount.compareTo(new Double("1.25"))==0?" <span class=\"pass\">PASS":" <span class=\"fail\">FAIL")+"</span></b>");
|
||||
out.println("<br/><b>JNDI Lookup Result: "+envLookupResult3+"</b>");
|
||||
out.println("<br/><b>JNDI Lookup Result: "+envLookupResult3+"</b></p>");
|
||||
|
||||
out.println("<h2>@Resource Injection for UserTransaction </h2>");
|
||||
out.println("<pre>");
|
||||
out.println("@Resource(mappedName=\"UserTransaction\")");
|
||||
out.println("private UserTransaction myUserTransaction;");
|
||||
out.println("</pre>");
|
||||
out.println("<br/><b>Result: "+txResult+"</b>");
|
||||
out.println("<br/><b>JNDI Lookup Result: "+txLookupResult+"</b>");
|
||||
out.println("<p><b>Result: "+txResult+"</b>");
|
||||
out.println("<br/><b>JNDI Lookup Result: "+txLookupResult+"</b></p>");
|
||||
|
||||
out.println("</body>");
|
||||
out.println("</html>");
|
||||
|
@ -17,6 +17,8 @@
|
||||
//
|
||||
|
||||
package com.acme;
|
||||
import java.util.EventListener;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.ServletContextAttributeEvent;
|
||||
import javax.servlet.ServletContextAttributeListener;
|
||||
@ -38,6 +40,26 @@ import javax.servlet.http.HttpSessionListener;
|
||||
@WebListener
|
||||
public class TestListener implements HttpSessionListener, HttpSessionAttributeListener, HttpSessionActivationListener, ServletContextListener, ServletContextAttributeListener, ServletRequestListener, ServletRequestAttributeListener
|
||||
{
|
||||
public class NaughtyServletContextListener implements ServletContextListener
|
||||
{
|
||||
|
||||
@Override
|
||||
public void contextInitialized(ServletContextEvent sce)
|
||||
{
|
||||
throw new IllegalStateException("Should not call NaughtServletContextListener.contextInitialized");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contextDestroyed(ServletContextEvent sce)
|
||||
{
|
||||
throw new IllegalStateException("Should not call NaughtServletContextListener.contextDestroyed");
|
||||
}
|
||||
}
|
||||
|
||||
public class InvalidListener implements EventListener
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Resource(mappedName="maxAmount")
|
||||
private Double maxAmount;
|
||||
@ -69,7 +91,36 @@ public class TestListener implements HttpSessionListener, HttpSessionAttributeL
|
||||
|
||||
public void contextInitialized(ServletContextEvent sce)
|
||||
{
|
||||
//System.err.println("contextInitialized, maxAmount injected as "+maxAmount);
|
||||
//Can't add a ServletContextListener from a ServletContextListener even if it is declared in web.xml
|
||||
try
|
||||
{
|
||||
sce.getServletContext().addListener(new NaughtyServletContextListener());
|
||||
sce.getServletContext().setAttribute("com.acme.AnnotationTest.sclFromSclRegoTest", Boolean.FALSE);
|
||||
}
|
||||
catch (IllegalArgumentException e)
|
||||
{
|
||||
sce.getServletContext().setAttribute("com.acme.AnnotationTest.sclFromSclRegoTest", Boolean.TRUE);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
sce.getServletContext().setAttribute("com.acme.AnnotationTest.sclFromSclRegoTest", Boolean.FALSE);
|
||||
}
|
||||
|
||||
|
||||
//Can't add an EventListener not part of the specified list for addListener()
|
||||
try
|
||||
{
|
||||
sce.getServletContext().addListener(new InvalidListener());
|
||||
sce.getServletContext().setAttribute("com.acme.AnnotationTest.invalidListenerRegoTest", Boolean.FALSE);
|
||||
}
|
||||
catch (IllegalArgumentException e)
|
||||
{
|
||||
sce.getServletContext().setAttribute("com.acme.AnnotationTest.invalidListenerRegoTest", Boolean.TRUE);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
sce.getServletContext().setAttribute("com.acme.AnnotationTest.invalidListenerRegoTest", Boolean.FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
public void contextDestroyed(ServletContextEvent sce)
|
||||
|
@ -1,6 +1,6 @@
|
||||
body {color: #2E2E2E; font-family:sans-serif; font-size:90%;}
|
||||
h1 {font-variant: small-caps; font-size:130%; letter-spacing: 0.1em;}
|
||||
h2 {font-variant: small-caps; font-size:100%; letter-spacing: 0.1em;}
|
||||
h2 {font-variant: small-caps; font-size:100%; letter-spacing: 0.1em; margin-top:2em;}
|
||||
h3 {font-size:100%; letter-spacing: 0.1em;}
|
||||
|
||||
span.pass { color: green; }
|
||||
|
@ -0,0 +1,7 @@
|
||||
body {color: #2E2E2E; font-family:sans-serif; font-size:90%;}
|
||||
h1 {font-variant: small-caps; font-size:130%; letter-spacing: 0.1em;}
|
||||
h2 {font-variant: small-caps; font-size:100%; letter-spacing: 0.1em; margin-top:2em}
|
||||
h3 {font-size:100%; letter-spacing: 0.1em;}
|
||||
|
||||
span.pass { color: green; }
|
||||
span.fail { color:red; }
|
Loading…
x
Reference in New Issue
Block a user