View Javadoc

1   package com.atlassian.plugin.servlet;
2   
3   import com.atlassian.plugin.Plugin;
4   import com.atlassian.plugin.event.PluginEventManager;
5   import com.atlassian.plugin.servlet.descriptors.ServletContextListenerModuleDescriptorBuilder;
6   import com.atlassian.plugin.servlet.descriptors.ServletContextParamDescriptorBuilder;
7   import com.atlassian.plugin.servlet.descriptors.ServletFilterModuleDescriptor;
8   import com.atlassian.plugin.servlet.descriptors.ServletFilterModuleDescriptorBuilder;
9   import com.atlassian.plugin.servlet.descriptors.ServletModuleDescriptor;
10  import com.atlassian.plugin.servlet.descriptors.ServletModuleDescriptorBuilder;
11  import com.atlassian.plugin.servlet.filter.DelegatingPluginFilter;
12  import com.atlassian.plugin.servlet.filter.FilterLocation;
13  import com.atlassian.plugin.servlet.filter.FilterTestUtils.FilterAdapter;
14  import com.atlassian.plugin.servlet.filter.FilterTestUtils.SoundOffFilter;
15  import com.atlassian.plugin.servlet.filter.IteratingFilterChain;
16  import com.google.common.collect.Iterables;
17  import com.mockobjects.dynamic.C;
18  import com.mockobjects.dynamic.Mock;
19  import junit.framework.TestCase;
20  
21  import javax.servlet.Filter;
22  import javax.servlet.FilterChain;
23  import javax.servlet.FilterConfig;
24  import javax.servlet.ServletConfig;
25  import javax.servlet.ServletContext;
26  import javax.servlet.ServletContextEvent;
27  import javax.servlet.ServletContextListener;
28  import javax.servlet.ServletException;
29  import javax.servlet.ServletRequest;
30  import javax.servlet.ServletResponse;
31  import javax.servlet.http.HttpServlet;
32  import javax.servlet.http.HttpServletRequest;
33  import javax.servlet.http.HttpServletResponse;
34  import java.io.IOException;
35  import java.util.ArrayList;
36  import java.util.Collections;
37  import java.util.Comparator;
38  import java.util.LinkedList;
39  import java.util.List;
40  import java.util.Vector;
41  import java.util.concurrent.atomic.AtomicReference;
42  
43  import static com.atlassian.plugin.servlet.DefaultServletModuleManager.sortedInsert;
44  import static com.atlassian.plugin.servlet.filter.FilterDispatcherCondition.ERROR;
45  import static com.atlassian.plugin.servlet.filter.FilterDispatcherCondition.FORWARD;
46  import static com.atlassian.plugin.servlet.filter.FilterDispatcherCondition.INCLUDE;
47  import static com.atlassian.plugin.servlet.filter.FilterDispatcherCondition.REQUEST;
48  import static com.atlassian.plugin.servlet.filter.FilterTestUtils.emptyChain;
49  import static org.mockito.Mockito.mock;
50  import static org.mockito.Mockito.when;
51  
52  public class TestDefaultServletModuleManager extends TestCase
53  {
54      ServletModuleManager servletModuleManager;
55      
56      Mock mockPluginEventManager;
57  
58      public void setUp()
59      {
60          mockPluginEventManager = new Mock(PluginEventManager.class);
61          mockPluginEventManager.expect("register", C.anyArgs(1));
62          servletModuleManager = new DefaultServletModuleManager((PluginEventManager) mockPluginEventManager.proxy());
63      }
64      
65      public void testSortedInsertInsertsDistinctElementProperly()
66      {
67          List<String> list = newList("cat", "dog", "fish", "monkey");
68          List<String> endList = newList("cat", "dog", "elephant", "fish", "monkey");
69          sortedInsert(list, "elephant", naturalOrder(String.class));
70          assertEquals(endList, list); 
71      }
72      
73      public void testSortedInsertInsertsNonDistinctElementProperly()
74      {
75          List<WeightedValue> list = newList
76          (
77              new WeightedValue(10, "dog"), new WeightedValue(20, "monkey"), new WeightedValue(20, "tiger"),
78              new WeightedValue(30, "fish"), new WeightedValue(100, "cat")
79          );
80          List<WeightedValue> endList = newList
81          (
82              new WeightedValue(10, "dog"), new WeightedValue(20, "monkey"), new WeightedValue(20, "tiger"),
83              new WeightedValue(20, "elephant"), new WeightedValue(30, "fish"), new WeightedValue(100, "cat")
84          );
85          sortedInsert(list, new WeightedValue(20, "elephant"), WeightedValue.byWeight);
86          assertEquals(endList, list); 
87      }
88      
89      public void testGettingServletWithSimplePath() throws Exception
90      {
91          Mock mockServletContext = new Mock(ServletContext.class);
92          mockServletContext.expectAndReturn("getInitParameterNames", Collections.enumeration(Collections.emptyList()));
93          mockServletContext.expect("log", C.ANY_ARGS);
94          Mock mockServletConfig = new Mock(ServletConfig.class);
95          mockServletConfig.expectAndReturn("getServletContext", mockServletContext.proxy());
96          
97          Mock mockHttpServletRequest = new Mock(HttpServletRequest.class);
98          mockHttpServletRequest.expectAndReturn("getPathInfo", "/servlet");
99          Mock mockHttpServletResponse = new Mock(HttpServletResponse.class);
100         
101         TestHttpServlet servlet = new TestHttpServlet();
102         ServletModuleDescriptor descriptor = new ServletModuleDescriptorBuilder()
103             .with(servlet)
104             .withPath("/servlet")
105             .with(servletModuleManager)
106             .build();
107         
108         servletModuleManager.addServletModule(descriptor);
109         
110         HttpServlet wrappedServlet = servletModuleManager.getServlet("/servlet", (ServletConfig) mockServletConfig.proxy());
111         wrappedServlet.service((HttpServletRequest) mockHttpServletRequest.proxy(), (HttpServletResponse) mockHttpServletResponse.proxy());
112         assertTrue(servlet.serviceCalled);
113     }
114 
115     public void testGettingServlet()
116     {
117         getServletTwice(false);
118     }
119 
120     private void getServletTwice(boolean expectNewServletEachCall)
121     {
122         mockPluginEventManager.expect("register", C.anyArgs(1));
123         DefaultServletModuleManager mgr = new DefaultServletModuleManager((PluginEventManager) mockPluginEventManager.proxy());
124 
125         AtomicReference<HttpServlet> servletRef = new AtomicReference<HttpServlet>();
126         TestHttpServlet firstServlet = new TestHttpServlet();
127         servletRef.set(firstServlet);
128         ServletModuleDescriptor descriptor = new ServletModuleDescriptorBuilder()
129             .withFactory(ObjectFactories.createMutable(servletRef))
130             .withPath("/servlet")
131             .with(mgr)
132             .build();
133 
134         final ServletConfig servletConfig = mock(ServletConfig.class);
135         final ServletContext servletContext = mock(ServletContext.class);
136         when(servletContext.getInitParameterNames()).thenReturn(Collections.<String>enumeration(Collections.<String>emptyList()));
137         when(servletConfig.getServletContext()).thenReturn(servletContext);
138 
139         assertTrue(firstServlet == ((DelegatingPluginServlet)mgr.getServlet(descriptor, servletConfig)).getDelegatingServlet());
140 
141         TestHttpServlet secondServlet = new TestHttpServlet();
142         servletRef.set(secondServlet);
143         HttpServlet expectedServlet = (expectNewServletEachCall ? secondServlet : firstServlet);
144         assertTrue(expectedServlet == ((DelegatingPluginServlet)mgr.getServlet(descriptor, servletConfig)).getDelegatingServlet());
145     }
146 
147     public void testGettingFilter()
148     {
149         getFilterTwice(false);
150     }
151 
152     private void getFilterTwice(boolean expectNewFilterEachCall)
153     {
154         mockPluginEventManager.expect("register", C.anyArgs(1));
155         DefaultServletModuleManager mgr = new DefaultServletModuleManager((PluginEventManager) mockPluginEventManager.proxy());
156 
157         AtomicReference<Filter> filterRef = new AtomicReference<Filter>();
158         TestHttpFilter firstFilter = new TestHttpFilter();
159         filterRef.set(firstFilter);
160         ServletFilterModuleDescriptor descriptor = new ServletFilterModuleDescriptorBuilder()
161             .withFactory(ObjectFactories.createMutable(filterRef))
162             .withPath("/servlet")
163             .with(mgr)
164             .build();
165 
166         final FilterConfig filterConfig = mock(FilterConfig.class);
167         final ServletContext servletContext = mock(ServletContext.class);
168         when(servletContext.getInitParameterNames()).thenReturn(Collections.<String>enumeration(Collections.<String>emptyList()));
169         when(filterConfig.getServletContext()).thenReturn(servletContext);
170 
171         assertTrue(firstFilter == ((DelegatingPluginFilter)mgr.getFilter(descriptor, filterConfig)).getDelegatingFilter());
172 
173         TestHttpFilter secondFilter = new TestHttpFilter();
174         filterRef.set(secondFilter);
175         Filter expectedFilter = (expectNewFilterEachCall ? secondFilter : firstFilter);
176         assertTrue(expectedFilter == ((DelegatingPluginFilter)mgr.getFilter(descriptor, filterConfig)).getDelegatingFilter());
177     }
178 
179     public void testGettingServletWithException() throws Exception
180     {
181         Mock mockServletContext = new Mock(ServletContext.class);
182         mockServletContext.expectAndReturn("getInitParameterNames", Collections.enumeration(Collections.emptyList()));
183         mockServletContext.expect("log", C.ANY_ARGS);
184         Mock mockServletConfig = new Mock(ServletConfig.class);
185         mockServletConfig.expectAndReturn("getServletContext", mockServletContext.proxy());
186 
187         Mock mockHttpServletRequest = new Mock(HttpServletRequest.class);
188         mockHttpServletRequest.expectAndReturn("getPathInfo", "/servlet");
189         Mock mockHttpServletResponse = new Mock(HttpServletResponse.class);
190 
191         TestHttpServletWithException servlet = new TestHttpServletWithException();
192         ServletModuleDescriptor descriptor = new ServletModuleDescriptorBuilder()
193             .with(servlet)
194             .withPath("/servlet")
195             .with(servletModuleManager)
196             .build();
197 
198         servletModuleManager.addServletModule(descriptor);
199 
200         assertNull(servletModuleManager.getServlet("/servlet", (ServletConfig) mockServletConfig.proxy()));
201     }
202 
203     public void testGettingFilterWithException() throws Exception
204     {
205         Mock mockServletContext = new Mock(ServletContext.class);
206         mockServletContext.expectAndReturn("getInitParameterNames", Collections.enumeration(Collections.emptyList()));
207         mockServletContext.expect("log", C.ANY_ARGS);
208         Mock mockFilterConfig = new Mock(FilterConfig.class);
209         mockFilterConfig.expectAndReturn("getServletContext", mockServletContext.proxy());
210 
211         Mock mockHttpServletRequest = new Mock(HttpServletRequest.class);
212         mockHttpServletRequest.expectAndReturn("getPathInfo", "/servlet");
213 
214         TestFilterWithException servlet = new TestFilterWithException();
215         ServletFilterModuleDescriptor descriptor = new ServletFilterModuleDescriptorBuilder()
216             .with(servlet)
217             .withPath("/servlet")
218             .with(servletModuleManager)
219             .at(FilterLocation.AFTER_ENCODING)
220             .build();
221 
222         servletModuleManager.addFilterModule(descriptor);
223 
224         assertEquals(false, servletModuleManager.getFilters(FilterLocation.AFTER_ENCODING, "/servlet", (FilterConfig) mockFilterConfig.proxy()).iterator().hasNext());
225     }
226     
227     public void testGettingServletWithComplexPath() throws Exception
228     {
229         Mock mockServletContext = new Mock(ServletContext.class);
230         mockServletContext.expectAndReturn("getInitParameterNames", Collections.enumeration(Collections.emptyList()));
231         mockServletContext.expect("log", C.ANY_ARGS);
232         Mock mockServletConfig = new Mock(ServletConfig.class);
233         mockServletConfig.expectAndReturn("getServletContext", mockServletContext.proxy());
234         
235         Mock mockHttpServletRequest = new Mock(HttpServletRequest.class);
236         mockHttpServletRequest.expectAndReturn("getPathInfo", "/servlet");
237         Mock mockHttpServletResponse = new Mock(HttpServletResponse.class);
238         
239         TestHttpServlet servlet = new TestHttpServlet();
240         ServletModuleDescriptor descriptor = new ServletModuleDescriptorBuilder()
241             .with(servlet)
242             .withPath("/servlet/*")
243             .with(servletModuleManager)
244             .build();
245         
246         servletModuleManager.addServletModule(descriptor);
247         
248         HttpServlet wrappedServlet = servletModuleManager.getServlet("/servlet/this/is/a/test", (ServletConfig) mockServletConfig.proxy());
249         wrappedServlet.service((HttpServletRequest) mockHttpServletRequest.proxy(), (HttpServletResponse) mockHttpServletResponse.proxy());
250         assertTrue(servlet.serviceCalled);
251     }
252 
253     public void testMultipleFitlersWithTheSameComplexPath() throws ServletException
254     {
255         ServletContext servletContext = mock(ServletContext.class);
256         FilterConfig filterConfig = mock(FilterConfig.class);
257         when(filterConfig.getServletContext()).thenReturn(servletContext);
258         when(servletContext.getInitParameterNames()).thenReturn(new Vector().elements());
259         Plugin plugin = new PluginBuilder().build();
260         ServletFilterModuleDescriptor filterDescriptor = new ServletFilterModuleDescriptorBuilder()
261             .with(plugin)
262             .withKey("foo")
263             .with(new FilterAdapter())
264             .withPath("/foo/*")
265             .with(servletModuleManager)
266             .build();
267 
268         ServletFilterModuleDescriptor filterDescriptor2 = new ServletFilterModuleDescriptorBuilder()
269             .with(plugin)
270             .withKey("bar")
271             .with(new FilterAdapter())
272             .withPath("/foo/*")
273             .with(servletModuleManager)
274             .build();
275         servletModuleManager.addFilterModule(filterDescriptor);
276         servletModuleManager.addFilterModule(filterDescriptor2);
277 
278         servletModuleManager.removeFilterModule(filterDescriptor);
279         assertTrue(servletModuleManager.getFilters(FilterLocation.BEFORE_DISPATCH, "/foo/jim", filterConfig).iterator().hasNext());
280     }
281 
282     public void testMultipleFitlersWithTheSameSimplePath() throws ServletException
283     {
284         ServletContext servletContext = mock(ServletContext.class);
285         FilterConfig filterConfig = mock(FilterConfig.class);
286         when(filterConfig.getServletContext()).thenReturn(servletContext);
287         when(servletContext.getInitParameterNames()).thenReturn(new Vector().elements());
288         Plugin plugin = new PluginBuilder().build();
289         ServletFilterModuleDescriptor filterDescriptor = new ServletFilterModuleDescriptorBuilder()
290             .with(plugin)
291             .withKey("foo")
292             .with(new FilterAdapter())
293             .withPath("/foo")
294             .with(servletModuleManager)
295             .build();
296 
297         ServletFilterModuleDescriptor filterDescriptor2 = new ServletFilterModuleDescriptorBuilder()
298             .with(plugin)
299             .withKey("bar")
300             .with(new FilterAdapter())
301             .withPath("/foo")
302             .with(servletModuleManager)
303             .build();
304         servletModuleManager.addFilterModule(filterDescriptor);
305         servletModuleManager.addFilterModule(filterDescriptor2);
306 
307         servletModuleManager.removeFilterModule(filterDescriptor);
308         assertTrue(servletModuleManager.getFilters(FilterLocation.BEFORE_DISPATCH, "/foo", filterConfig).iterator().hasNext());
309     }
310     
311     public void testPluginContextInitParamsGetMerged() throws Exception
312     {
313         Mock mockServletContext = new Mock(ServletContext.class);
314         mockServletContext.expectAndReturn("getInitParameterNames", Collections.enumeration(Collections.emptyList()));
315         mockServletContext.expect("log", C.ANY_ARGS);
316         Mock mockServletConfig = new Mock(ServletConfig.class);
317         mockServletConfig.expectAndReturn("getServletContext", mockServletContext.proxy());
318 
319         Plugin plugin = new PluginBuilder().build();
320 
321         new ServletContextParamDescriptorBuilder()
322             .with(plugin)
323             .withParam("param.name", "param.value")
324             .build();
325 
326         // a servlet that will check for param.name to be in the servlet context
327         ServletModuleDescriptor servletDescriptor = new ServletModuleDescriptorBuilder()
328             .with(plugin)
329             .with(new TestHttpServlet()
330             {
331                 @Override
332                 public void init(ServletConfig servletConfig)
333                 {
334                     assertEquals("param.value", servletConfig.getServletContext().getInitParameter("param.name"));
335                 }
336             })
337             .withPath("/servlet")
338             .with(servletModuleManager)
339             .build();
340         servletModuleManager.addServletModule(servletDescriptor);
341         
342         servletModuleManager.getServlet("/servlet", (ServletConfig) mockServletConfig.proxy());
343     }
344     
345     public void testServletListenerContextInitializedIsCalled() throws Exception
346     {
347         Mock mockServletContext = new Mock(ServletContext.class);
348         mockServletContext.expectAndReturn("getInitParameterNames", Collections.enumeration(Collections.emptyList()));
349         mockServletContext.expect("log", C.ANY_ARGS);
350         Mock mockServletConfig = new Mock(ServletConfig.class);
351         mockServletConfig.expectAndReturn("getServletContext", mockServletContext.proxy());
352         
353         final TestServletContextListener listener = new TestServletContextListener();
354         
355         Plugin plugin = new PluginBuilder().build();
356         
357         new ServletContextListenerModuleDescriptorBuilder()
358             .with(plugin)
359             .with(listener)
360             .build();
361         
362         ServletModuleDescriptor servletDescriptor = new ServletModuleDescriptorBuilder()
363             .with(plugin)
364             .with(new TestHttpServlet())
365             .withPath("/servlet")
366             .with(servletModuleManager)
367             .build();
368         
369         servletModuleManager.addServletModule(servletDescriptor);
370         servletModuleManager.getServlet("/servlet", (ServletConfig) mockServletConfig.proxy());
371         assertTrue(listener.initCalled);
372     }
373     
374     public void testServletListenerContextFilterAndServletUseTheSameServletContext() throws Exception
375     {
376         Plugin plugin = new PluginBuilder().build();
377 
378         final AtomicReference<ServletContext> contextRef = new AtomicReference<ServletContext>();
379         // setup a context listener to capture the context
380         new ServletContextListenerModuleDescriptorBuilder()
381             .with(plugin)
382             .with(new TestServletContextListener()
383             {
384                 @Override
385                 public void contextInitialized(ServletContextEvent event)
386                 {
387                     contextRef.set(event.getServletContext());
388                 }
389             })
390             .build();
391         
392         // a servlet that checks that the context is the same for it as it was for the context listener
393         ServletModuleDescriptor servletDescriptor = new ServletModuleDescriptorBuilder()
394             .with(plugin)
395             .with(new TestHttpServlet()
396             {
397                 @Override
398                 public void init(ServletConfig servletConfig)
399                 {
400                     assertSame(contextRef.get(), servletConfig.getServletContext());
401                 }
402             })
403             .withPath("/servlet")
404             .with(servletModuleManager)
405             .build();
406         servletModuleManager.addServletModule(servletDescriptor);
407         
408         // a filter that checks that the context is the same for it as it was for the context listener
409         ServletFilterModuleDescriptor filterDescriptor = new ServletFilterModuleDescriptorBuilder()
410             .with(plugin)
411             .with(new FilterAdapter()
412             {
413                 @Override
414                 public void init(FilterConfig filterConfig)
415                 {
416                     assertSame(contextRef.get(), filterConfig.getServletContext());
417                 }
418             })
419             .withPath("/*")
420             .with(servletModuleManager)
421             .build();
422         servletModuleManager.addFilterModule(filterDescriptor);
423         
424         Mock mockServletContext = new Mock(ServletContext.class);
425         mockServletContext.expectAndReturn("getInitParameterNames", Collections.enumeration(Collections.emptyList()));
426         mockServletContext.expect("log", C.ANY_ARGS);
427 
428         // get a servlet, this will initialize the servlet context for the first time in addition to the servlet itself.
429         // if the servlet doesn't get the same context as the context listener did, the assert will fail
430         Mock mockServletConfig = new Mock(ServletConfig.class);
431         mockServletConfig.expectAndReturn("getServletContext", mockServletContext.proxy());
432         servletModuleManager.getServlet("/servlet", (ServletConfig) mockServletConfig.proxy());
433         
434         // get the filters, if the filter doesn't get the same context as the context listener did, the assert will fail
435         Mock mockFilterConfig = new Mock(FilterConfig.class);
436         mockFilterConfig.expectAndReturn("getServletContext", mockServletContext.proxy());
437         servletModuleManager.getFilters(FilterLocation.BEFORE_DISPATCH, "/servlet", (FilterConfig) mockFilterConfig.proxy());
438     }
439     
440     public void testFiltersWithSameLocationAndWeightInTheSamePluginAppearInTheOrderTheyAreDeclared() throws Exception
441     {
442         Mock mockServletContext = new Mock(ServletContext.class);
443         mockServletContext.matchAndReturn("getInitParameterNames", Collections.enumeration(Collections.emptyList()));
444         mockServletContext.expect("log", C.ANY_ARGS);
445         Mock mockFilterConfig = new Mock(FilterConfig.class);
446         mockFilterConfig.matchAndReturn("getServletContext", mockServletContext.proxy());
447 
448         Plugin plugin = new PluginBuilder().build();
449         
450         List<Integer> filterCallOrder = new LinkedList<Integer>();
451         ServletFilterModuleDescriptor d1 = new ServletFilterModuleDescriptorBuilder()
452             .with(plugin)
453             .withKey("filter-1")
454             .with(new SoundOffFilter(filterCallOrder, 1))
455             .withPath("/*")
456             .build();
457         servletModuleManager.addFilterModule(d1);
458         
459         ServletFilterModuleDescriptor d2 = new ServletFilterModuleDescriptorBuilder()
460             .with(plugin)
461             .withKey("filter-2")
462             .with(new SoundOffFilter(filterCallOrder, 2))
463             .withPath("/*")
464             .build();
465         servletModuleManager.addFilterModule(d2);
466         
467         Mock mockHttpServletRequest = new Mock(HttpServletRequest.class);
468         mockHttpServletRequest.matchAndReturn("getPathInfo", "/servlet");
469         Mock mockHttpServletResponse = new Mock(HttpServletResponse.class);
470         
471         Iterable<Filter> filters = servletModuleManager.getFilters(FilterLocation.BEFORE_DISPATCH, "/some/path", (FilterConfig) mockFilterConfig.proxy());
472         FilterChain chain = new IteratingFilterChain(filters.iterator(), emptyChain);
473         
474         chain.doFilter((HttpServletRequest) mockHttpServletRequest.proxy(), (HttpServletResponse) mockHttpServletResponse.proxy());
475         assertEquals(newList(1, 2, 2, 1), filterCallOrder);
476     }
477 
478     public void testGetFiltersWithDispatcher() throws Exception {
479         ServletContext servletContext = mock(ServletContext.class);
480         FilterConfig filterConfig = mock(FilterConfig.class);
481         when(filterConfig.getServletContext()).thenReturn(servletContext);
482         when(servletContext.getInitParameterNames()).thenReturn(new Vector().elements());
483         Plugin plugin = new PluginBuilder().build();
484 
485         ServletFilterModuleDescriptor filterDescriptor = new ServletFilterModuleDescriptorBuilder()
486             .with(plugin)
487             .withKey("foo")
488             .with(new FilterAdapter())
489             .withPath("/foo")
490             .with(servletModuleManager)
491             .withDispatcher(REQUEST)
492             .withDispatcher(FORWARD)
493             .build();
494 
495         ServletFilterModuleDescriptor filterDescriptor2 = new ServletFilterModuleDescriptorBuilder()
496             .with(plugin)
497             .withKey("bar")
498             .with(new FilterAdapter())
499             .withPath("/foo")
500             .with(servletModuleManager)
501             .withDispatcher(REQUEST)
502             .withDispatcher(INCLUDE)
503             .build();
504         
505         servletModuleManager.addFilterModule(filterDescriptor);
506         servletModuleManager.addFilterModule(filterDescriptor2);
507 
508         assertEquals(2, Iterables.size(servletModuleManager.getFilters(FilterLocation.BEFORE_DISPATCH, "/foo", filterConfig, REQUEST)));
509         assertEquals(1, Iterables.size(servletModuleManager.getFilters(FilterLocation.BEFORE_DISPATCH, "/foo", filterConfig, INCLUDE)));
510         assertEquals(1, Iterables.size(servletModuleManager.getFilters(FilterLocation.BEFORE_DISPATCH, "/foo", filterConfig, FORWARD)));
511         assertEquals(0, Iterables.size(servletModuleManager.getFilters(FilterLocation.BEFORE_DISPATCH, "/foo", filterConfig, ERROR)));
512 
513         try
514         {
515             servletModuleManager.getFilters(FilterLocation.BEFORE_DISPATCH, "/foo", filterConfig, null);
516             fail("Shouldn't accept nulls");
517         }
518         catch (NullPointerException ex)
519         {
520             // this is good
521         }
522     }
523 
524     static class TestServletContextListener implements ServletContextListener
525     {
526         boolean initCalled = false;
527         
528         public void contextInitialized(ServletContextEvent event)
529         {
530             initCalled = true;
531         }
532 
533         public void contextDestroyed(ServletContextEvent event) {}
534     }
535     
536     static class TestHttpServlet extends HttpServlet
537     {
538         boolean serviceCalled = false;
539         
540         @Override
541         public void service(ServletRequest request, ServletResponse response)
542         {
543             serviceCalled = true;
544         }
545     }
546 
547     static class TestHttpServletWithException extends HttpServlet
548     {
549         @Override
550         public void init(ServletConfig servletConfig) throws ServletException
551         {
552             throw new RuntimeException("exception thrown");
553         }
554     }
555 
556     static class TestFilterWithException implements Filter
557     {
558         public void init(FilterConfig filterConfig) throws ServletException
559         {
560             throw new RuntimeException("exception thrown");
561         }
562 
563         public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException
564         {
565         }
566 
567         public void destroy()
568         {
569         }
570     }
571 
572     static class TestHttpFilter implements Filter
573     {
574         public void init(FilterConfig filterConfig) throws ServletException
575         {
576         }
577 
578         public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException
579         {
580         }
581 
582         public void destroy()
583         {
584         }
585     }
586 
587     static final class WeightedValue
588     {
589         final int weight;
590         final String value;
591         
592         WeightedValue(int weight, String value)
593         {
594             this.weight = weight;
595             this.value = value;
596         }
597         
598         @Override
599         public boolean equals(Object o)
600         {
601             if (this == o)
602                 return true;
603             if (!(o instanceof WeightedValue))
604                 return false;
605             WeightedValue rhs = (WeightedValue) o;
606             return weight == rhs.weight && value.equals(rhs.value);
607         }
608         
609         @Override
610         public String toString()
611         {
612             return "[" + weight + ", " + value + "]";
613         }
614         
615         static final Comparator<WeightedValue> byWeight = new Comparator<WeightedValue>()
616         {
617             public int compare(WeightedValue o1, WeightedValue o2)
618             {
619                 return Integer.valueOf(o1.weight).compareTo(o2.weight);
620             }
621         };
622     }
623     
624     static <T> List<T> newList(T... elements)
625     {
626         List<T> list = new ArrayList<T>();
627         for (T e : elements)
628         {
629             list.add(e);
630         }
631         return list;
632     }
633     
634     static <T extends Comparable<T>> Comparator<T> naturalOrder(Class<T> type)
635     {
636         return new Comparator<T>()
637         {
638             public int compare(T o1, T o2)
639             {
640                 return o1.compareTo(o2);
641             }
642         };
643     }    
644 }