Home | History | Annotate | Download | only in servlet
      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.
     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 
     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.
    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", "/*", "/Tams nem ms.html", "");
    140   }
    141 
    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.
    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", "/(.)*", "/Tams nem ms.html", "");
    240   }
    241 
    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