• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (C) 2008 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.inject.servlet;
18 
19 import static com.google.inject.servlet.ManagedServletPipeline.REQUEST_DISPATCHER_REQUEST;
20 import static org.easymock.EasyMock.anyObject;
21 import static org.easymock.EasyMock.createMock;
22 import static org.easymock.EasyMock.expect;
23 import static org.easymock.EasyMock.replay;
24 import static org.easymock.EasyMock.verify;
25 
26 import com.google.common.collect.Sets;
27 import com.google.inject.Binding;
28 import com.google.inject.Injector;
29 import com.google.inject.Key;
30 import com.google.inject.spi.BindingScopingVisitor;
31 
32 import junit.framework.TestCase;
33 
34 import java.io.IOException;
35 import java.util.HashMap;
36 
37 import javax.servlet.ServletException;
38 import javax.servlet.http.HttpServlet;
39 import javax.servlet.http.HttpServletRequest;
40 import javax.servlet.http.HttpServletResponse;
41 
42 /**
43  * Ensures servlet spec compliance for CGI-style variables and general
44  *  path/pattern matching.
45  *
46  * @author Dhanji R. Prasanna (dhanji@gmail com)
47  */
48 public class ServletDefinitionPathsTest extends TestCase {
49 
50   // Data-driven test.
testServletPathMatching()51   public final void testServletPathMatching() throws IOException, ServletException {
52     servletPath("/index.html", "*.html", "/index.html");
53     servletPath("/somewhere/index.html", "*.html", "/somewhere/index.html");
54     servletPath("/somewhere/index.html", "/*", "");
55     servletPath("/index.html", "/*", "");
56     servletPath("/", "/*", "");
57     servletPath("//", "/*", "");
58     servletPath("/////", "/*", "");
59     servletPath("", "/*", "");
60     servletPath("/thing/index.html", "/thing/*", "/thing");
61     servletPath("/thing/wing/index.html", "/thing/*", "/thing");
62   }
63 
servletPath(final String requestPath, String mapping, final String expectedServletPath)64   private void servletPath(final String requestPath, String mapping,
65       final String expectedServletPath) throws IOException, ServletException {
66 
67     Injector injector = createMock(Injector.class);
68     Binding binding = createMock(Binding.class);
69     HttpServletRequest request = createMock(HttpServletRequest.class);
70     HttpServletResponse response = createMock(HttpServletResponse.class);
71 
72     expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject()))
73         .andReturn(true);
74     expect(injector.getBinding(Key.get(HttpServlet.class)))
75         .andReturn(binding);
76 
77     final boolean[] run = new boolean[1];
78     //get an instance of this servlet
79     expect(injector.getInstance(Key.get(HttpServlet.class)))
80         .andReturn(new HttpServlet() {
81 
82           @Override
83           protected void service(HttpServletRequest servletRequest,
84               HttpServletResponse httpServletResponse) throws ServletException, IOException {
85 
86             final String path = servletRequest.getServletPath();
87             assertEquals(String.format("expected [%s] but was [%s]", expectedServletPath, path),
88                 expectedServletPath, path);
89             run[0] = true;
90           }
91         });
92 
93     expect(request.getServletPath())
94         .andReturn(requestPath);
95 
96     replay(injector, binding, request);
97 
98     ServletDefinition servletDefinition = new ServletDefinition(mapping, Key.get(HttpServlet.class),
99         UriPatternType.get(UriPatternType.SERVLET, mapping), new HashMap<String, String>(), null);
100 
101     servletDefinition.init(null, injector, Sets.<HttpServlet>newIdentityHashSet());
102     servletDefinition.doService(request, response);
103 
104     assertTrue("Servlet did not run!", run[0]);
105 
106     verify(injector, binding, request);
107 
108   }
109 
110   // Data-driven test.
testPathInfoWithServletStyleMatching()111   public final void testPathInfoWithServletStyleMatching() throws IOException, ServletException {
112     pathInfoWithServletStyleMatching("/path/index.html", "/path", "/*", "/index.html", "");
113     pathInfoWithServletStyleMatching("/path//hulaboo///index.html", "/path", "/*",
114         "/hulaboo/index.html", "");
115     pathInfoWithServletStyleMatching("/path/", "/path", "/*", "/", "");
116     pathInfoWithServletStyleMatching("/path////////", "/path", "/*", "/", "");
117 
118     // a servlet mapping of /thing/*
119     pathInfoWithServletStyleMatching("/path/thing////////", "/path", "/thing/*", "/", "/thing");
120     pathInfoWithServletStyleMatching("/path/thing/stuff", "/path", "/thing/*", "/stuff", "/thing");
121     pathInfoWithServletStyleMatching("/path/thing/stuff.html", "/path", "/thing/*", "/stuff.html",
122         "/thing");
123     pathInfoWithServletStyleMatching("/path/thing", "/path", "/thing/*", null, "/thing");
124 
125     // see external issue 372
126     pathInfoWithServletStyleMatching("/path/some/path/of.jsp", "/path", "/thing/*",
127         null, "/some/path/of.jsp");
128 
129     // *.xx style mapping
130     pathInfoWithServletStyleMatching("/path/thing.thing", "/path", "*.thing", null, "/thing.thing");
131     pathInfoWithServletStyleMatching("/path///h.thing", "/path", "*.thing", null, "/h.thing");
132     pathInfoWithServletStyleMatching("/path///...//h.thing", "/path", "*.thing", null,
133         "/.../h.thing");
134     pathInfoWithServletStyleMatching("/path/my/h.thing", "/path", "*.thing", null, "/my/h.thing");
135 
136     // Encoded URLs
137     pathInfoWithServletStyleMatching("/path/index%2B.html", "/path", "/*", "/index+.html", "");
138     pathInfoWithServletStyleMatching("/path/a%20file%20with%20spaces%20in%20name.html", "/path", "/*", "/a file with spaces in name.html", "");
139     pathInfoWithServletStyleMatching("/path/Tam%C3%A1s%20nem%20m%C3%A1s.html", "/path", "/*", "/Tamás nem más.html", "");
140   }
141 
pathInfoWithServletStyleMatching(final String requestUri, final String contextPath, String mapping, final String expectedPathInfo, final String servletPath)142   private void pathInfoWithServletStyleMatching(final String requestUri, final String contextPath,
143       String mapping, final String expectedPathInfo, final String servletPath)
144       throws IOException, ServletException {
145 
146     Injector injector = createMock(Injector.class);
147     Binding binding = createMock(Binding.class);
148     HttpServletRequest request = createMock(HttpServletRequest.class);
149     HttpServletResponse response = createMock(HttpServletResponse.class);
150 
151     expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject()))
152         .andReturn(true);
153     expect(injector.getBinding(Key.get(HttpServlet.class)))
154         .andReturn(binding);
155 
156     final boolean[] run = new boolean[1];
157     //get an instance of this servlet
158     expect(injector.getInstance(Key.get(HttpServlet.class)))
159         .andReturn(new HttpServlet() {
160 
161           @Override
162           protected void service(HttpServletRequest servletRequest,
163               HttpServletResponse httpServletResponse) throws ServletException, IOException {
164 
165             final String path = servletRequest.getPathInfo();
166 
167             if (null == expectedPathInfo) {
168               assertNull(String.format("expected [%s] but was [%s]", expectedPathInfo, path),
169                   path);
170             }
171             else {
172               assertEquals(String.format("expected [%s] but was [%s]", expectedPathInfo, path),
173                   expectedPathInfo, path);
174             }
175 
176             //assert memoizer
177             //noinspection StringEquality
178             assertSame("memo field did not work", path, servletRequest.getPathInfo());
179 
180             run[0] = true;
181           }
182         });
183 
184     expect(request.getRequestURI())
185         .andReturn(requestUri);
186 
187     expect(request.getServletPath())
188         .andReturn(servletPath)
189         .anyTimes();
190 
191     expect(request.getContextPath())
192         .andReturn(contextPath);
193 
194     expect(request.getAttribute(REQUEST_DISPATCHER_REQUEST)).andReturn(null);
195 
196     replay(injector, binding, request);
197 
198     ServletDefinition servletDefinition = new ServletDefinition(mapping, Key.get(HttpServlet.class),
199         UriPatternType.get(UriPatternType.SERVLET, mapping), new HashMap<String, String>(), null);
200 
201     servletDefinition.init(null, injector, Sets.<HttpServlet>newIdentityHashSet());
202     servletDefinition.doService(request, response);
203 
204     assertTrue("Servlet did not run!", run[0]);
205 
206     verify(injector, binding, request);
207   }
208 
209   // Data-driven test.
testPathInfoWithRegexMatching()210   public final void testPathInfoWithRegexMatching() throws IOException, ServletException {
211     // first a mapping of /*
212     pathInfoWithRegexMatching("/path/index.html", "/path", "/(.)*", "/index.html", "");
213     pathInfoWithRegexMatching("/path//hulaboo///index.html", "/path", "/(.)*",
214         "/hulaboo/index.html", "");
215     pathInfoWithRegexMatching("/path/", "/path", "/(.)*", "/", "");
216     pathInfoWithRegexMatching("/path////////", "/path", "/(.)*", "/", "");
217 
218     // a servlet mapping of /thing/*
219     pathInfoWithRegexMatching("/path/thing////////", "/path", "/thing/(.)*", "/", "/thing");
220     pathInfoWithRegexMatching("/path/thing/stuff", "/path", "/thing/(.)*", "/stuff", "/thing");
221     pathInfoWithRegexMatching("/path/thing/stuff.html", "/path", "/thing/(.)*", "/stuff.html",
222         "/thing");
223     pathInfoWithRegexMatching("/path/thing", "/path", "/thing/(.)*", null, "/thing");
224 
225     // *.xx style mapping
226     pathInfoWithRegexMatching("/path/thing.thing", "/path", ".*\\.thing", null, "/thing.thing");
227     pathInfoWithRegexMatching("/path///h.thing", "/path", ".*\\.thing", null, "/h.thing");
228     pathInfoWithRegexMatching("/path///...//h.thing", "/path", ".*\\.thing", null,
229         "/.../h.thing");
230     pathInfoWithRegexMatching("/path/my/h.thing", "/path", ".*\\.thing", null, "/my/h.thing");
231 
232     // path
233     pathInfoWithRegexMatching("/path/test.com/com.test.MyServletModule", "", "/path/[^/]+/(.*)",
234         "com.test.MyServletModule", "/path/test.com/com.test.MyServletModule");
235 
236     // Encoded URLs
237     pathInfoWithRegexMatching("/path/index%2B.html", "/path", "/(.)*", "/index+.html", "");
238     pathInfoWithRegexMatching("/path/a%20file%20with%20spaces%20in%20name.html", "/path", "/(.)*", "/a file with spaces in name.html", "");
239     pathInfoWithRegexMatching("/path/Tam%C3%A1s%20nem%20m%C3%A1s.html", "/path", "/(.)*", "/Tamás nem más.html", "");
240   }
241 
pathInfoWithRegexMatching(final String requestUri, final String contextPath, String mapping, final String expectedPathInfo, final String servletPath)242   public final void pathInfoWithRegexMatching(final String requestUri, final String contextPath,
243       String mapping, final String expectedPathInfo, final String servletPath)
244       throws IOException, ServletException {
245 
246     Injector injector = createMock(Injector.class);
247     Binding binding = createMock(Binding.class);
248     HttpServletRequest request = createMock(HttpServletRequest.class);
249     HttpServletResponse response = createMock(HttpServletResponse.class);
250 
251     expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject()))
252         .andReturn(true);
253     expect(injector.getBinding(Key.get(HttpServlet.class)))
254         .andReturn(binding);
255 
256     final boolean[] run = new boolean[1];
257     //get an instance of this servlet
258     expect(injector.getInstance(Key.get(HttpServlet.class)))
259         .andReturn(new HttpServlet() {
260 
261           @Override
262           protected void service(HttpServletRequest servletRequest,
263               HttpServletResponse httpServletResponse) throws ServletException, IOException {
264 
265             final String path = servletRequest.getPathInfo();
266 
267             if (null == expectedPathInfo) {
268               assertNull(String.format("expected [%s] but was [%s]", expectedPathInfo, path),
269                   path);
270             }
271             else {
272               assertEquals(String.format("expected [%s] but was [%s]", expectedPathInfo, path),
273                   expectedPathInfo, path);
274             }
275 
276             //assert memoizer
277             //noinspection StringEquality
278             assertSame("memo field did not work", path, servletRequest.getPathInfo());
279 
280             run[0] = true;
281           }
282         });
283 
284     expect(request.getRequestURI())
285         .andReturn(requestUri);
286 
287     expect(request.getServletPath())
288         .andReturn(servletPath)
289         .anyTimes();
290 
291     expect(request.getContextPath())
292         .andReturn(contextPath);
293 
294     expect(request.getAttribute(REQUEST_DISPATCHER_REQUEST)).andReturn(null);
295 
296     replay(injector, binding, request);
297 
298     ServletDefinition servletDefinition = new ServletDefinition(mapping, Key.get(HttpServlet.class),
299         UriPatternType.get(UriPatternType.REGEX, mapping), new HashMap<String, String>(), null);
300 
301     servletDefinition.init(null, injector, Sets.<HttpServlet>newIdentityHashSet());
302     servletDefinition.doService(request, response);
303 
304     assertTrue("Servlet did not run!", run[0]);
305 
306     verify(injector, binding, request);
307   }
308 }
309