1   package com.atlassian.plugins.rest.module.filter;
2   
3   import com.sun.jersey.core.util.MultivaluedMapImpl;
4   import com.sun.jersey.spi.container.ContainerRequest;
5   import static org.junit.Assert.*;
6   import org.junit.Before;
7   import org.junit.Test;
8   import org.mockito.ArgumentMatcher;
9   import org.mockito.Matchers;
10  import org.mockito.Mock;
11  import static org.mockito.Mockito.*;
12  import org.mockito.MockitoAnnotations;
13  
14  import javax.ws.rs.core.MediaType;
15  import javax.ws.rs.core.MultivaluedMap;
16  import java.net.URI;
17  import java.util.Collections;
18  import java.util.List;
19  import java.util.Map;
20  
21  
22  public class ExtensionJerseyFilterTest
23  {
24      private static final String ACCEPT_HEADER = "Accept";
25  
26      @Mock
27      private ContainerRequest containerRequest;
28  
29      private ExtensionJerseyFilter jerseyFilter;
30  
31      @Before
32      public void setUp()
33      {
34          MockitoAnnotations.initMocks(this);
35          jerseyFilter = new ExtensionJerseyFilter(Collections.singletonList("/excluded.*"));
36      }
37  
38      @Test
39      public void testFilterWithoutQueryParameters() throws Exception
40      {
41          testFilter(new MultivaluedMapImpl());
42      }
43  
44      @Test
45      public void testFilterWithQueryParameters() throws Exception
46      {
47          final MultivaluedMap<String, String> parameters = new MultivaluedMapImpl();
48          parameters.add("param1", "value1");
49          parameters.add("param2", "value2.1");
50          parameters.add("param2", "value2.2");
51          testFilter(parameters);
52      }
53  
54      @Test
55      public void testDoNotFilterWhenExtensionNotMatched() throws Exception
56      {
57          testDoNotFilter("resource.myextension");
58      }
59  
60      @Test
61      public void testDoNotFilterWhenNoExtension() throws Exception
62      {
63          testDoNotFilter("resource");
64      }
65  
66      @Test
67      public void testDoNotFilterWhenExcluded() throws Exception
68      {
69          testDoNotFilter("excluded/resource.json");
70      }
71  
72      private void testFilter(MultivaluedMap<String, String> queryParameters) throws Exception
73      {
74          final MultivaluedMapImpl headers = new MultivaluedMapImpl();
75          final URI baseUri = new URI("http://localhost:8080/rest");
76  
77          when(containerRequest.getAbsolutePath()).thenReturn(new URI("http://localhost:8080/rest/application.json"));
78          when(containerRequest.getBaseUri()).thenReturn(baseUri);
79          when(containerRequest.getRequestHeaders()).thenReturn(headers);
80          when(containerRequest.getQueryParameters()).thenReturn(queryParameters);
81  
82          jerseyFilter.filter(containerRequest);
83  
84          final List<String> acceptHeader = headers.get(ACCEPT_HEADER);
85          assertEquals(1, acceptHeader.size());
86          assertEquals(MediaType.APPLICATION_JSON, acceptHeader.get(0));
87  
88          verify(containerRequest).setUris(eq(baseUri), argThat(new UriMatcher(new URI("http://localhost:8080/rest/application"), queryParameters)));
89      }
90  
91      private void testDoNotFilter(String resourceName) throws Exception
92      {
93          final String baseUri = "http://localhost:8080/rest/";
94  
95          when(containerRequest.getBaseUri()).thenReturn(new URI(baseUri));
96          when(containerRequest.getAbsolutePath()).thenReturn(new URI(baseUri + resourceName));
97  
98          jerseyFilter.filter(containerRequest);
99  
100         verify(containerRequest, never()).getRequestHeaders();
101         verify(containerRequest, never()).setUris(Matchers.<URI>anyObject(), Matchers.<URI>anyObject());
102     }
103 
104     private static class UriMatcher extends ArgumentMatcher<URI>
105     {
106         private final URI requestUri;
107         private final MultivaluedMap<String, String> parameters;
108 
109         UriMatcher(URI requestUri, MultivaluedMap<String, String> parameters)
110         {
111             this.requestUri = requestUri;
112             this.parameters = parameters;
113         }
114 
115         public boolean matches(Object actual)
116         {
117             final URI uri = (URI) actual;
118 
119             if (!actual.toString().startsWith(requestUri.toString()))
120             {
121                 return false;
122             }
123 
124             // check query parameters
125             final String queryParametersString = '&' + uri.getQuery() + '&';
126             for (Map.Entry<String, List<String>> queryParameter : parameters.entrySet())
127             {
128                 for (String value : queryParameter.getValue())
129                 {
130                     if (!queryParametersString.contains('&' + queryParameter.getKey() + '=' + value + '&'))
131                     {
132                         return false;
133                     }
134                 }
135             }
136             return true;
137         }
138     }
139 }