View Javadoc

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