• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (C) 2011 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 org.easymock.EasyMock.createControl;
20 import static org.easymock.EasyMock.expect;
21 
22 import com.google.inject.Guice;
23 import com.google.inject.Inject;
24 import com.google.inject.Injector;
25 import com.google.inject.Key;
26 import com.google.inject.Scopes;
27 import com.google.inject.name.Named;
28 import com.google.inject.name.Names;
29 
30 import junit.framework.TestCase;
31 
32 import org.easymock.IMocksControl;
33 
34 import java.io.IOException;
35 
36 import javax.servlet.FilterChain;
37 import javax.servlet.FilterConfig;
38 import javax.servlet.ServletContext;
39 import javax.servlet.ServletException;
40 import javax.servlet.ServletRequest;
41 import javax.servlet.ServletResponse;
42 import javax.servlet.http.HttpServlet;
43 import javax.servlet.http.HttpServletRequest;
44 import javax.servlet.http.HttpServletResponse;
45 
46 /** Tests to make sure that servlets with a context path are handled right. */
47 public class ContextPathTest extends TestCase {
48 
49   @Inject @Named("foo")
50   private TestServlet fooServlet;
51 
52   @Inject @Named("bar")
53   private TestServlet barServlet;
54 
55   private IMocksControl globalControl;
56   private Injector injector;
57   private ServletContext servletContext;
58   private FilterConfig filterConfig;
59   private GuiceFilter guiceFilter;
60 
61   @Override
setUp()62   public final void setUp() throws Exception {
63     injector = Guice.createInjector(new ServletModule() {
64       @Override
65       protected void configureServlets() {
66         bind(TestServlet.class).annotatedWith(Names.named("foo"))
67             .to(TestServlet.class).in(Scopes.SINGLETON);
68         bind(TestServlet.class).annotatedWith(Names.named("bar"))
69             .to(TestServlet.class).in(Scopes.SINGLETON);
70         serve("/foo/*").with(Key.get(TestServlet.class, Names.named("foo")));
71         serve("/bar/*").with(Key.get(TestServlet.class, Names.named("bar")));
72         // TODO: add a filter(..) call and validate it is correct
73       }
74     });
75     injector.injectMembers(this);
76 
77     assertNotNull(fooServlet);
78     assertNotNull(barServlet);
79     assertNotSame(fooServlet, barServlet);
80 
81     globalControl = createControl();
82     servletContext = globalControl.createMock(ServletContext.class);
83     filterConfig = globalControl.createMock(FilterConfig.class);
84 
85     expect(servletContext.getAttribute(GuiceServletContextListener.INJECTOR_NAME))
86         .andReturn(injector).anyTimes();
87     expect(filterConfig.getServletContext()).andReturn(servletContext).anyTimes();
88 
89     globalControl.replay();
90 
91     guiceFilter = new GuiceFilter();
92     guiceFilter.init(filterConfig);
93   }
94 
95   @Override
tearDown()96   public final void tearDown() {
97     assertNotNull(fooServlet);
98     assertNotNull(barServlet);
99 
100     fooServlet = null;
101     barServlet = null;
102 
103     guiceFilter.destroy();
104     guiceFilter = null;
105 
106     injector = null;
107 
108     filterConfig = null;
109     servletContext = null;
110 
111     globalControl.verify();
112   }
113 
testSimple()114   public void testSimple() throws Exception {
115     IMocksControl testControl = createControl();
116     TestFilterChain testFilterChain = new TestFilterChain();
117     HttpServletRequest req = testControl.createMock(HttpServletRequest.class);
118     HttpServletResponse res = testControl.createMock(HttpServletResponse.class);
119 
120     expect(req.getMethod()).andReturn("GET").anyTimes();
121     expect(req.getRequestURI()).andReturn("/bar/foo").anyTimes();
122     expect(req.getServletPath()).andReturn("/bar/foo").anyTimes();
123     expect(req.getContextPath()).andReturn("").anyTimes();
124 
125     testControl.replay();
126 
127     guiceFilter.doFilter(req, res, testFilterChain);
128 
129     assertFalse(testFilterChain.isTriggered());
130     assertFalse(fooServlet.isTriggered());
131     assertTrue(barServlet.isTriggered());
132 
133     testControl.verify();
134   }
135 
136   //
137   // each of the following "runTest" calls takes three path parameters:
138   //
139   // The value of "getRequestURI()"
140   // The value of "getServletPath()"
141   // The value of "getContextPath()"
142   //
143   // these values have been captured using a filter in Apache Tomcat 6.0.32
144   // and are used for real-world values that a servlet container would send into
145   // the GuiceFilter.
146   //
147   // the remaining three booleans are:
148   //
149   // True if the request gets passed down the filter chain
150   // True if the request hits the "foo" servlet
151   // True if the request hits the "bar" sevlet
152   //
153   // After adjusting the request URI for the web app deployment location, all
154   // calls
155   // should always produce the same result.
156   //
157 
158   // ROOT Web app, using Tomcat default servlet
testRootDefault()159   public void testRootDefault() throws Exception {
160     // fetching /. Should go up the filter chain (only mappings on /foo/* and /bar/*).
161     runTest("/", "/", "", true, false, false);
162     // fetching /bar/. Should hit the bar servlet
163     runTest("/bar/", "/bar/", "", false, false, true);
164     // fetching /foo/xxx. Should hit the foo servlet
165     runTest("/foo/xxx", "/foo/xxx", "", false, true, false);
166     // fetching /xxx. Should go up the chain
167     runTest("/xxx", "/xxx", "", true, false, false);
168   }
169 
170   // ROOT Web app, using explicit backing servlet mounted at /*
testRootExplicit()171   public void testRootExplicit() throws Exception {
172     // fetching /. Should go up the filter chain (only mappings on /foo/* and /bar/*).
173     runTest("/", "", "", true, false, false);
174     // fetching /bar/. Should hit the bar servlet
175     runTest("/bar/", "", "", false, false, true);
176     // fetching /foo/xxx. Should hit the foo servlet
177     runTest("/foo/xxx", "", "", false, true, false);
178     // fetching /xxx. Should go up the chain
179     runTest("/xxx", "", "", true, false, false);
180   }
181 
182   // ROOT Web app, using two backing servlets, mounted at /bar/* and /foo/*
testRootSpecific()183   public void testRootSpecific() throws Exception {
184     // fetching /. Should go up the filter chain (only mappings on /foo/* and /bar/*).
185     runTest("/", "/", "", true, false, false);
186     // fetching /bar/. Should hit the bar servlet
187     runTest("/bar/", "/bar", "", false, false, true);
188     // fetching /foo/xxx. Should hit the foo servlet
189     runTest("/foo/xxx", "/foo", "", false, true, false);
190     // fetching /xxx. Should go up the chain
191     runTest("/xxx", "/xxx", "", true, false, false);
192   }
193 
194   // Web app located at /webtest, using Tomcat default servlet
testWebtestDefault()195   public void testWebtestDefault() throws Exception {
196     // fetching /. Should go up the filter chain (only mappings on /foo/* and /bar/*).
197     runTest("/webtest/", "/", "/webtest", true, false, false);
198     // fetching /bar/. Should hit the bar servlet
199     runTest("/webtest/bar/", "/bar/", "/webtest", false, false, true);
200     // fetching /foo/xxx. Should hit the foo servlet
201     runTest("/webtest/foo/xxx", "/foo/xxx", "/webtest", false, true, false);
202     // fetching /xxx. Should go up the chain
203     runTest("/webtest/xxx", "/xxx", "/webtest", true, false, false);
204   }
205 
206   // Web app located at /webtest, using explicit backing servlet mounted at /*
testWebtestExplicit()207   public void testWebtestExplicit() throws Exception {
208     // fetching /. Should go up the filter chain (only mappings on /foo/* and /bar/*).
209     runTest("/webtest/", "", "/webtest", true, false, false);
210     // fetching /bar/. Should hit the bar servlet
211     runTest("/webtest/bar/", "", "/webtest", false, false, true);
212     // fetching /foo/xxx. Should hit the foo servlet
213     runTest("/webtest/foo/xxx", "", "/webtest", false, true, false);
214     // fetching /xxx. Should go up the chain
215     runTest("/webtest/xxx", "", "/webtest", true, false, false);
216   }
217 
218   // Web app located at /webtest, using two backing servlets, mounted at /bar/*
219   // and /foo/*
testWebtestSpecific()220   public void testWebtestSpecific() throws Exception {
221     // fetching /. Should go up the filter chain (only mappings on /foo/* and
222     // /bar/*).
223     runTest("/webtest/", "/", "/webtest", true, false, false);
224     // fetching /bar/. Should hit the bar servlet
225     runTest("/webtest/bar/", "/bar", "/webtest", false, false, true);
226     // fetching /foo/xxx. Should hit the foo servlet
227     runTest("/webtest/foo/xxx", "/foo", "/webtest", false, true, false);
228     // fetching /xxx. Should go up the chain
229     runTest("/webtest/xxx", "/xxx", "/webtest", true, false, false);
230   }
231 
runTest(final String requestURI, final String servletPath, final String contextPath, final boolean filterResult, final boolean fooResult, final boolean barResult)232   private void runTest(final String requestURI, final String servletPath, final String contextPath,
233       final boolean filterResult, final boolean fooResult, final boolean barResult)
234       throws Exception {
235     IMocksControl testControl = createControl();
236 
237     barServlet.clear();
238     fooServlet.clear();
239 
240     TestFilterChain testFilterChain = new TestFilterChain();
241     HttpServletRequest req = testControl.createMock(HttpServletRequest.class);
242     HttpServletResponse res = testControl.createMock(HttpServletResponse.class);
243 
244     expect(req.getMethod()).andReturn("GET").anyTimes();
245     expect(req.getRequestURI()).andReturn(requestURI).anyTimes();
246     expect(req.getServletPath()).andReturn(servletPath).anyTimes();
247     expect(req.getContextPath()).andReturn(contextPath).anyTimes();
248 
249     testControl.replay();
250 
251     guiceFilter.doFilter(req, res, testFilterChain);
252 
253     assertEquals(filterResult, testFilterChain.isTriggered());
254     assertEquals(fooResult, fooServlet.isTriggered());
255     assertEquals(barResult, barServlet.isTriggered());
256 
257     testControl.verify();
258   }
259 
260   public static class TestServlet extends HttpServlet {
261     private boolean triggered = false;
262 
263     @Override
doGet(HttpServletRequest req, HttpServletResponse resp)264     public void doGet(HttpServletRequest req, HttpServletResponse resp) {
265       triggered = true;
266     }
267 
isTriggered()268     public boolean isTriggered() {
269       return triggered;
270     }
271 
clear()272     public void clear() {
273       triggered = false;
274     }
275   }
276 
277   public static class TestFilterChain implements FilterChain {
278     private boolean triggered = false;
279 
doFilter(ServletRequest request, ServletResponse response)280     public void doFilter(ServletRequest request, ServletResponse response) throws IOException,
281         ServletException {
282       triggered = true;
283     }
284 
isTriggered()285     public boolean isTriggered() {
286       return triggered;
287     }
288 
clear()289     public void clear() {
290       triggered = false;
291     }
292   }
293 }
294